From patchwork Sun Jul 1 10:34:49 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: =?utf-8?q?Pali_Roh=C3=A1r?= X-Patchwork-Id: 168376 X-Patchwork-Delegate: agust@denx.de Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from theia.denx.de (theia.denx.de [85.214.87.163]) by ozlabs.org (Postfix) with ESMTP id CE4C72C01E0 for ; Sun, 1 Jul 2012 20:35:02 +1000 (EST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 556172809B; Sun, 1 Jul 2012 12:35:01 +0200 (CEST) X-Virus-Scanned: Debian amavisd-new at theia.denx.de Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id JOvauvsPXa7I; Sun, 1 Jul 2012 12:35:01 +0200 (CEST) Received: from theia.denx.de (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 2D1D42808D; Sun, 1 Jul 2012 12:34:59 +0200 (CEST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 34C1228082 for ; Sun, 1 Jul 2012 12:34:57 +0200 (CEST) X-Virus-Scanned: Debian amavisd-new at theia.denx.de Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id q8kVfcewJrAd for ; Sun, 1 Jul 2012 12:34:56 +0200 (CEST) X-policyd-weight: NOT_IN_SBL_XBL_SPAMHAUS=-1.5 NOT_IN_SPAMCOP=-1.5 NOT_IN_BL_NJABL=-1.5 (only DNSBL check requested) Received: from mail-bk0-f44.google.com (mail-bk0-f44.google.com [209.85.214.44]) by theia.denx.de (Postfix) with ESMTPS id 142562808D for ; Sun, 1 Jul 2012 12:34:54 +0200 (CEST) Received: by bkty8 with SMTP id y8so3828687bkt.3 for ; Sun, 01 Jul 2012 03:34:54 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:subject:date:message-id:user-agent:mime-version :content-type:content-transfer-encoding; bh=sOpcfVLMaXRctWQ3gtQ3KLnHXlLPefAdobIVOv53Fws=; b=FTLPxuX4IW43BBTjt9k0ojzMFWKkaFhibVBANqU43LRFkrTWxrKWb/fAjpheWW60IJ P6R1VEM1VI6gaQHzQWY8jXYI1oqZHRL0bJnV2MmTZMt6mMz6QYo1mv5zNHI0G9LGojDp nQdFHFKJbreSUjSEhA8/DT06BidCvXqC5lU1FL6hsXbtG9Y8zYjC7seg05vtZBXgKWHg r0ermCUCwwaTl+LH1A0AZzON6dsH2eRBouU4R9HQBuM3JYZlL0v3/k5hALMx51MFgi2m ZzTAaQ/qh+F8Ky2Bt8nZBsvV51h4BnSDFr+fAKQOxRQ7ytK2QB7+sKNfJ6PzwO84ocqf kGBQ== Received: by 10.205.133.19 with SMTP id hw19mr5001790bkc.0.1341138893951; Sun, 01 Jul 2012 03:34:53 -0700 (PDT) Received: from pali-elitebook.localnet (ip-88-212-34-237.antik.sk. [88.212.34.237]) by mx.google.com with ESMTPS id e20sm9214017bkv.10.2012.07.01.03.34.52 (version=TLSv1/SSLv3 cipher=OTHER); Sun, 01 Jul 2012 03:34:53 -0700 (PDT) From: Pali =?ISO-8859-1?Q?Roh=E1r?= To: Anatolij Gustschin , u-boot@lists.denx.de Date: Sun, 01 Jul 2012 12:34:49 +0200 Message-ID: <3330533.yzEXzbXSKO@pali> User-Agent: KMail/4.8.4 (Linux/3.2.0-26-generic; KDE/4.8.4; x86_64; ; ) MIME-Version: 1.0 Subject: [U-Boot] [PATCH] cfb_console: Add support for some ANSI terminal escape codes X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.11 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: u-boot-bounces@lists.denx.de Errors-To: u-boot-bounces@lists.denx.de Hello, I'm sending new patch which add support for ANSI terminal in cfb_console driver. This patch comes from RX-51 patch series, but more cfb patches were commited to u-boot git. This is last patch for cfb driver, so I'm sending it separatly. Changes from last version: this patch is rebased on top of u-boot master and has fixed comment style problems. diff --git a/README b/README index 67dc444..5528004 100644 --- a/README +++ b/README @@ -621,6 +621,9 @@ The following options need to be configured: additional board info beside the logo + When CONFIG_CFB_CONSOLE_ANSI is defined, console will have + ANSI terminal support. Needed for CONFIG_CMDLINE_EDITING. + When CONFIG_CFB_CONSOLE is defined, video console is default i/o. Serial console can be forced with environment 'console=serial'. diff --git a/drivers/video/cfb_console.c b/drivers/video/cfb_console.c index 92fa77d..8ead72c 100644 --- a/drivers/video/cfb_console.c +++ b/drivers/video/cfb_console.c @@ -381,6 +381,11 @@ static u32 eorx, fgx, bgx; /* color pats */ static int cfb_do_flush_cache; +static char ansi_buf[10] = { 0, }; +static int ansi_buf_size; +static int ansi_colors_need_revert; +static int ansi_cursor_hidden; + static const int video_font_draw_table8[] = { 0x00000000, 0x000000ff, 0x0000ff00, 0x0000ffff, 0x00ff0000, 0x00ff00ff, 0x00ffff00, 0x00ffffff, @@ -608,6 +613,14 @@ static void video_putchar(int xx, int yy, unsigned char c) video_drawchars(xx, yy + video_logo_height, &c, 1); } +static void console_swap_colors(void) +{ + eorx = fgx; + fgx = bgx; + bgx = eorx; + eorx = fgx ^ bgx; +} + #if defined(CONFIG_CONSOLE_CURSOR) || defined(CONFIG_VIDEO_SW_CURSOR) static void video_set_cursor(void) { @@ -691,6 +704,21 @@ static void memcpyl(int *d, int *s, int c) } #endif +static void console_clear(void) +{ +#ifdef VIDEO_HW_RECTFILL + video_hw_rectfill(VIDEO_PIXEL_SIZE, /* bytes per pixel */ + 0, /* dest pos x */ + video_logo_height, /* dest pos y */ + VIDEO_VISIBLE_COLS, /* frame width */ + VIDEO_VISIBLE_ROWS, /* frame height */ + bgx /* fill color */ + ); +#else + memsetl(CONSOLE_ROW_FIRST, CONSOLE_SIZE, bgx); +#endif +} + static void console_clear_line(int line, int begin, int end) { #ifdef VIDEO_HW_RECTFILL @@ -764,9 +792,54 @@ static void console_back(void) } } -static void console_newline(void) +static void console_cursor_fix(void) +{ + if (console_row < 0) + console_row = 0; + if (console_row >= CONSOLE_ROWS) + console_row = CONSOLE_ROWS-1; + if (console_col < 0) + console_col = 0; + if (console_col >= CONSOLE_COLS) + console_col = CONSOLE_COLS-1; +} + +static void console_cursor_up(int n) +{ + console_row -= n; + console_cursor_fix(); +} + +static void console_cursor_down(int n) +{ + console_row += n; + console_cursor_fix(); +} + +static void console_cursor_left(int n) +{ + console_col -= n; + console_cursor_fix(); +} + +static void console_cursor_right(int n) +{ + console_col += n; + console_cursor_fix(); +} + +static void console_cursor_set_position(int row, int col) { - console_row++; + if (console_row != -1) + console_row = row; + if (console_col != -1) + console_col = col; + console_cursor_fix(); +} + +static void console_newline(int n) +{ + console_row += n; console_col = 0; /* Check if we need to scroll the terminal */ @@ -775,20 +848,28 @@ static void console_newline(void) console_scrollup(); /* Decrement row number */ - console_row--; + console_row = CONSOLE_ROWS-1; } } +static void console_previewsline(int n) +{ + /* FIXME: also scroll terminal ? */ + console_row -= n; + console_cursor_fix(); +} + static void console_cr(void) { console_col = 0; } -void video_putc(const char c) +static void parse_putc(const char c) { static int nl = 1; - CURSOR_OFF; + if (!ansi_cursor_hidden) + CURSOR_OFF; switch (c) { case 13: /* back to first column */ @@ -797,7 +878,7 @@ void video_putc(const char c) case '\n': /* next line */ if (console_col || (!console_col && nl)) - console_newline(); + console_newline(1); nl = 1; break; @@ -806,7 +887,7 @@ void video_putc(const char c) console_col &= ~0x0007; if (console_col >= CONSOLE_COLS) - console_newline(); + console_newline(1); break; case 8: /* backspace */ @@ -823,11 +904,225 @@ void video_putc(const char c) /* check for newline */ if (console_col >= CONSOLE_COLS) { - console_newline(); + console_newline(1); nl = 0; } } - CURSOR_SET; + + if (!ansi_cursor_hidden) + CURSOR_SET; +} + +void video_putc(const char c) +{ +#ifdef CONFIG_CFB_CONSOLE_ANSI + int i; + + if (c == 27) { + for (i = 0; i < ansi_buf_size; ++i) + parse_putc(ansi_buf[i]); + ansi_buf[0] = 27; + ansi_buf_size = 1; + return; + } + + if (ansi_buf_size > 0) { + /* + * 0 - ESC + * 1 - [ + * 2 - num1 + * 3 - .. + * 4 - ; + * 5 - num2 + * 6 - .. + * - cchar + */ + int next = 0; + + int flush = 0; + int fail = 0; + + int num1 = 0; + int num2 = 0; + int cchar = 0; + + ansi_buf[ansi_buf_size++] = c; + + if (ansi_buf_size >= sizeof(ansi_buf)) + fail = 1; + + for (i = 0; i < ansi_buf_size; ++i) { + if (fail) + break; + + switch (next) { + case 0: + if (ansi_buf[i] == 27) + next = 1; + else + fail = 1; + break; + + case 1: + if (ansi_buf[i] == '[') + next = 2; + else + fail = 1; + break; + + case 2: + if (ansi_buf[i] >= '0' && ansi_buf[i] <= '9') { + num1 = ansi_buf[i]-'0'; + next = 3; + } else if (ansi_buf[i] != '?') { + --i; + num1 = 1; + next = 4; + } + break; + + case 3: + if (ansi_buf[i] >= '0' && ansi_buf[i] <= '9') { + num1 *= 10; + num1 += ansi_buf[i]-'0'; + } else { + --i; + next = 4; + } + break; + + case 4: + if (ansi_buf[i] != ';') { + --i; + next = 7; + } else + next = 5; + break; + + case 5: + if (ansi_buf[i] >= '0' && ansi_buf[i] <= '9') { + num2 = ansi_buf[i]-'0'; + next = 6; + } else + fail = 1; + break; + + case 6: + if (ansi_buf[i] >= '0' && ansi_buf[i] <= '9') { + num2 *= 10; + num2 += ansi_buf[i]-'0'; + } else { + --i; + next = 7; + } + break; + + case 7: + if ((ansi_buf[i] >= 'A' && ansi_buf[i] <= 'H') + || ansi_buf[i] == 'J' + || ansi_buf[i] == 'K' + || ansi_buf[i] == 'h' + || ansi_buf[i] == 'l' + || ansi_buf[i] == 'm') { + cchar = ansi_buf[i]; + flush = 1; + } else + fail = 1; + break; + } + } + + if (fail) { + for (i = 0; i < ansi_buf_size; ++i) + parse_putc(ansi_buf[i]); + ansi_buf_size = 0; + return; + } + + if (flush) { + if (!ansi_cursor_hidden) + CURSOR_OFF; + ansi_buf_size = 0; + switch (cchar) { + case 'A': + /* move cursor num1 rows up */ + console_cursor_up(num1); + break; + case 'B': + /* move cursor num1 rows down */ + console_cursor_down(num1); + break; + case 'C': + /* move cursor num1 columns forward */ + console_cursor_right(num1); + break; + case 'D': + /* move cursor num1 columns back */ + console_cursor_left(num1); + break; + case 'E': + /* move cursor num1 rows up at begin of row */ + console_previewsline(num1); + break; + case 'F': + /* move cursor num1 rows down at begin of row */ + console_newline(num1); + break; + case 'G': + /* move cursor to column num1 */ + console_cursor_set_position(-1, num1-1); + break; + case 'H': + /* move cursor to row num1, column num2 */ + console_cursor_set_position(num1-1, num2-1); + break; + case 'J': + /* clear console and move cursor to 0, 0 */ + console_clear(); + console_cursor_set_position(0, 0); + break; + case 'K': + /* clear line */ + if (num1 == 0) + console_clear_line(console_row, + console_col, + CONSOLE_COLS-1); + else if (num1 == 1) + console_clear_line(console_row, + 0, console_col); + else + console_clear_line(console_row, + 0, CONSOLE_COLS-1); + break; + case 'h': + ansi_cursor_hidden = 0; + break; + case 'l': + ansi_cursor_hidden = 1; + break; + case 'm': + if (num1 == 0) { /* reset swapped colors */ + if (ansi_colors_need_revert) { + console_swap_colors(); + ansi_colors_need_revert = 0; + } + } else if (num1 == 7) { /* once swap colors */ + if (!ansi_colors_need_revert) { + console_swap_colors(); + ansi_colors_need_revert = 1; + } + } + break; + } + if (!ansi_cursor_hidden) + CURSOR_SET; + } + } else { + parse_putc(c); + } +#else + parse_putc(c); +#endif } void video_puts(const char *s)