sim-card
/
qemu
Archived
10
0
Fork 0

send correctly long key sequences on slow terminals - fixes backspace handling

git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2012 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
bellard 2006-06-25 16:26:29 +00:00
parent be995c2764
commit e15d737181
1 changed files with 104 additions and 24 deletions

128
console.c
View File

@ -53,6 +53,57 @@ enum TTYState {
TTY_STATE_CSI, TTY_STATE_CSI,
}; };
typedef struct QEMUFIFO {
uint8_t *buf;
int buf_size;
int count, wptr, rptr;
} QEMUFIFO;
int qemu_fifo_write(QEMUFIFO *f, const uint8_t *buf, int len1)
{
int l, len;
l = f->buf_size - f->count;
if (len1 > l)
len1 = l;
len = len1;
while (len > 0) {
l = f->buf_size - f->wptr;
if (l > len)
l = len;
memcpy(f->buf + f->wptr, buf, l);
f->wptr += l;
if (f->wptr >= f->buf_size)
f->wptr = 0;
buf += l;
len -= l;
}
f->count += len1;
return len1;
}
int qemu_fifo_read(QEMUFIFO *f, uint8_t *buf, int len1)
{
int l, len;
if (len1 > f->count)
len1 = f->count;
len = len1;
while (len > 0) {
l = f->buf_size - f->rptr;
if (l > len)
l = len;
memcpy(buf, f->buf + f->rptr, l);
f->rptr += l;
if (f->rptr >= f->buf_size)
f->rptr = 0;
buf += l;
len -= l;
}
f->count -= len1;
return len1;
}
/* ??? This is mis-named. /* ??? This is mis-named.
It is used for both text and graphical consoles. */ It is used for both text and graphical consoles. */
struct TextConsole { struct TextConsole {
@ -81,8 +132,13 @@ struct TextConsole {
int nb_esc_params; int nb_esc_params;
/* kbd read handler */ /* kbd read handler */
IOCanRWHandler *fd_can_read;
IOReadHandler *fd_read; IOReadHandler *fd_read;
void *fd_opaque; void *fd_opaque;
/* fifo for key pressed */
QEMUFIFO out_fifo;
uint8_t out_fifo_buf[16];
QEMUTimer *kbd_timer;
}; };
static TextConsole *active_console; static TextConsole *active_console;
@ -712,12 +768,8 @@ static void console_putchar(TextConsole *s, int ch)
console_put_lf(s); console_put_lf(s);
break; break;
case '\b': /* backspace */ case '\b': /* backspace */
if(s->x > 0) s->x--; if (s->x > 0)
y1 = (s->y_base + s->y) % s->total_height; s->x--;
c = &s->cells[y1 * s->width + s->x];
c->ch = ' ';
c->t_attrib = s->t_attrib;
update_xy(s, s->x, s->y);
break; break;
case '\t': /* tabspace */ case '\t': /* tabspace */
if (s->x + (8 - (s->x % 8)) > s->width) { if (s->x + (8 - (s->x % 8)) > s->width) {
@ -835,6 +887,7 @@ static void console_chr_add_read_handler(CharDriverState *chr,
IOReadHandler *fd_read, void *opaque) IOReadHandler *fd_read, void *opaque)
{ {
TextConsole *s = chr->opaque; TextConsole *s = chr->opaque;
s->fd_can_read = fd_can_read;
s->fd_read = fd_read; s->fd_read = fd_read;
s->fd_opaque = opaque; s->fd_opaque = opaque;
} }
@ -854,6 +907,28 @@ static void console_send_event(CharDriverState *chr, int event)
} }
} }
static void kbd_send_chars(void *opaque)
{
TextConsole *s = opaque;
int len;
uint8_t buf[16];
len = s->fd_can_read(s->fd_opaque);
if (len > s->out_fifo.count)
len = s->out_fifo.count;
if (len > 0) {
if (len > sizeof(buf))
len = sizeof(buf);
qemu_fifo_read(&s->out_fifo, buf, len);
s->fd_read(s->fd_opaque, buf, len);
}
/* characters are pending: we send them a bit later (XXX:
horrible, should change char device API) */
if (s->out_fifo.count > 0) {
qemu_mod_timer(s->kbd_timer, qemu_get_clock(rt_clock) + 1);
}
}
/* called when an ascii key is pressed */ /* called when an ascii key is pressed */
void kbd_put_keysym(int keysym) void kbd_put_keysym(int keysym)
{ {
@ -879,25 +954,26 @@ void kbd_put_keysym(int keysym)
console_scroll(10); console_scroll(10);
break; break;
default: default:
if (s->fd_read) { /* convert the QEMU keysym to VT100 key string */
/* convert the QEMU keysym to VT100 key string */ q = buf;
q = buf; if (keysym >= 0xe100 && keysym <= 0xe11f) {
if (keysym >= 0xe100 && keysym <= 0xe11f) { *q++ = '\033';
*q++ = '\033'; *q++ = '[';
*q++ = '['; c = keysym - 0xe100;
c = keysym - 0xe100; if (c >= 10)
if (c >= 10) *q++ = '0' + (c / 10);
*q++ = '0' + (c / 10); *q++ = '0' + (c % 10);
*q++ = '0' + (c % 10); *q++ = '~';
*q++ = '~'; } else if (keysym >= 0xe120 && keysym <= 0xe17f) {
} else if (keysym >= 0xe120 && keysym <= 0xe17f) { *q++ = '\033';
*q++ = '\033'; *q++ = '[';
*q++ = '['; *q++ = keysym & 0xff;
*q++ = keysym & 0xff; } else {
} else {
*q++ = keysym; *q++ = keysym;
} }
s->fd_read(s->fd_opaque, buf, q - buf); if (s->fd_read) {
qemu_fifo_write(&s->out_fifo, buf, q - buf);
kbd_send_chars(s);
} }
break; break;
} }
@ -974,6 +1050,10 @@ CharDriverState *text_console_init(DisplayState *ds)
chr->chr_add_read_handler = console_chr_add_read_handler; chr->chr_add_read_handler = console_chr_add_read_handler;
chr->chr_send_event = console_send_event; chr->chr_send_event = console_send_event;
s->out_fifo.buf = s->out_fifo_buf;
s->out_fifo.buf_size = sizeof(s->out_fifo_buf);
s->kbd_timer = qemu_new_timer(rt_clock, kbd_send_chars, s);
if (!color_inited) { if (!color_inited) {
color_inited = 1; color_inited = 1;
for(j = 0; j < 2; j++) { for(j = 0; j < 2; j++) {