[U-Boot] [PATCH v2 06/11] cfb_console: Add support for some ANSI terminal escape codes

Marek Vasut
2012-04-28T22:19:03Z

Dear Pali Roh?r,

> * This patch add support for move cursor and reverse colors
> via ANSI espace codes in cfb_console driver
> * ANSI escape codes can be enabled/disabled via CONFIG_CFB_CONSOLE_ANSI
>
> Signed-off-by: Pali Roh?r <pali.rohar@gmail.com>
> ---
> Changes since v1:
> - Added support ANSI code show/hide cursor
> - Added info to README
>
> Changes since original version:
> - Fixed commit message
>
> README | 3 +
> drivers/video/cfb_console.c | 234
> ++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 234
> insertions(+), 3 deletions(-)
>
> diff --git a/README b/README
> index 60ad9c2..4a610f7 100644
> --- a/README
> +++ b/README
> @@ -613,6 +613,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 43eb994..c9f9765 100644
> --- a/drivers/video/cfb_console.c
> +++ b/drivers/video/cfb_console.c
> @@ -377,6 +377,11 @@ static int console_row; /* cursor row */
>
> static u32 eorx, fgx, bgx; /* color pats */
>
> +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,
> @@ -602,6 +607,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)
> {
> @@ -843,11 +856,12 @@ 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 */
> @@ -883,7 +897,221 @@ void video_putc(const char c)
> 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 - ..
> + 7 - cchar

wrong comment ... did you even run these patches through checkpatch? Run them
and resubmit please, I'm ending my review here.

> + */
> + 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)