From: "Pali Rohár" <pali.rohar@gmail.com>
To: u-boot@lists.denx.de
Subject: [U-Boot] [PATCH] cfb_console: Add support for some ANSI terminal escape codes
Date: Sun, 01 Jul 2012 12:34:49 +0200 [thread overview]
Message-ID: <3330533.yzEXzbXSKO@pali> (raw)
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)
--
1.7.9.5
--
Pali Roh?r
pali.rohar@gmail.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 198 bytes
Desc: This is a digitally signed message part.
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20120701/03c8f22c/attachment.pgp>
next reply other threads:[~2012-07-01 10:34 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-07-01 10:34 Pali Rohár [this message]
2012-07-13 14:12 ` [U-Boot] [PATCH] cfb_console: Add support for some ANSI terminal escape codes Pali Rohár
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=3330533.yzEXzbXSKO@pali \
--to=pali.rohar@gmail.com \
--cc=u-boot@lists.denx.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.