In preparation for the VESA console needing to fall back to text mode...
\
sys/xserial_write.o \
\
+ sys/ansi.o \
+ \
sys/ansicon_write.o sys/ansiserial_write.o \
\
sys/vesacon_write.o sys/vesaserial_write.o \
--- /dev/null
+/* ----------------------------------------------------------------------- *
+ *
+ * Copyright 2004-2006 H. Peter Anvin - All Rights Reserved
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall
+ * be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * ansi.c
+ *
+ * ANSI character code engine
+ */
+
+#include <string.h>
+#include <colortbl.h>
+#include "ansi.h"
+
+static const struct term_state default_state =
+{
+ .xy = { 0, 0 },
+ .cindex = 0, /* First color table entry */
+ .vtgraphics = 0,
+ .intensity = 1,
+ .underline = 0,
+ .blink = 0,
+ .reverse = 0,
+ .fg = 7,
+ .bg = 0,
+ .autocr = 0,
+ .saved_xy = { 0, 0 },
+ .cursor_type = 0x0607,
+ .state = st_init,
+ .pvt = 0,
+ .nparms = 0,
+ .xy = { 0, 0 },
+};
+
+/* DEC VT graphics to codepage 437 table (characters 0x60-0x7F only) */
+static const char decvt_to_cp437[] =
+ {
+ 0004, 0261, 0007, 0007, 0007, 0007, 0370, 0361,
+ 0007, 0007, 0331, 0277, 0332, 0300, 0305, 0304,
+ 0304, 0304, 0137, 0137, 0303, 0264, 0301, 0302,
+ 0263, 0363, 0362, 0343, 0330, 0234, 0007, 00
+ };
+
+void __ansi_init(const struct term_info *ti)
+{
+ memcpy(ti->ts, &default_state, sizeof default_state);
+}
+
+void __ansi_putchar(const struct term_info *ti, uint8_t ch)
+{
+ const struct ansi_ops *op = ti->op;
+ struct term_state *st = ti->ts;
+ const int rows = ti->rows;
+ const int cols = ti->cols;
+ struct curxy xy = st->xy;
+
+ switch ( st->state ) {
+ case st_init:
+ switch ( ch ) {
+ case 1:
+ st->state = st_soh;
+ break;
+ case '\b':
+ if ( xy.x > 0 ) xy.x--;
+ break;
+ case '\t':
+ {
+ int nsp = 8 - (xy.x & 7);
+ while ( nsp-- )
+ __ansi_putchar(ti, ' ');
+ }
+ return; /* Cursor already updated */
+ case '\n':
+ case '\v':
+ case '\f':
+ xy.y++;
+ if ( st->autocr )
+ xy.x = 0;
+ break;
+ case '\r':
+ xy.x = 0;
+ break;
+ case 127:
+ /* Ignore delete */
+ break;
+ case 14:
+ st->vtgraphics = 1;
+ break;
+ case 15:
+ st->vtgraphics = 0;
+ break;
+ case 27:
+ st->state = st_esc;
+ break;
+ default:
+ /* Print character */
+ if ( ch >= 32 ) {
+ if ( st->vtgraphics && (ch & 0xe0) == 0x60 )
+ ch = decvt_to_cp437[ch - 0x60];
+
+ op->write_char(xy.x, xy.y, ch, st);
+ xy.x++;
+ }
+ break;
+ }
+ break;
+
+ case st_esc:
+ switch ( ch ) {
+ case '%':
+ case '(':
+ case ')':
+ case '#':
+ /* Ignore this plus the subsequent character, allows
+ compatibility with Linux sequence to set charset */
+ break;
+ case '[':
+ st->state = st_csi;
+ st->nparms = st->pvt = 0;
+ memset(st->parms, 0, sizeof st->parms);
+ break;
+ case 'c':
+ /* Reset terminal */
+ memcpy(&st, &default_state, sizeof st);
+ op->erase(st, 0, 0, cols-1, rows-1);
+ xy.x = xy.y = 0;
+ st->state = st_init;
+ break;
+ default:
+ /* Ignore sequence */
+ st->state = st_init;
+ break;
+ }
+ break;
+
+ case st_csi:
+ {
+ int p0 = st->parms[0] ? st->parms[0] : 1;
+
+ if ( ch >= '0' && ch <= '9' ) {
+ st->parms[st->nparms] = st->parms[st->nparms]*10 + (ch-'0');
+ } else if ( ch == ';' ) {
+ st->nparms++;
+ if ( st->nparms >= ANSI_MAX_PARMS )
+ st->nparms = ANSI_MAX_PARMS-1;
+ break;
+ } else if ( ch == '?' ) {
+ st->pvt = 1;
+ } else {
+ switch ( ch ) {
+ case 'A':
+ {
+ int y = xy.y - p0;
+ xy.y = (y < 0) ? 0 : y;
+ }
+ break;
+ case 'B':
+ {
+ int y = xy.y + p0;
+ xy.y = (y >= rows) ? rows-1 : y;
+ }
+ break;
+ case 'C':
+ {
+ int x = xy.x + p0;
+ xy.x = (x >= cols) ? cols-1 : x;
+ }
+ break;
+ case 'D':
+ {
+ int x = xy.x - p0;
+ xy.x = (x < 0) ? 0 : x;
+ }
+ break;
+ case 'E':
+ {
+ int y = xy.y + p0;
+ xy.y = (y >= rows) ? rows-1 : y;
+ xy.x = 0;
+ }
+ break;
+ case 'F':
+ {
+ int y = xy.y - p0;
+ xy.y = (y < 0) ? 0 : y;
+ xy.x = 0;
+ }
+ break;
+ case 'G':
+ case '\'':
+ {
+ int x = st->parms[0] - 1;
+ xy.x = (x >= cols) ? cols-1 : (x < 0) ? 0 : x;
+ }
+ break;
+ case 'H':
+ case 'f':
+ {
+ int y = st->parms[0] - 1;
+ int x = st->parms[1] - 1;
+
+ xy.x = (x >= cols) ? cols-1 : (x < 0) ? 0 : x;
+ xy.y = (y >= rows) ? rows-1 : (y < 0) ? 0 : y;
+ }
+ break;
+ case 'J':
+ {
+ switch ( st->parms[0] ) {
+ case 0:
+ op->erase(st, xy.x, xy.y, cols-1, xy.y);
+ if ( xy.y < rows-1 )
+ op->erase(st, 0, xy.y+1, cols-1, rows-1);
+ break;
+
+ case 1:
+ if ( xy.y > 0 )
+ op->erase(st, 0, 0, cols-1, xy.y-1);
+ if ( xy.y > 0 )
+ op->erase(st, 0, xy.y, xy.x-1, xy.y);
+ break;
+
+ case 2:
+ op->erase(st, 0, 0, cols-1, rows-1);
+ break;
+
+ default:
+ /* Ignore */
+ break;
+ }
+ }
+ break;
+ case 'K':
+ {
+ switch ( st->parms[0] ) {
+ case 0:
+ op->erase(st, xy.x, xy.y, cols-1, xy.y);
+ break;
+
+ case 1:
+ if ( xy.x > 0 )
+ op->erase(st, 0, xy.y, xy.x-1, xy.y);
+ break;
+
+ case 2:
+ op->erase(st, 0, xy.y, cols-1, xy.y);
+ break;
+
+ default:
+ /* Ignore */
+ break;
+ }
+ }
+ break;
+ case 'h':
+ case 'l':
+ {
+ int set = (ch == 'h');
+ switch ( st->parms[0] ) {
+ case 20:
+ st->autocr = set;
+ break;
+ case 25:
+ op->showcursor(st, set);
+ break;
+ default:
+ /* Ignore */
+ break;
+ }
+ }
+ 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 = 0;
+ 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;
+ }
+ }
+ }
+ break;
+ case 's':
+ st->saved_xy = xy;
+ break;
+ case 'u':
+ xy = st->saved_xy;
+ break;
+ default: /* Includes CAN and SUB */
+ break; /* Drop unknown sequence */
+ }
+ st->state = st_init;
+ }
+ }
+ break;
+
+ case st_soh:
+ if ( ch == '#' )
+ st->state = st_sohc;
+ else
+ st->state = st_init;
+ break;
+
+ case st_sohc:
+ {
+ int n = (unsigned char)ch - '0';
+ if (n < 10) {
+ st->parms[0] = n*10;
+ st->state = st_sohc1;
+ } else {
+ st->state = st_init;
+ }
+ }
+ break;
+
+ case st_sohc1:
+ {
+ int n = (unsigned char)ch - '0';
+ const char *p;
+
+ if (n < 10) {
+ st->parms[0] += n;
+ if (st->parms[0] < console_color_table_size) {
+ /* Set the color table index */
+ st->cindex = st->parms[0];
+
+ /* See if there are any other attributes we care about */
+ p = console_color_table[st->parms[0]].ansi;
+ st->state = st_esc;
+ __ansi_putchar(ti, '[');
+ while (*p)
+ __ansi_putchar(ti, *p++);
+ __ansi_putchar(ti, 'm');
+ }
+ }
+
+ st->state = st_init;
+ }
+ break;
+ }
+
+ /* If we fell off the end of the screen, adjust */
+ if ( xy.x >= cols ) {
+ xy.x = 0;
+ xy.y++;
+ }
+ while ( xy.y >= rows ) {
+ xy.y--;
+ op->scroll_up(st);
+ }
+
+ /* Update cursor position */
+ op->set_cursor(xy.x, xy.y);
+ st->xy = xy;
+}
--- /dev/null
+/*
+ * ansi.h
+ */
+
+#ifndef COM32_LIB_SYS_ANSI_H
+#define COM32_LIB_SYS_ANSI_H
+
+#include <inttypes.h>
+
+#define ANSI_MAX_PARMS 16
+
+enum ansi_state {
+ st_init,
+ st_esc,
+ st_csi,
+ st_soh,
+ st_sohc,
+ st_sohc1,
+};
+
+struct curxy {
+ uint8_t x, y;
+} __attribute__((packed));
+
+struct term_state {
+ struct curxy xy;
+ int attr; /* Current display attribute */
+ int cindex; /* SOH color index */
+ int vtgraphics; /* VT graphics on/off */
+ int intensity;
+ int underline;
+ int blink;
+ int reverse;
+ int fg;
+ int bg;
+ int autocr;
+ struct curxy saved_xy;
+ uint16_t cursor_type;
+ enum ansi_state state;
+ int pvt; /* Private code? */
+ int nparms; /* Number of parameters seen */
+ int parms[ANSI_MAX_PARMS];
+};
+
+
+struct ansi_ops {
+ void (*erase)(const struct term_state *st, int x0, int y0, int x1, int y1);
+ void (*write_char)(int x, int y, uint8_t ch, const struct term_state *st);
+ void (*showcursor)(const struct term_state *st, int);
+ void (*scroll_up)(const struct term_state *st);
+ void (*set_cursor)(int x, int y);
+};
+
+struct term_info {
+ int rows, cols; /* Screen size */
+ int disabled;
+ struct term_state *ts;
+ const struct ansi_ops *op;
+};
+
+void __ansi_init(const struct term_info *ti);
+void __ansi_putchar(const struct term_info *ti, uint8_t ch);
+
+#endif /* COM32_LIB_SYS_ANSI_H */
#include <colortbl.h>
#include <klibc/compiler.h>
#include "file.h"
+#include "ansi.h"
+
+static void ansicon_erase(const struct term_state *, int, int, int, int);
+static void ansicon_write_char(int, int, uint8_t, const struct term_state *);
+static void ansicon_showcursor(const struct term_state *, int);
+static void ansicon_scroll_up(const struct term_state *);
+static void ansicon_set_cursor(int, int);
+
+static struct term_state ts;
+struct ansi_ops __ansicon_ops = {
+ .erase = ansicon_erase,
+ .write_char = ansicon_write_char,
+ .showcursor = ansicon_showcursor,
+ .set_cursor = ansicon_set_cursor,
+ .scroll_up = ansicon_scroll_up,
+};
+
+static struct term_info ti =
+ {
+ .disabled = 0,
+ .ts = &ts,
+ .op = &__ansicon_ops
+ };
-struct curxy {
- uint8_t x, y;
-} __attribute__((packed));
#define BIOS_CURXY ((struct curxy *)0x450) /* Array for each page */
#define BIOS_ROWS (*(uint8_t *)0x484) /* Minus one; if zero use 24 (= 25 lines) */
#define BIOS_COLS (*(uint16_t *)0x44A)
#define BIOS_PAGE (*(uint8_t *)0x462)
-enum ansi_state {
- st_init, /* Normal (no ESC seen) */
- st_esc, /* ESC seen */
- st_csi, /* CSI seen */
- st_soh, /* SOH seen */
- st_sohc, /* SOH # seen */
- st_sohc1, /* SOH # digit seen */
-};
-
-#define MAX_PARMS 16
-
-struct term_state {
- int disabled;
- int attr; /* Current display attribute */
- int vtgraphics; /* VT graphics on/off */
- int intensity;
- int underline;
- int blink;
- int reverse;
- int fg;
- int bg;
- int autocr;
- struct curxy saved_xy;
- uint16_t cursor_type;
- enum ansi_state state;
- int pvt; /* Private code? */
- int nparms; /* Number of parameters seen */
- int parms[MAX_PARMS];
-};
-
-static const struct term_state default_state =
-{
- .disabled = 0,
- .attr = 0x07, /* Grey on black */
- .vtgraphics = 0,
- .intensity = 1,
- .underline = 0,
- .blink = 0,
- .reverse = 0,
- .fg = 7,
- .bg = 0,
- .autocr = 0,
- .saved_xy = { 0, 0 },
- .cursor_type = 0x0607,
- .state = st_init,
- .pvt = 0,
- .nparms = 0,
-};
-
-static struct term_state st;
-
-/* DEC VT graphics to codepage 437 table (characters 0x60-0x7F only) */
-static const char decvt_to_cp437[] =
- { 0004, 0261, 0007, 0007, 0007, 0007, 0370, 0361, 0007, 0007, 0331, 0277, 0332, 0300, 0305, 0304,
- 0304, 0304, 0137, 0137, 0303, 0264, 0301, 0302, 0263, 0363, 0362, 0343, 0330, 0234, 0007, 00 };
-
-/* Reference counter to the screen, to keep track of if we need reinitialization. */
+/* Reference counter to the screen, to keep track of if we need
+ reinitialization. */
static int ansicon_counter = 0;
/* Common setup */
(void)fp;
if (!ansicon_counter) {
- /* Initial state */
- memcpy(&st, &default_state, sizeof st);
-
/* Are we disabled? */
ireg.eax.w[0] = 0x000b;
__intcall(0x22, &ireg, &oreg);
if ( (signed char)oreg.ebx.b[1] < 0 ) {
- st.disabled = 1;
+ ti.disabled = 1;
} else {
+ /* Initial state */
+ ti.rows = BIOS_ROWS ? BIOS_ROWS+1 : 25;
+ ti.cols = BIOS_COLS;
+ __ansi_init(&ti);
+
/* Force text mode */
ireg.eax.w[0] = 0x0005;
__intcall(0x22, &ireg, NULL);
ireg.eax.b[1] = 0x03;
ireg.ebx.b[1] = BIOS_PAGE;
__intcall(0x10, &ireg, &oreg);
- st.cursor_type = oreg.ecx.w[0];
+ ti.ts->cursor_type = oreg.ecx.w[0];
}
}
return 0;
}
+/* Turn ANSI attributes into VGA attributes */
+static uint8_t ansicon_attribute(const struct term_state *st)
+{
+ 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;
+
+ return (bg << 4) | fg;
+}
+
/* Erase a region of the screen */
-static void ansicon_erase(int x0, int y0, int x1, int y1)
+static void ansicon_erase(const struct term_state *st,
+ int x0, int y0, int x1, int y1)
{
static com32sys_t ireg;
ireg.eax.w[0] = 0x0600; /* Clear window */
- ireg.ebx.b[1] = st.attr; /* Fill with current attribute */
+ ireg.ebx.b[1] = ansicon_attribute(st);
ireg.ecx.b[0] = x0;
ireg.ecx.b[1] = y0;
ireg.edx.b[0] = x1;
}
/* Show or hide the cursor */
-static void showcursor(int yes)
+static void ansicon_showcursor(const struct term_state *st, int yes)
{
static com32sys_t ireg;
ireg.eax.b[1] = 0x01;
- ireg.ecx.w[0] = yes ? st.cursor_type : 0x2020;
+ ireg.ecx.w[0] = yes ? st->cursor_type : 0x2020;
__intcall(0x10, &ireg, NULL);
}
-static void ansicon_putchar(int ch)
+static void ansicon_set_cursor(int x, int y)
{
- 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];
+ static com32sys_t ireg;
- switch ( st.state ) {
- case st_init:
- switch ( ch ) {
- case 1:
- st.state = st_soh;
- break;
- case '\b':
- if ( xy.x > 0 ) xy.x--;
- break;
- case '\t':
- {
- int nsp = 8 - (xy.x & 7);
- while ( nsp-- )
- ansicon_putchar(' ');
- }
- return; /* Cursor already updated */
- case '\n':
- case '\v':
- case '\f':
- xy.y++;
- if ( st.autocr )
- xy.x = 0;
- break;
- case '\r':
- xy.x = 0;
- break;
- case 127:
- /* Ignore delete */
- break;
- case 14:
- st.vtgraphics = 1;
- break;
- case 15:
- st.vtgraphics = 0;
- break;
- case 27:
- st.state = st_esc;
- break;
- default:
- /* Print character */
- if ( ch >= 32 ) {
- if ( st.vtgraphics && (ch & 0xe0) == 0x60 )
- ch = decvt_to_cp437[ch - 0x60];
-
- 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:
- switch ( ch ) {
- case '%':
- case '(':
- case ')':
- case '#':
- /* Ignore this plus the subsequent character, allows
- compatibility with Linux sequence to set charset */
- break;
- case '[':
- st.state = st_csi;
- st.nparms = st.pvt = 0;
- memset(st.parms, 0, sizeof st.parms);
- break;
- case 'c':
- /* Reset terminal */
- memcpy(&st, &default_state, sizeof st);
- ansicon_erase(0, 0, cols-1, rows-1);
- xy.x = xy.y = 1;
- break;
- default:
- /* Ignore sequence */
- st.state = st_init;
- break;
- }
- break;
-
- case st_csi:
- {
- int p0 = st.parms[0] ? st.parms[0] : 1;
-
- if ( ch >= '0' && ch <= '9' ) {
- st.parms[st.nparms] = st.parms[st.nparms]*10 + (ch-'0');
- } else if ( ch == ';' ) {
- st.nparms++;
- if ( st.nparms >= MAX_PARMS )
- st.nparms = MAX_PARMS-1;
- break;
- } else if ( ch == '?' ) {
- st.pvt = 1;
- } else {
- switch ( ch ) {
- case 'A':
- {
- int y = xy.y - p0;
- xy.y = (y < 0) ? 0 : y;
- }
- break;
- case 'B':
- {
- int y = xy.y + p0;
- xy.y = (y >= rows) ? rows-1 : y;
- }
- break;
- case 'C':
- {
- int x = xy.x + p0;
- xy.x = (x >= cols) ? cols-1 : x;
- }
- break;
- case 'D':
- {
- int x = xy.x - p0;
- xy.x = (x < 0) ? 0 : x;
- }
- break;
- case 'E':
- {
- int y = xy.y + p0;
- xy.y = (y >= rows) ? rows-1 : y;
- xy.x = 0;
- }
- break;
- case 'F':
- {
- int y = xy.y - p0;
- xy.y = (y < 0) ? 0 : y;
- xy.x = 0;
- }
- break;
- case 'G':
- case '\'':
- {
- int x = st.parms[0] - 1;
- xy.x = (x >= cols) ? cols-1 : (x < 0) ? 0 : x;
- }
- break;
- case 'H':
- case 'f':
- {
- int y = st.parms[0] - 1;
- int x = st.parms[1] - 1;
-
- xy.x = (x >= cols) ? cols-1 : (x < 0) ? 0 : x;
- xy.y = (y >= rows) ? rows-1 : (y < 0) ? 0 : y;
- }
- break;
- case 'J':
- {
- switch ( st.parms[0] ) {
- case 0:
- 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 1:
- if ( xy.y > 0 )
- ansicon_erase(0, 0, cols-1, xy.y-1);
- if ( xy.y > 0 )
- ansicon_erase(0, xy.y, xy.x-1, xy.y);
- break;
-
- case 2:
- ansicon_erase(0, 0, cols-1, rows-1);
- break;
-
- default:
- /* Ignore */
- break;
- }
- }
- break;
- case 'K':
- {
- switch ( st.parms[0] ) {
- case 0:
- ansicon_erase(xy.x, xy.y, cols-1, xy.y);
- break;
-
- case 1:
- if ( xy.x > 0 )
- ansicon_erase(0, xy.y, xy.x-1, xy.y);
- break;
-
- case 2:
- ansicon_erase(0, xy.y, cols-1, xy.y);
- break;
-
- default:
- /* Ignore */
- break;
- }
- }
- break;
- case 'h':
- case 'l':
- {
- int set = (ch == 'h');
- switch ( st.parms[0] ) {
- case 20:
- st.autocr = set;
- break;
- case 25:
- showcursor(set);
- break;
- default:
- /* Ignore */
- break;
- }
- }
- 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 = 0;
- 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;
- default: /* Includes CAN and SUB */
- break; /* Drop unknown sequence */
- }
- st.state = st_init;
- }
- }
- break;
-
- case st_soh:
- if ( ch == '#' )
- st.state = st_sohc;
- else
- st.state = st_init;
- break;
-
- case st_sohc:
- {
- int n = (unsigned char)ch - '0';
- if (n < 10) {
- st.parms[0] = n*10;
- st.state = st_sohc1;
- } else {
- st.state = st_init;
- }
- }
- break;
-
- case st_sohc1:
- {
- int n = (unsigned char)ch - '0';
- const char *p;
-
- if (n < 10) {
- st.parms[0] += n;
- /* Emulate the appropriate CSI m sequence */
- if (st.parms[0] < console_color_table_size) {
- st.state = st_csi;
- for (p = console_color_table[st.parms[0]].ansi; *p; p++)
- ansicon_putchar(*p);
- ansicon_putchar('m');
- }
- }
-
- st.state = st_init;
- }
- break;
+ if (xy.x != x || xy.y != y) {
+ ireg.eax.b[1] = 0x02;
+ ireg.ebx.b[1] = page;
+ ireg.edx.b[1] = xy.y;
+ ireg.edx.b[0] = xy.x;
+ __intcall(0x10, &ireg, NULL);
}
+}
- /* If we fell off the end of the screen, adjust */
- if ( xy.x >= cols ) {
- xy.x = 0;
- xy.y++;
- }
- while ( xy.y >= rows ) {
- xy.y--;
- ireg.eax.w[0] = 0x0601;
- ireg.ebx.b[1] = st.attr;
- ireg.ecx.w[0] = 0;
- ireg.edx.b[1] = rows-1;
- ireg.edx.b[0] = cols-1;
- __intcall(0x10, &ireg, NULL); /* Scroll */
- }
+static void ansicon_write_char(int x, int y, uint8_t ch,
+ const struct term_state *st)
+{
+ static com32sys_t ireg;
- /* Update cursor position */
- ireg.eax.b[1] = 0x02;
- ireg.ebx.b[1] = page;
- ireg.edx.b[1] = xy.y;
- ireg.edx.b[0] = xy.x;
+ ansicon_set_cursor(x, y);
+
+ ireg.eax.b[1] = 0x09;
+ ireg.eax.b[0] = ch;
+ ireg.ebx.b[1] = BIOS_PAGE;
+ ireg.ebx.b[0] = ansicon_attribute(st);
+ ireg.ecx.w[0] = 1;
__intcall(0x10, &ireg, NULL);
}
+static void ansicon_scroll_up(const struct term_state *st)
+{
+ static com32sys_t ireg;
+
+ ireg.eax.w[0] = 0x0601;
+ ireg.ebx.b[1] = ansicon_attribute(st);
+ ireg.ecx.w[0] = 0;
+ ireg.edx.b[1] = ti.rows-1;
+ ireg.edx.b[0] = ti.cols-1;
+ __intcall(0x10, &ireg, NULL); /* Scroll */
+}
ssize_t __ansicon_write(struct file_info *fp, const void *buf, size_t count)
{
(void)fp;
- if ( st.disabled )
+ if ( ti.disabled )
return n; /* Nothing to do */
while ( count-- ) {
- ansicon_putchar(*bufp++);
+ __ansi_putchar(&ti, *bufp++);
n++;
}
/* ----------------------------------------------------------------------- *
- *
+ *
* Copyright 2006 H. Peter Anvin - All Rights Reserved
*
* Permission is hereby granted, free of charge, to any person
* sell copies of the Software, and to permit persons to whom
* the Software is furnished to do so, subject to the following
* conditions:
- *
+ *
* The above copyright notice and this permission notice shall
* be included in all copies or substantial portions of the Software.
- *
+ *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
/* Set the appropriate set of transformations. We need to end up
with 32-bit BGRA format, no more, no less. */
-
+
switch (info_ptr->color_type) {
case PNG_COLOR_TYPE_GRAY_ALPHA:
png_set_gray_to_rgb(png_ptr);
/* fall through */
-
+
case PNG_COLOR_TYPE_RGB_ALPHA:
break;
else
png_set_add_alpha(png_ptr, ~0, PNG_FILLER_AFTER);
break;
-
+
case PNG_COLOR_TYPE_PALETTE:
png_set_palette_to_rgb(png_ptr);
break;
png_set_background(png_ptr, &my_background,
PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
#endif
-
+
/* Whew! Now we should get the stuff we want... */
for (i = 0; i < (int)info_ptr->height; i++)
row_pointers[i] = (void *)__vesacon_background[i];
-
+
passes = png_set_interlace_handling(png_ptr);
for (i = 0; i < passes; i++)
free(jpeg_file);
return rv;
-}
+}
int vesacon_load_background(const char *filename)
{
rv = read_png_file(fp);
} else if (!jpeg_sig_cmp(header, 8)) {
rv = read_jpeg_file(fp, header, 8);
- }
+ }
/* This actually displays the stuff */
draw_background();
/* ----------------------------------------------------------------------- *
- *
+ *
* Copyright 2006 H. Peter Anvin - All Rights Reserved
*
* Permission is hereby granted, free of charge, to any person
* sell copies of the Software, and to permit persons to whom
* the Software is furnished to do so, subject to the following
* conditions:
- *
+ *
* The above copyright notice and this permission notice shall
* be included in all copies or substantial portions of the Software.
- *
+ *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
chsbits ^= (csptr->sha & 0x01) ? 0xff : 0x00;
chsbits <<= 6;
csptr++;
-
+
for (j = width*ncols; j >= 0; j--) {
chbits <<= 1;
chsbits <<= 1;
color >>= 2;
color &= 0x3f3f3f;
}
-
+
*fbptr++ = color;
}
/* Danger, Will Robinson: this is wrong if rev != SHADOW_NORMAL */
vesacon_fill(toptr, fill, dword_count);
-
+
vesacon_update_characters(0, 0, __vesacon_text_rows,
TEXT_PIXEL_COLS/FONT_WIDTH);
}
}
/* Draw one character text at a specific area of the screen */
-void __vesacon_write_char(int x, int y, char ch, uint8_t attr, int rev)
+void __vesacon_write_char(int x, int y, uint8_t ch, uint8_t attr, int rev)
{
struct vesa_char *ptr = &__vesacon_text_display
[(y+1)*(TEXT_PIXEL_COLS/FONT_WIDTH+2)+(x+1)];
vesacon_update_characters(y, x, 1, 1);
}
-
void __vesacon_erase(int, int, int, int, uint8_t, int);
void __vesacon_scroll_up(int, uint8_t, int);
void __vesacon_write_at(int, int, const char *, uint8_t, int);
-void __vesacon_write_char(int, int, char, uint8_t, int);
+void __vesacon_write_char(int, int, uint8_t, uint8_t, int);
#endif /* LIB_SYS_VESA_VIDEO_H */
#include <minmax.h>
#include <colortbl.h>
#include <klibc/compiler.h>
+#include "ansi.h"
#include "file.h"
#include "vesa/video.h"
-struct curxy {
- uint8_t x, y;
-} __attribute__((packed));
-
-enum ansi_state {
- st_init, /* Normal (no ESC seen) */
- st_esc, /* ESC seen */
- st_csi, /* CSI seen */
- st_soh, /* SOH seen */
- st_sohc, /* SOH # seen */
- st_sohc1, /* SOH # digit seen */
-};
-
-#define MAX_PARMS 16
-
-struct term_state {
- int disabled;
- int attr; /* Current display attribute */
- int vtgraphics; /* VT graphics on/off */
- int intensity;
- int underline;
- int blink;
- int reverse;
- int fg;
- int bg;
- int autocr;
- struct curxy saved_xy;
- uint16_t cursor_type;
- enum ansi_state state;
- int pvt; /* Private code? */
- int nparms; /* Number of parameters seen */
- int parms[MAX_PARMS];
- struct curxy xy;
-};
-
-static const struct term_state default_state =
-{
- .disabled = 0,
- .attr = 0, /* First color table entry */
- .vtgraphics = 0,
- .intensity = 1,
- .underline = 0,
- .blink = 0,
- .reverse = 0,
- .fg = 7,
- .bg = 0,
- .autocr = 0,
- .saved_xy = { 0, 0 },
- .cursor_type = 0x0607,
- .state = st_init,
- .pvt = 0,
- .nparms = 0,
- .xy = { 0, 0 },
+static void vesacon_erase(const struct term_state *, int, int, int, int);
+static void vesacon_write_char(int, int, uint8_t, const struct term_state *);
+static void vesacon_showcursor(const struct term_state *, int);
+static void vesacon_scroll_up(const struct term_state *);
+static void vesacon_set_cursor(int, int);
+
+static struct term_state ts;
+static struct ansi_ops op = {
+ .erase = vesacon_erase,
+ .write_char = vesacon_write_char,
+ .showcursor = vesacon_showcursor,
+ .set_cursor = vesacon_set_cursor,
+ .scroll_up = vesacon_scroll_up,
};
-static struct term_state st;
-
-/* DEC VT graphics to codepage 437 table (characters 0x60-0x7F only) */
-static const char decvt_to_cp437[] =
- { 0004, 0261, 0007, 0007, 0007, 0007, 0370, 0361, 0007, 0007, 0331, 0277, 0332, 0300, 0305, 0304,
- 0304, 0304, 0137, 0137, 0303, 0264, 0301, 0302, 0263, 0363, 0362, 0343, 0330, 0234, 0007, 00 };
+static struct term_info ti =
+ {
+ .cols = TEXT_PIXEL_COLS/FONT_WIDTH,
+ .disabled = 0,
+ .ts = &ts,
+ .op = &op
+ };
/* Reference counter to the screen, to keep track of if we need reinitialization. */
static int vesacon_counter = 0;
(void)fp;
if (!vesacon_counter) {
- /* Initial state */
- memcpy(&st, &default_state, sizeof st);
-
/* Are we disabled? */
ireg.eax.w[0] = 0x000b;
__intcall(0x22, &ireg, &oreg);
if ( (signed char)oreg.ebx.b[1] < 0 ) {
- st.disabled = 1;
+ ti.disabled = 1;
} else {
/* Switch mode */
if (__vesacon_init())
return EIO;
+
+ /* Initial state */
+ __ansi_init(&ti);
+ ti.rows = __vesacon_text_rows;
}
}
}
/* Erase a region of the screen */
-static void vesacon_erase(int x0, int y0, int x1, int y1)
+static void vesacon_erase(const struct term_state *st,
+ int x0, int y0, int x1, int y1)
{
- __vesacon_erase(x0, y0, x1, y1, st.attr,
- st.reverse ? SHADOW_ALL : SHADOW_NORMAL);
+ __vesacon_erase(x0, y0, x1, y1, st->attr,
+ st->reverse ? SHADOW_ALL : SHADOW_NORMAL);
+}
+
+/* Draw text on the screen */
+static void vesacon_write_char(int x, int y, uint8_t ch,
+ const struct term_state *st)
+{
+ __vesacon_write_char(x, y, ch, st->cindex,
+ st->reverse ? SHADOW_ALL : SHADOW_NORMAL);
}
/* Show or hide the cursor */
-static void showcursor(int yes)
+static void vesacon_showcursor(const struct term_state *st, int yes)
{
+ (void)st;
(void)yes;
/* Do something here */
}
-static void vesacon_putchar(int ch)
+static void vesacon_set_cursor(int x, int y)
{
- const int rows = __vesacon_text_rows;
- const int cols = TEXT_PIXEL_COLS/FONT_WIDTH;
- struct curxy xy = st.xy;
-
- switch ( st.state ) {
- case st_init:
- switch ( ch ) {
- case 1:
- st.state = st_soh;
- break;
- case '\b':
- if ( xy.x > 0 ) xy.x--;
- break;
- case '\t':
- {
- int nsp = 8 - (xy.x & 7);
- while ( nsp-- )
- vesacon_putchar(' ');
- }
- return; /* Cursor already updated */
- case '\n':
- case '\v':
- case '\f':
- xy.y++;
- if ( st.autocr )
- xy.x = 0;
- break;
- case '\r':
- xy.x = 0;
- break;
- case 127:
- /* Ignore delete */
- break;
- case 14:
- st.vtgraphics = 1;
- break;
- case 15:
- st.vtgraphics = 0;
- break;
- case 27:
- st.state = st_esc;
- break;
- default:
- /* Print character */
- if ( ch >= 32 ) {
- if ( st.vtgraphics && (ch & 0xe0) == 0x60 )
- ch = decvt_to_cp437[ch - 0x60];
-
- __vesacon_write_char(xy.x, xy.y, ch, st.attr,
- st.reverse ? SHADOW_ALL : SHADOW_NORMAL);
- xy.x++;
- }
- break;
- }
- break;
-
- case st_esc:
- switch ( ch ) {
- case '%':
- case '(':
- case ')':
- case '#':
- /* Ignore this plus the subsequent character, allows
- compatibility with Linux sequence to set charset */
- break;
- case '[':
- st.state = st_csi;
- st.nparms = st.pvt = 0;
- memset(st.parms, 0, sizeof st.parms);
- break;
- case 'c':
- /* Reset terminal */
- memcpy(&st, &default_state, sizeof st);
- vesacon_erase(0, 0, cols-1, rows-1);
- xy.x = xy.y = 1;
- st.state = st_init;
- break;
- default:
- /* Ignore sequence */
- st.state = st_init;
- break;
- }
- break;
-
- case st_csi:
- {
- int p0 = st.parms[0] ? st.parms[0] : 1;
-
- if ( ch >= '0' && ch <= '9' ) {
- st.parms[st.nparms] = st.parms[st.nparms]*10 + (ch-'0');
- } else if ( ch == ';' ) {
- st.nparms++;
- if ( st.nparms >= MAX_PARMS )
- st.nparms = MAX_PARMS-1;
- break;
- } else if ( ch == '?' ) {
- st.pvt = 1;
- } else {
- switch ( ch ) {
- case 'A':
- {
- int y = xy.y - p0;
- xy.y = (y < 0) ? 0 : y;
- }
- break;
- case 'B':
- {
- int y = xy.y + p0;
- xy.y = (y >= rows) ? rows-1 : y;
- }
- break;
- case 'C':
- {
- int x = xy.x + p0;
- xy.x = (x >= cols) ? cols-1 : x;
- }
- break;
- case 'D':
- {
- int x = xy.x - p0;
- xy.x = (x < 0) ? 0 : x;
- }
- break;
- case 'E':
- {
- int y = xy.y + p0;
- xy.y = (y >= rows) ? rows-1 : y;
- xy.x = 0;
- }
- break;
- case 'F':
- {
- int y = xy.y - p0;
- xy.y = (y < 0) ? 0 : y;
- xy.x = 0;
- }
- break;
- case 'G':
- case '\'':
- {
- int x = st.parms[0] - 1;
- xy.x = (x >= cols) ? cols-1 : (x < 0) ? 0 : x;
- }
- break;
- case 'H':
- case 'f':
- {
- int y = st.parms[0] - 1;
- int x = st.parms[1] - 1;
-
- xy.x = (x >= cols) ? cols-1 : (x < 0) ? 0 : x;
- xy.y = (y >= rows) ? rows-1 : (y < 0) ? 0 : y;
- }
- break;
- case 'J':
- {
- switch ( st.parms[0] ) {
- case 0:
- vesacon_erase(xy.x, xy.y, cols-1, xy.y);
- if ( xy.y < rows-1 )
- vesacon_erase(0, xy.y+1, cols-1, rows-1);
- break;
-
- case 1:
- if ( xy.y > 0 )
- vesacon_erase(0, 0, cols-1, xy.y-1);
- if ( xy.y > 0 )
- vesacon_erase(0, xy.y, xy.x-1, xy.y);
- break;
-
- case 2:
- vesacon_erase(0, 0, cols-1, rows-1);
- break;
-
- default:
- /* Ignore */
- break;
- }
- }
- break;
- case 'K':
- {
- switch ( st.parms[0] ) {
- case 0:
- vesacon_erase(xy.x, xy.y, cols-1, xy.y);
- break;
-
- case 1:
- if ( xy.x > 0 )
- vesacon_erase(0, xy.y, xy.x-1, xy.y);
- break;
-
- case 2:
- vesacon_erase(0, xy.y, cols-1, xy.y);
- break;
-
- default:
- /* Ignore */
- break;
- }
- }
- break;
- case 'h':
- case 'l':
- {
- int set = (ch == 'h');
- switch ( st.parms[0] ) {
- case 20:
- st.autocr = set;
- break;
- case 25:
- showcursor(set);
- break;
- default:
- /* Ignore */
- break;
- }
- }
- 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 = 0;
- 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;
- }
- }
- }
- break;
- case 's':
- st.saved_xy = xy;
- break;
- case 'u':
- xy = st.saved_xy;
- break;
- default: /* Includes CAN and SUB */
- break; /* Drop unknown sequence */
- }
- st.state = st_init;
- }
- }
- break;
-
- case st_soh:
- if ( ch == '#' )
- st.state = st_sohc;
- else
- st.state = st_init;
- break;
-
- case st_sohc:
- {
- int n = (unsigned char)ch - '0';
- if (n < 10) {
- st.parms[0] = n*10;
- st.state = st_sohc1;
- } else {
- st.state = st_init;
- }
- }
- break;
-
- case st_sohc1:
- {
- int n = (unsigned char)ch - '0';
- const char *p;
-
- if (n < 10) {
- st.parms[0] += n;
- if (st.parms[0] < console_color_table_size) {
- /* Set the color table index */
- st.attr = st.parms[0];
-
- /* See if there are any other attributes we care about */
- p = console_color_table[st.parms[0]].ansi;
- st.state = st_esc;
- vesacon_putchar('[');
- while (*p)
- vesacon_putchar(*p++);
- vesacon_putchar('m');
- }
- }
-
- st.state = st_init;
- }
- break;
- }
-
- /* If we fell off the end of the screen, adjust */
- if ( xy.x >= cols ) {
- xy.x = 0;
- xy.y++;
- }
- while ( xy.y >= rows ) {
- xy.y--;
- __vesacon_scroll_up(1, st.attr, st.reverse ? SHADOW_ALL : SHADOW_NORMAL);
- }
-
- /* Update cursor position */
- /* vesacon_set_cursor(xy.x, xy.y); */
- st.xy = xy;
+ (void)x; (void)y;
+ /* Do something here */
}
+static void vesacon_scroll_up(const struct term_state *st)
+{
+ __vesacon_scroll_up(1, st->cindex,
+ st->reverse ? SHADOW_ALL : SHADOW_NORMAL);
+}
ssize_t __vesacon_write(struct file_info *fp, const void *buf, size_t count)
{
(void)fp;
- if ( st.disabled )
+ if ( ti.disabled )
return n; /* Nothing to do */
while ( count-- ) {
- vesacon_putchar(*bufp++);
+ __ansi_putchar(&ti, *bufp++);
n++;
}