From 9ac07bc4aad3c52a63c2c1063cc7fde9d103fcf4 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Mon, 11 Sep 2006 22:10:21 -0700 Subject: [PATCH] Cursor support for vesacon --- com32/lib/sys/ansi.c | 6 +-- com32/lib/sys/ansi.h | 6 +-- com32/lib/sys/ansicon_write.c | 18 +++++---- com32/lib/sys/vesa/drawtxt.c | 86 ++++++++++++++++++++++++++++++++++++++++--- com32/lib/sys/vesa/initvesa.c | 1 + com32/lib/sys/vesa/video.h | 3 ++ com32/lib/sys/vesacon_write.c | 21 ++++------- 7 files changed, 110 insertions(+), 31 deletions(-) diff --git a/com32/lib/sys/ansi.c b/com32/lib/sys/ansi.c index 244b627f..74bf09f7 100644 --- a/com32/lib/sys/ansi.c +++ b/com32/lib/sys/ansi.c @@ -48,7 +48,7 @@ static const struct term_state default_state = .bg = 0, .autocr = 0, .saved_xy = { 0, 0 }, - .cursor_type = 0x0607, + .cursor = 1, .state = st_init, .pvt = 0, .nparms = 0, @@ -283,7 +283,7 @@ void __ansi_putchar(const struct term_info *ti, uint8_t ch) st->autocr = set; break; case 25: - op->showcursor(st, set); + op->showcursor(st); break; default: /* Ignore */ @@ -429,6 +429,6 @@ void __ansi_putchar(const struct term_info *ti, uint8_t ch) } /* Update cursor position */ - op->set_cursor(xy.x, xy.y); + op->set_cursor(xy.x, xy.y, st->cursor); st->xy = xy; } diff --git a/com32/lib/sys/ansi.h b/com32/lib/sys/ansi.h index f4074c21..ec2c58cb 100644 --- a/com32/lib/sys/ansi.h +++ b/com32/lib/sys/ansi.h @@ -35,7 +35,7 @@ struct term_state { int bg; int autocr; struct curxy saved_xy; - uint16_t cursor_type; + int cursor; enum ansi_state state; int pvt; /* Private code? */ int nparms; /* Number of parameters seen */ @@ -46,9 +46,9 @@ struct term_state { 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 (*showcursor)(const struct term_state *st); void (*scroll_up)(const struct term_state *st); - void (*set_cursor)(int x, int y); + void (*set_cursor)(int x, int y, int visible); }; struct term_info { diff --git a/com32/lib/sys/ansicon_write.c b/com32/lib/sys/ansicon_write.c index e3fb0ec7..43b7c18b 100644 --- a/com32/lib/sys/ansicon_write.c +++ b/com32/lib/sys/ansicon_write.c @@ -43,9 +43,9 @@ 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_showcursor(const struct term_state *); static void ansicon_scroll_up(const struct term_state *); -static void ansicon_set_cursor(int, int); +static void ansicon_set_cursor(int, int, int); static struct term_state ts; struct ansi_ops __ansicon_ops = { @@ -72,6 +72,8 @@ static struct term_info ti = reinitialization. */ static int ansicon_counter = 0; +static uint16_t cursor_type; /* Saved cursor pattern */ + /* Common setup */ int __ansicon_open(struct file_info *fp) { @@ -101,7 +103,7 @@ int __ansicon_open(struct file_info *fp) ireg.eax.b[1] = 0x03; ireg.ebx.b[1] = BIOS_PAGE; __intcall(0x10, &ireg, &oreg); - ti.ts->cursor_type = oreg.ecx.w[0]; + cursor_type = oreg.ecx.w[0]; } } @@ -161,21 +163,23 @@ static void ansicon_erase(const struct term_state *st, } /* Show or hide the cursor */ -static void ansicon_showcursor(const struct term_state *st, int yes) +static void ansicon_showcursor(const struct term_state *st) { static com32sys_t ireg; ireg.eax.b[1] = 0x01; - ireg.ecx.w[0] = yes ? st->cursor_type : 0x2020; + ireg.ecx.w[0] = st->cursor ? cursor_type : 0x2020; __intcall(0x10, &ireg, NULL); } -static void ansicon_set_cursor(int x, int y) +static void ansicon_set_cursor(int x, int y, int visible) { const int page = BIOS_PAGE; struct curxy xy = BIOS_CURXY[page]; static com32sys_t ireg; + (void)visible; + if (xy.x != x || xy.y != y) { ireg.eax.b[1] = 0x02; ireg.ebx.b[1] = page; @@ -190,7 +194,7 @@ static void ansicon_write_char(int x, int y, uint8_t ch, { static com32sys_t ireg; - ansicon_set_cursor(x, y); + ansicon_set_cursor(x, y, 0); ireg.eax.b[1] = 0x09; ireg.eax.b[0] = ch; diff --git a/com32/lib/sys/vesa/drawtxt.c b/com32/lib/sys/vesa/drawtxt.c index b2265e80..5a42457f 100644 --- a/com32/lib/sys/vesa/drawtxt.c +++ b/com32/lib/sys/vesa/drawtxt.c @@ -31,6 +31,13 @@ #include "video.h" /* + * Visible cursor information + */ +static uint8_t cursor_pattern[FONT_MAX_HEIGHT]; +static struct vesa_char *cursor_pointer = NULL; +static int cursor_x, cursor_y; + +/* * Linear alpha blending. Useless for anything that's actually * depends on color accuracy (because of gamma), but it's fine for * what we want. @@ -89,6 +96,8 @@ static void vesacon_update_characters(int row, int col, int nrows, int ncols) csptr = rowsptr; chsbits = __vesacon_graphics_font[csptr->ch][pixsrow]; + if (__unlikely(csptr == cursor_pointer)) + chsbits |= cursor_pattern[pixsrow]; chsbits &= (csptr->sha & 0x02) ? 0xff : 0x00; chsbits ^= (csptr->sha & 0x01) ? 0xff : 0x00; chsbits <<= 6; @@ -102,6 +111,8 @@ static void vesacon_update_characters(int row, int col, int nrows, int ncols) switch (j % FONT_WIDTH) { case 0: chbits = __vesacon_graphics_font[cptr->ch][pixrow]; + if (__unlikely(cptr == cursor_pointer)) + chbits |= cursor_pattern[pixrow]; chxbits = chbits; chxbits &= (cptr->sha & 0x02) ? 0xff : 0x00; chxbits ^= (cptr->sha & 0x01) ? 0xff : 0x00; @@ -111,6 +122,8 @@ static void vesacon_update_characters(int row, int col, int nrows, int ncols) break; case FONT_WIDTH-1: chsbits = __vesacon_graphics_font[csptr->ch][pixsrow]; + if (__unlikely(csptr == cursor_pointer)) + chsbits |= cursor_pattern[pixsrow]; chsbits &= (csptr->sha & 0x02) ? 0xff : 0x00; chsbits ^= (csptr->sha & 0x01) ? 0xff : 0x00; csptr++; @@ -152,6 +165,38 @@ static void vesacon_update_characters(int row, int col, int nrows, int ncols) } } +/* Bounding box for changed text. The (x1, y1) coordinates are +1! */ +static unsigned int upd_x0 = -1U, upd_x1, upd_y0 = -1U, upd_y1; + +/* Update the range already touched by various variables */ +void __vesacon_doit(void) +{ + if (upd_x1 > upd_x0 && upd_y1 > upd_y0) { + vesacon_update_characters(upd_y0, upd_x0, upd_y1-upd_y0, upd_x1-upd_x0); + upd_x0 = upd_y0 = -1U; + upd_x1 = upd_y1 = 0; + } +} + +/* Mark a range for update; note argument sequence is the same as + vesacon_update_characters() */ +static inline void vesacon_touch(int row, int col, int rows, int cols) +{ + unsigned int y0 = row; + unsigned int x0 = col; + unsigned int y1 = y0+rows; + unsigned int x1 = x0+cols; + + if (y0 < upd_y0) + upd_y0 = y0; + if (y1 > upd_y1) + upd_y1 = y1; + if (x0 < upd_x0) + upd_x0 = x0; + if (x1 > upd_x1) + upd_x1 = x1; +} + /* Fill a number of characters... */ static inline struct vesa_char *vesacon_fill(struct vesa_char *ptr, struct vesa_char fill, @@ -183,7 +228,7 @@ void __vesacon_erase(int x0, int y0, int x1, int y1, uint8_t attr, int rev) ptr += TEXT_PIXEL_COLS/FONT_WIDTH+2; } - vesacon_update_characters(y0, x0, y1-y0+1, ncols); + vesacon_touch(y0, x0, y1-y0+1, ncols); } /* Scroll the screen up */ @@ -208,8 +253,7 @@ void __vesacon_scroll_up(int nrows, uint8_t attr, int rev) /* 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); + vesacon_touch(0, 0, __vesacon_text_rows, TEXT_PIXEL_COLS/FONT_WIDTH); } /* Draw text at a specific area of the screen */ @@ -230,7 +274,7 @@ void __vesacon_write_at(int x, int y, const char *str, ptr++; } - vesacon_update_characters(y, x, 1, n); + vesacon_touch(y, x, 1, n); } /* Draw one character text at a specific area of the screen */ @@ -243,5 +287,37 @@ void __vesacon_write_char(int x, int y, uint8_t ch, uint8_t attr, int rev) ptr->attr = attr; ptr->sha = rev; - vesacon_update_characters(y, x, 1, 1); + vesacon_touch(y, x, 1, 1); +} + +void __vesacon_set_cursor(int x, int y, int visible) +{ + struct vesa_char *ptr = &__vesacon_text_display + [(y+1)*(TEXT_PIXEL_COLS/FONT_WIDTH+2)+(x+1)]; + + if (cursor_pointer) + vesacon_touch(cursor_y, cursor_x, 1, 1); + + if (!visible) { + /* Invisible cursor */ + cursor_pointer = NULL; + } else { + cursor_pointer = ptr; + vesacon_touch(y, x, 1, 1); + } + + cursor_x = x; + cursor_y = y; +} + +void __vesacon_init_cursor(int font_height) +{ + int r0 = font_height - (font_height < 10 ? 2 : 3); + + if (r0 < 0) + r0 = 0; + + /* cursor_pattern is assumed to be all zero */ + cursor_pattern[r0] = 0xff; + cursor_pattern[r0+1] = 0xff; } diff --git a/com32/lib/sys/vesa/initvesa.c b/com32/lib/sys/vesa/initvesa.c index 82c99406..2becc9be 100644 --- a/com32/lib/sys/vesa/initvesa.c +++ b/com32/lib/sys/vesa/initvesa.c @@ -161,6 +161,7 @@ static int vesacon_set_mode(void) __vesacon_font_height = 16; unpack_font((uint8_t *)__vesacon_graphics_font, rom_font, 16); __vesacon_text_rows = (VIDEO_Y_SIZE-2*VIDEO_BORDER)/__vesacon_font_height; + __vesacon_init_cursor(__vesacon_font_height); /* Now set video mode */ rm.eax.w[0] = 0x4F02; /* Set SVGA video mode */ diff --git a/com32/lib/sys/vesa/video.h b/com32/lib/sys/vesa/video.h index bfb1466e..d13021c7 100644 --- a/com32/lib/sys/vesa/video.h +++ b/com32/lib/sys/vesa/video.h @@ -63,9 +63,12 @@ extern unsigned char __vesacon_alpha_tbl[256][4]; int __vesacon_init_background(void); int vesacon_load_background(const char *); int __vesacon_init(void); +void __vesacon_init_cursor(int); 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, uint8_t, uint8_t, int); +void __vesacon_doit(void); +void __vesacon_set_cursor(int, int, int); #endif /* LIB_SYS_VESA_VIDEO_H */ diff --git a/com32/lib/sys/vesacon_write.c b/com32/lib/sys/vesacon_write.c index ee9c1931..bcdf6a13 100644 --- a/com32/lib/sys/vesacon_write.c +++ b/com32/lib/sys/vesacon_write.c @@ -44,16 +44,15 @@ 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_showcursor(const struct term_state *); 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, + .set_cursor = __vesacon_set_cursor, /* in drawtxt.c */ .scroll_up = vesacon_scroll_up, }; @@ -123,17 +122,9 @@ static void vesacon_write_char(int x, int y, uint8_t ch, } /* Show or hide the cursor */ -static void vesacon_showcursor(const struct term_state *st, int yes) +static void vesacon_showcursor(const struct term_state *st) { - (void)st; - (void)yes; - /* Do something here */ -} - -static void vesacon_set_cursor(int x, int y) -{ - (void)x; (void)y; - /* Do something here */ + __vesacon_set_cursor(st->xy.x, st->xy.y, st->cursor); } static void vesacon_scroll_up(const struct term_state *st) @@ -152,11 +143,15 @@ ssize_t __vesacon_write(struct file_info *fp, const void *buf, size_t count) if ( ti.disabled ) return n; /* Nothing to do */ + /* This only updates the shadow text buffer... */ while ( count-- ) { __ansi_putchar(&ti, *bufp++); n++; } + /* This actually draws it */ + __vesacon_doit(); + return n; } -- 2.11.4.GIT