summaryrefslogtreecommitdiff
path: root/console.c
diff options
context:
space:
mode:
authorbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>2006-06-25 16:26:29 +0000
committerbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>2006-06-25 16:26:29 +0000
commite15d737181c9e7da2274ca62a3f4f28b7a5cbeb7 (patch)
tree1692ffd9dea5d062aa685b511a87542b81331c1e /console.c
parentbe995c27640a82c7056b6f53d02ec823570114e5 (diff)
downloadqemu-e15d737181c9e7da2274ca62a3f4f28b7a5cbeb7.tar.gz
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
Diffstat (limited to 'console.c')
-rw-r--r--console.c128
1 files changed, 104 insertions, 24 deletions
diff --git a/console.c b/console.c
index 6f9dc1fea2..279b7e01e1 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++) {