Commit e15d737181c9e7da2274ca62a3f4f28b7a5cbeb7
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++) { | ... | ... |