From 65c7485dfdcbebe57194d8432439125a8c7ed797 Mon Sep 17 00:00:00 2001 From: hpa Date: Tue, 30 Nov 2004 20:44:18 +0000 Subject: [PATCH] A version of ansicon_write which compiles, and just make actually work --- com32/lib/Makefile | 1 + com32/lib/sys/ansicon_write.c | 325 +++++++++++++++++++++++++++++++++++++++--- 2 files changed, 308 insertions(+), 18 deletions(-) diff --git a/com32/lib/Makefile b/com32/lib/Makefile index 0503459..acc385f 100644 --- a/com32/lib/Makefile +++ b/com32/lib/Makefile @@ -25,6 +25,7 @@ LIBOBJS = abort.o atexit.o atoi.o atol.o atoll.o calloc.o creat.o \ sys/rawcon_read.o sys/rawcon_write.o \ sys/err_read.o sys/err_write.o \ sys/null_read.o sys/null_write.o \ + sys/ansicon_write.o all: libcom32.a diff --git a/com32/lib/sys/ansicon_write.c b/com32/lib/sys/ansicon_write.c index 786464b..59eec01 100644 --- a/com32/lib/sys/ansicon_write.c +++ b/com32/lib/sys/ansicon_write.c @@ -57,27 +57,314 @@ struct curxy { #define BIOS_PAGE (*(uint8_t *)0x462) #define BIOS_FB (*(uint16_t *)0x44E) /* Current page fb address */ +enum ansi_state { + st_init, /* Normal (no ESC seen) */ + st_esc, /* ESC seen */ + st_empty, /* CSI seen, empty position */ + st_digits, /* CSI seen, digits seen in this position */ +}; + +#define MAX_PARMS 16 + static struct { - uint8_t attr; /* Current display attribute */ + int attr; /* Current display attribute */ + int intensity; + int underline; + int blink; + int reverse; + int fg; + int bg; + struct curxy saved_xy; + enum ansi_state state; + int nparms; /* Number of parameters seen */ + int parms[MAX_PARMS]; } st = { - 0x0007, /* Grey on black */ + .attr = 0x07, /* Grey on black */ + .intensity = 1, + .underline = 0, + .blink = 0, + .reverse = 0, + .fg = 7, + .bg = 0, + .saved_xy = { 0, 0 }, + .state = st_init, + .nparms = 0, + .parms = { 0, }, }; -static void ansicon_putchar(int ch) +/* Erase a region of the screen */ +static void ansicon_erase(int x0, int y0, int x1, int y1) { static com32sys_t ireg; - int rows = BIOS_ROWS ? BIOS_ROWS+1 : 25; - int cols = BIOS_COLS; - struct curxy xy = BIOS_CURXY[BIOS_PAGE]; - ireg.eax.b[1] = 0x09; - ireg.eax.b[0] = ch; - ireg.ebx.b[1] = BIOS_PAGE; - ireg.ebx.b[0] = st.attr; - ireg.ecx.w[0] = 1; + ireg.eax.w[0] = 0x0600; /* Clear window */ + ireg.eax.b[1] = st.attr; /* Fill with current attribute */ + ireg.ecx.b[0] = x0; + ireg.ecx.b[1] = y0; + ireg.edx.b[0] = x1; + ireg.edx.b[1] = y1; __intcall(0x10, &ireg, NULL); +} + +static void ansicon_putchar(int ch) +{ + static com32sys_t ireg; + const int rows = BIOS_ROWS ? BIOS_ROWS+1 : 25; + const int cols = BIOS_COLS; + const int page = BIOS_PAGE; + struct curxy xy = BIOS_CURXY[page]; + int again; + + do { + again = 0; + + switch ( st.state ) { + case st_init: + switch ( ch ) { + case '\a': + /* Ignore beep */ + break; + case '\b': + if ( xy.y > 0 ) xy.y--; + break; + case '\t': + { + int nsp = 8 - (xy.y & 7); + while ( nsp-- ) + ansicon_putchar(' '); + } + return; /* Cursor already updated */ + case '\n': + case '\v': + case '\f': + xy.y++; + break; + case '\r': + xy.x = 0; + break; + case '\0': + case 127: + /* Ignore null or delete */ + break; + case 27: + st.state = st_esc; + break; + default: + /* Print character */ + ireg.eax.b[1] = 0x09; + ireg.eax.b[0] = ch; + ireg.ebx.b[1] = page; + ireg.ebx.b[0] = st.attr; + ireg.ecx.w[0] = 1; + __intcall(0x10, &ireg, NULL); + xy.x++; + break; + } + break; + + case st_esc: + if ( ch == '[' ) { + int i; + st.state = st_empty; + st.nparms = 0; + for ( i = 0 ; i < MAX_PARMS ; i++ ) + st.parms[i] = 1; /* 1 is the default, not 0 */ + } else { + st.state = st_init; + again = 1; + } + break; + + case st_empty: + case st_digits: + switch ( ch ) { + case '0' ... '9': + if ( st.state == st_empty ) { + st.parms[st.nparms] = ch - '0'; + st.state = st_digits; + } else { + st.parms[st.nparms] = st.parms[st.nparms]*10 + (ch-'0'); + } + break; + case ';': + st.nparms++; + if ( st.nparms >= MAX_PARMS ) + st.nparms = MAX_PARMS-1; + st.state = st_empty; + break; + case 'A': + { + int y = xy.y - st.parms[0]; + xy.y = (y < 0) ? 0 : y; + } + break; + case 'B': + { + int y = xy.y + st.parms[0]; + xy.y = (y >= rows) ? rows-1 : y; + } + break; + case 'C': + { + int x = xy.x + st.parms[0]; + xy.x = (x >= cols) ? cols-1 : x; + } + break; + case 'D': + { + int x = xy.x - st.parms[0]; + xy.x = (x < 0) ? 0 : x; + } + break; + case 'E': + { + int y = xy.y + st.parms[0]; + xy.y = (y >= rows) ? rows-1 : y; + xy.x = 0; + } + break; + case 'F': + { + int y = xy.y - st.parms[0]; + xy.y = (y < 0) ? 0 : y; + xy.x = 0; + } + break; + case 'H': + case 'f': + { + int x = st.parms[0]; + int y = st.parms[1]; - xy.x++; + xy.x = (x >= cols) ? cols-1 : x; + xy.y = (y >= rows) ? rows-1 : y; + } + break; + case 'J': + { + if ( st.parms[0] == 2 ) { + ansicon_erase(0, 0, cols-1, rows-1); + } else { + ansicon_erase(xy.x, xy.y, cols-1, xy.y); + if ( xy.y < rows-1 ) + ansicon_erase(0, xy.y+1, cols-1, rows-1); + } + } + break; + case 'K': + { + if ( st.parms[0] == 2 ) + ansicon_erase(0, xy.y, cols-1, xy.y); + else + ansicon_erase(xy.x, xy.y, cols-1, xy.y); + } + break; + case 'm': + { + static const int ansi2pc[8] = { 0, 4, 2, 6, 1, 5, 3, 7 }; + + int i; + for ( i = 0 ; i < st.nparms ; i++ ) { + int a = st.parms[i]; + switch ( a ) { + case 0: + st.fg = 7; + st.bg = 7; + st.intensity = 1; + st.underline = 0; + st.blink = 0; + st.reverse = 0; + break; + case 1: + st.intensity = 2; + break; + case 2: + st.intensity = 0; + break; + case 4: + st.underline = 1; + break; + case 5: + st.blink = 1; + break; + case 7: + st.reverse = 1; + break; + case 21: + case 22: + st.intensity = 1; + break; + case 24: + st.underline = 0; + break; + case 25: + st.blink = 0; + break; + case 27: + st.reverse = 0; + break; + case 30 ... 37: + st.fg = ansi2pc[a-30]; + break; + case 38: + st.fg = 7; + st.underline = 1; + break; + case 39: + st.fg = 7; + st.underline = 0; + break; + case 40 ... 47: + st.bg = ansi2pc[a-40]; + break; + case 49: + st.bg = 7; + break; + default: + /* Do nothing */ + break; + } + } + + /* Turn into an attribute code */ + { + int bg = st.bg; + int fg; + + if ( st.underline ) + fg = 0x01; + else if ( st.intensity == 0 ) + fg = 0x08; + else + fg = st.fg; + + if ( st.reverse ) { + bg = fg & 0x07; + fg &= 0x08; + fg |= st.bg; + } + + if ( st.blink ) + bg ^= 0x08; + + if ( st.intensity == 2 ) + fg ^= 0x08; + + st.attr = (bg << 4) | fg; + } + } + break; + case 's': + st.saved_xy = xy; + break; + case 'u': + xy = st.saved_xy; + break; + } + } + } while ( again ); + + /* If we fell off the end of the screen, adjust */ if ( xy.x >= cols ) { xy.x = 0; xy.y++; @@ -91,13 +378,15 @@ static void ansicon_putchar(int ch) __intcall(0x10, &ireg, NULL); /* Scroll */ } } - + + /* Update cursor position */ ireg.eax.b[1] = 0x04; ireg.ebx.b[1] = BIOS_PAGE; - ireg.edx.b[1] = curxy.y; - ireg.edx.b[0] = curxy.x; - __intcall(0x10, &ireg, NULL); /* Update cursor position */ -} + ireg.edx.b[1] = xy.y; + ireg.edx.b[0] = xy.x; + __intcall(0x10, &ireg, NULL); +} + static ssize_t ansicon_write(struct file_info *fp, const void *buf, size_t count) { @@ -122,6 +411,6 @@ const struct output_dev dev_ansicon_w = { .dev_magic = __DEV_MAGIC, .flags = __DEV_TTY | __DEV_OUTPUT, .fileflags = O_WRONLY | O_CREAT | O_TRUNC | O_APPEND, - .write = __ansicon_write, + .write = ansicon_write, .close = NULL, }; -- 2.7.4