From e15d737181c9e7da2274ca62a3f4f28b7a5cbeb7 Mon Sep 17 00:00:00 2001 From: bellard Date: Sun, 25 Jun 2006 16:26:29 +0000 Subject: [PATCH] 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 --- console.c | 128 +++++++++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 104 insertions(+), 24 deletions(-) diff --git a/console.c b/console.c index 6f9dc1f..279b7e0 100644 --- a/console.c +++ b/console.c @@ -53,6 +53,57 @@ enum TTYState { 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. It is used for both text and graphical consoles. */ struct TextConsole { @@ -81,8 +132,13 @@ struct TextConsole { int nb_esc_params; /* kbd read handler */ + IOCanRWHandler *fd_can_read; IOReadHandler *fd_read; void *fd_opaque; + /* fifo for key pressed */ + QEMUFIFO out_fifo; + uint8_t out_fifo_buf[16]; + QEMUTimer *kbd_timer; }; static TextConsole *active_console; @@ -712,12 +768,8 @@ static void console_putchar(TextConsole *s, int ch) console_put_lf(s); break; case '\b': /* backspace */ - if(s->x > 0) s->x--; - y1 = (s->y_base + s->y) % s->total_height; - c = &s->cells[y1 * s->width + s->x]; - c->ch = ' '; - c->t_attrib = s->t_attrib; - update_xy(s, s->x, s->y); + if (s->x > 0) + s->x--; break; case '\t': /* tabspace */ 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) { TextConsole *s = chr->opaque; + s->fd_can_read = fd_can_read; s->fd_read = fd_read; 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 */ void kbd_put_keysym(int keysym) { @@ -879,25 +954,26 @@ void kbd_put_keysym(int keysym) console_scroll(10); break; default: - if (s->fd_read) { - /* convert the QEMU keysym to VT100 key string */ - q = buf; - if (keysym >= 0xe100 && keysym <= 0xe11f) { - *q++ = '\033'; - *q++ = '['; - c = keysym - 0xe100; - if (c >= 10) - *q++ = '0' + (c / 10); - *q++ = '0' + (c % 10); - *q++ = '~'; - } else if (keysym >= 0xe120 && keysym <= 0xe17f) { - *q++ = '\033'; - *q++ = '['; - *q++ = keysym & 0xff; - } else { + /* convert the QEMU keysym to VT100 key string */ + q = buf; + if (keysym >= 0xe100 && keysym <= 0xe11f) { + *q++ = '\033'; + *q++ = '['; + c = keysym - 0xe100; + if (c >= 10) + *q++ = '0' + (c / 10); + *q++ = '0' + (c % 10); + *q++ = '~'; + } else if (keysym >= 0xe120 && keysym <= 0xe17f) { + *q++ = '\033'; + *q++ = '['; + *q++ = keysym & 0xff; + } else { *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; } @@ -974,6 +1050,10 @@ CharDriverState *text_console_init(DisplayState *ds) chr->chr_add_read_handler = console_chr_add_read_handler; 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) { color_inited = 1; for(j = 0; j < 2; j++) { -- 1.7.9.5