aboutsummaryrefslogtreecommitdiffstats
path: root/com32
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2006-09-11 22:10:21 -0700
committerH. Peter Anvin <hpa@zytor.com>2006-09-11 22:10:21 -0700
commit9ac07bc4aad3c52a63c2c1063cc7fde9d103fcf4 (patch)
treebdf8f40e7f2d37598b65b12c775478ce64055d75 /com32
parent146c0ce9b8f15b77c9a215cc65bad0edebb789a6 (diff)
downloadsyslinux-9ac07bc4aad3c52a63c2c1063cc7fde9d103fcf4.tar.gz
syslinux-9ac07bc4aad3c52a63c2c1063cc7fde9d103fcf4.tar.xz
syslinux-9ac07bc4aad3c52a63c2c1063cc7fde9d103fcf4.zip
Cursor support for vesacon
Diffstat (limited to 'com32')
-rw-r--r--com32/lib/sys/ansi.c6
-rw-r--r--com32/lib/sys/ansi.h6
-rw-r--r--com32/lib/sys/ansicon_write.c18
-rw-r--r--com32/lib/sys/vesa/drawtxt.c86
-rw-r--r--com32/lib/sys/vesa/initvesa.c1
-rw-r--r--com32/lib/sys/vesa/video.h3
-rw-r--r--com32/lib/sys/vesacon_write.c21
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;
}