Improved console handling, thanks Stefan Weil.

git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2322 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
ths 2007-01-16 23:02:36 +00:00
parent dabd98ddf5
commit adb4796796

185
console.c
View File

@ -121,6 +121,7 @@ struct TextConsole {
int total_height;
int backscroll_height;
int x, y;
int x_saved, y_saved;
int y_displayed;
int y_base;
TextAttributes t_attrib_default; /* default text attributes */
@ -147,7 +148,7 @@ static int nb_consoles = 0;
void vga_hw_update(void)
{
if (active_console->hw_update)
if (active_console && active_console->hw_update)
active_console->hw_update(active_console->hw);
}
@ -659,10 +660,6 @@ static void console_handle_escape(TextConsole *s)
{
int i;
if (s->nb_esc_params == 0) { /* ESC[m sets all attributes to default */
s->t_attrib = s->t_attrib_default;
return;
}
for (i=0; i<s->nb_esc_params; i++) {
switch (s->esc_params[i]) {
case 0: /* reset all console attributes to default */
@ -752,10 +749,21 @@ static void console_handle_escape(TextConsole *s)
}
}
static void console_clear_xy(TextConsole *s, int x, int y)
{
int y1 = (s->y_base + y) % s->total_height;
TextCell *c = &s->cells[y1 * s->width + x];
c->ch = ' ';
c->t_attrib = s->t_attrib_default;
c++;
update_xy(s, x, y);
}
static void console_putchar(TextConsole *s, int ch)
{
TextCell *c;
int y1, i, x;
int y1, i;
int x, y;
switch(s->state) {
case TTY_STATE_NORM:
@ -781,20 +789,31 @@ static void console_putchar(TextConsole *s, int ch)
case '\a': /* alert aka. bell */
/* TODO: has to be implemented */
break;
case 14:
/* SI (shift in), character set 0 (ignored) */
break;
case 15:
/* SO (shift out), character set 1 (ignored) */
break;
case 27: /* esc (introducing an escape sequence) */
s->state = TTY_STATE_ESC;
break;
default:
if (s->x >= s->width - 1) {
break;
}
y1 = (s->y_base + s->y) % s->total_height;
c = &s->cells[y1 * s->width + s->x];
c->ch = ch;
c->t_attrib = s->t_attrib;
update_xy(s, s->x, s->y);
s->x++;
#if 0 /* line wrap disabled */
if (s->x >= s->width) {
s->x = 0;
console_put_lf(s);
}
#endif
break;
}
break;
@ -818,32 +837,150 @@ static void console_putchar(TextConsole *s, int ch)
s->nb_esc_params++;
if (ch == ';')
break;
#ifdef DEBUG_CONSOLE
fprintf(stderr, "escape sequence CSI%d;%d%c, %d parameters\n",
s->esc_params[0], s->esc_params[1], ch, s->nb_esc_params);
#endif
s->state = TTY_STATE_NORM;
switch(ch) {
case 'D':
if (s->x > 0)
s->x--;
break;
case 'C':
if (s->x < (s->width - 1))
s->x++;
break;
case 'K':
/* clear to eol */
y1 = (s->y_base + s->y) % s->total_height;
for(x = s->x; x < s->width; x++) {
c = &s->cells[y1 * s->width + x];
c->ch = ' ';
c->t_attrib = s->t_attrib_default;
c++;
update_xy(s, x, s->y);
case 'A':
/* move cursor up */
if (s->esc_params[0] == 0) {
s->esc_params[0] = 1;
}
s->y -= s->esc_params[0];
if (s->y < 0) {
s->y = 0;
}
break;
default:
case 'B':
/* move cursor down */
if (s->esc_params[0] == 0) {
s->esc_params[0] = 1;
}
s->y += s->esc_params[0];
if (s->y >= s->height) {
s->y = s->height - 1;
}
break;
case 'C':
/* move cursor right */
if (s->esc_params[0] == 0) {
s->esc_params[0] = 1;
}
s->x += s->esc_params[0];
if (s->x >= s->width) {
s->x = s->width - 1;
}
break;
case 'D':
/* move cursor left */
if (s->esc_params[0] == 0) {
s->esc_params[0] = 1;
}
s->x -= s->esc_params[0];
if (s->x < 0) {
s->x = 0;
}
break;
case 'G':
/* move cursor to column */
s->x = s->esc_params[0] - 1;
if (s->x < 0) {
s->x = 0;
}
break;
case 'f':
case 'H':
/* move cursor to row, column */
s->x = s->esc_params[1] - 1;
if (s->x < 0) {
s->x = 0;
}
s->y = s->esc_params[0] - 1;
if (s->y < 0) {
s->y = 0;
}
break;
case 'J':
switch (s->esc_params[0]) {
case 0:
/* clear to end of screen */
for (y = s->y; y < s->height; y++) {
for (x = 0; x < s->width; x++) {
if (y == s->y && x < s->x) {
continue;
}
console_clear_xy(s, x, y);
}
}
break;
case 1:
/* clear from beginning of screen */
for (y = 0; y <= s->y; y++) {
for (x = 0; x < s->width; x++) {
if (y == s->y && x > s->x) {
break;
}
console_clear_xy(s, x, y);
}
}
break;
case 2:
/* clear entire screen */
for (y = 0; y <= s->height; y++) {
for (x = 0; x < s->width; x++) {
console_clear_xy(s, x, y);
}
}
break;
}
case 'K':
switch (s->esc_params[0]) {
case 0:
/* clear to eol */
for(x = s->x; x < s->width; x++) {
console_clear_xy(s, x, s->y);
}
break;
case 1:
/* clear from beginning of line */
for (x = 0; x <= s->x; x++) {
console_clear_xy(s, x, s->y);
}
break;
case 2:
/* clear entire line */
for(x = 0; x < s->width; x++) {
console_clear_xy(s, x, s->y);
}
break;
}
break;
case 'm':
console_handle_escape(s);
break;
case 'n':
/* report cursor position */
/* TODO: send ESC[row;colR */
break;
case 's':
/* save cursor position */
s->x_saved = s->x;
s->y_saved = s->y;
break;
case 'u':
/* restore cursor position */
s->x = s->x_saved;
s->y = s->y_saved;
break;
default:
#ifdef DEBUG_CONSOLE
fprintf(stderr, "unhandled escape character '%c'\n", ch);
#endif
break;
}
break;
}
}
}