Message ID | 1335634011-9104-7-git-send-email-pali.rohar@gmail.com |
---|---|
State | Superseded |
Delegated to: | Anatolij Gustschin |
Headers | show |
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)
On Sunday 29 April 2012 00:19:03 Marek Vasut wrote: > > + > > + 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. > Yes, I all patches except first is OK for checkpatch. It show no errors and no warnings.
Dear Pali =?ISO-8859-1?Q?Roh=E1r?=, In message <3284404.3VX1zBQJtc@pali> you wrote: > > > > + 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. > > Yes, I all patches except first is OK for checkpatch. It show no > errors and no warnings. Nevertheless, this violates the CodingStyle (see entry for multiline comments); please fix globally. Best regards, Wolfgang Denk
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 + */ + 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)
* 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(-)