Commit e15d737181c9e7da2274ca62a3f4f28b7a5cbeb7

Authored by bellard
1 parent be995c27

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
Showing 1 changed file with 104 additions and 24 deletions
console.c
... ... @@ -53,6 +53,57 @@ enum TTYState {
53 53 TTY_STATE_CSI,
54 54 };
55 55  
  56 +typedef struct QEMUFIFO {
  57 + uint8_t *buf;
  58 + int buf_size;
  59 + int count, wptr, rptr;
  60 +} QEMUFIFO;
  61 +
  62 +int qemu_fifo_write(QEMUFIFO *f, const uint8_t *buf, int len1)
  63 +{
  64 + int l, len;
  65 +
  66 + l = f->buf_size - f->count;
  67 + if (len1 > l)
  68 + len1 = l;
  69 + len = len1;
  70 + while (len > 0) {
  71 + l = f->buf_size - f->wptr;
  72 + if (l > len)
  73 + l = len;
  74 + memcpy(f->buf + f->wptr, buf, l);
  75 + f->wptr += l;
  76 + if (f->wptr >= f->buf_size)
  77 + f->wptr = 0;
  78 + buf += l;
  79 + len -= l;
  80 + }
  81 + f->count += len1;
  82 + return len1;
  83 +}
  84 +
  85 +int qemu_fifo_read(QEMUFIFO *f, uint8_t *buf, int len1)
  86 +{
  87 + int l, len;
  88 +
  89 + if (len1 > f->count)
  90 + len1 = f->count;
  91 + len = len1;
  92 + while (len > 0) {
  93 + l = f->buf_size - f->rptr;
  94 + if (l > len)
  95 + l = len;
  96 + memcpy(buf, f->buf + f->rptr, l);
  97 + f->rptr += l;
  98 + if (f->rptr >= f->buf_size)
  99 + f->rptr = 0;
  100 + buf += l;
  101 + len -= l;
  102 + }
  103 + f->count -= len1;
  104 + return len1;
  105 +}
  106 +
56 107 /* ??? This is mis-named.
57 108 It is used for both text and graphical consoles. */
58 109 struct TextConsole {
... ... @@ -81,8 +132,13 @@ struct TextConsole {
81 132 int nb_esc_params;
82 133  
83 134 /* kbd read handler */
  135 + IOCanRWHandler *fd_can_read;
84 136 IOReadHandler *fd_read;
85 137 void *fd_opaque;
  138 + /* fifo for key pressed */
  139 + QEMUFIFO out_fifo;
  140 + uint8_t out_fifo_buf[16];
  141 + QEMUTimer *kbd_timer;
86 142 };
87 143  
88 144 static TextConsole *active_console;
... ... @@ -712,12 +768,8 @@ static void console_putchar(TextConsole *s, int ch)
712 768 console_put_lf(s);
713 769 break;
714 770 case '\b': /* backspace */
715   - if(s->x > 0) s->x--;
716   - y1 = (s->y_base + s->y) % s->total_height;
717   - c = &s->cells[y1 * s->width + s->x];
718   - c->ch = ' ';
719   - c->t_attrib = s->t_attrib;
720   - update_xy(s, s->x, s->y);
  771 + if (s->x > 0)
  772 + s->x--;
721 773 break;
722 774 case '\t': /* tabspace */
723 775 if (s->x + (8 - (s->x % 8)) > s->width) {
... ... @@ -835,6 +887,7 @@ static void console_chr_add_read_handler(CharDriverState *chr,
835 887 IOReadHandler *fd_read, void *opaque)
836 888 {
837 889 TextConsole *s = chr->opaque;
  890 + s->fd_can_read = fd_can_read;
838 891 s->fd_read = fd_read;
839 892 s->fd_opaque = opaque;
840 893 }
... ... @@ -854,6 +907,28 @@ static void console_send_event(CharDriverState *chr, int event)
854 907 }
855 908 }
856 909  
  910 +static void kbd_send_chars(void *opaque)
  911 +{
  912 + TextConsole *s = opaque;
  913 + int len;
  914 + uint8_t buf[16];
  915 +
  916 + len = s->fd_can_read(s->fd_opaque);
  917 + if (len > s->out_fifo.count)
  918 + len = s->out_fifo.count;
  919 + if (len > 0) {
  920 + if (len > sizeof(buf))
  921 + len = sizeof(buf);
  922 + qemu_fifo_read(&s->out_fifo, buf, len);
  923 + s->fd_read(s->fd_opaque, buf, len);
  924 + }
  925 + /* characters are pending: we send them a bit later (XXX:
  926 + horrible, should change char device API) */
  927 + if (s->out_fifo.count > 0) {
  928 + qemu_mod_timer(s->kbd_timer, qemu_get_clock(rt_clock) + 1);
  929 + }
  930 +}
  931 +
857 932 /* called when an ascii key is pressed */
858 933 void kbd_put_keysym(int keysym)
859 934 {
... ... @@ -879,25 +954,26 @@ void kbd_put_keysym(int keysym)
879 954 console_scroll(10);
880 955 break;
881 956 default:
882   - if (s->fd_read) {
883   - /* convert the QEMU keysym to VT100 key string */
884   - q = buf;
885   - if (keysym >= 0xe100 && keysym <= 0xe11f) {
886   - *q++ = '\033';
887   - *q++ = '[';
888   - c = keysym - 0xe100;
889   - if (c >= 10)
890   - *q++ = '0' + (c / 10);
891   - *q++ = '0' + (c % 10);
892   - *q++ = '~';
893   - } else if (keysym >= 0xe120 && keysym <= 0xe17f) {
894   - *q++ = '\033';
895   - *q++ = '[';
896   - *q++ = keysym & 0xff;
897   - } else {
  957 + /* convert the QEMU keysym to VT100 key string */
  958 + q = buf;
  959 + if (keysym >= 0xe100 && keysym <= 0xe11f) {
  960 + *q++ = '\033';
  961 + *q++ = '[';
  962 + c = keysym - 0xe100;
  963 + if (c >= 10)
  964 + *q++ = '0' + (c / 10);
  965 + *q++ = '0' + (c % 10);
  966 + *q++ = '~';
  967 + } else if (keysym >= 0xe120 && keysym <= 0xe17f) {
  968 + *q++ = '\033';
  969 + *q++ = '[';
  970 + *q++ = keysym & 0xff;
  971 + } else {
898 972 *q++ = keysym;
899   - }
900   - s->fd_read(s->fd_opaque, buf, q - buf);
  973 + }
  974 + if (s->fd_read) {
  975 + qemu_fifo_write(&s->out_fifo, buf, q - buf);
  976 + kbd_send_chars(s);
901 977 }
902 978 break;
903 979 }
... ... @@ -974,6 +1050,10 @@ CharDriverState *text_console_init(DisplayState *ds)
974 1050 chr->chr_add_read_handler = console_chr_add_read_handler;
975 1051 chr->chr_send_event = console_send_event;
976 1052  
  1053 + s->out_fifo.buf = s->out_fifo_buf;
  1054 + s->out_fifo.buf_size = sizeof(s->out_fifo_buf);
  1055 + s->kbd_timer = qemu_new_timer(rt_clock, kbd_send_chars, s);
  1056 +
977 1057 if (!color_inited) {
978 1058 color_inited = 1;
979 1059 for(j = 0; j < 2; j++) {
... ...