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,6 +53,57 @@ enum TTYState { | ||
53 | TTY_STATE_CSI, | 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 | /* ??? This is mis-named. | 107 | /* ??? This is mis-named. |
57 | It is used for both text and graphical consoles. */ | 108 | It is used for both text and graphical consoles. */ |
58 | struct TextConsole { | 109 | struct TextConsole { |
@@ -81,8 +132,13 @@ struct TextConsole { | @@ -81,8 +132,13 @@ struct TextConsole { | ||
81 | int nb_esc_params; | 132 | int nb_esc_params; |
82 | 133 | ||
83 | /* kbd read handler */ | 134 | /* kbd read handler */ |
135 | + IOCanRWHandler *fd_can_read; | ||
84 | IOReadHandler *fd_read; | 136 | IOReadHandler *fd_read; |
85 | void *fd_opaque; | 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 | static TextConsole *active_console; | 144 | static TextConsole *active_console; |
@@ -712,12 +768,8 @@ static void console_putchar(TextConsole *s, int ch) | @@ -712,12 +768,8 @@ static void console_putchar(TextConsole *s, int ch) | ||
712 | console_put_lf(s); | 768 | console_put_lf(s); |
713 | break; | 769 | break; |
714 | case '\b': /* backspace */ | 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 | break; | 773 | break; |
722 | case '\t': /* tabspace */ | 774 | case '\t': /* tabspace */ |
723 | if (s->x + (8 - (s->x % 8)) > s->width) { | 775 | if (s->x + (8 - (s->x % 8)) > s->width) { |
@@ -835,6 +887,7 @@ static void console_chr_add_read_handler(CharDriverState *chr, | @@ -835,6 +887,7 @@ static void console_chr_add_read_handler(CharDriverState *chr, | ||
835 | IOReadHandler *fd_read, void *opaque) | 887 | IOReadHandler *fd_read, void *opaque) |
836 | { | 888 | { |
837 | TextConsole *s = chr->opaque; | 889 | TextConsole *s = chr->opaque; |
890 | + s->fd_can_read = fd_can_read; | ||
838 | s->fd_read = fd_read; | 891 | s->fd_read = fd_read; |
839 | s->fd_opaque = opaque; | 892 | s->fd_opaque = opaque; |
840 | } | 893 | } |
@@ -854,6 +907,28 @@ static void console_send_event(CharDriverState *chr, int event) | @@ -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 | /* called when an ascii key is pressed */ | 932 | /* called when an ascii key is pressed */ |
858 | void kbd_put_keysym(int keysym) | 933 | void kbd_put_keysym(int keysym) |
859 | { | 934 | { |
@@ -879,25 +954,26 @@ void kbd_put_keysym(int keysym) | @@ -879,25 +954,26 @@ void kbd_put_keysym(int keysym) | ||
879 | console_scroll(10); | 954 | console_scroll(10); |
880 | break; | 955 | break; |
881 | default: | 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 | *q++ = keysym; | 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 | break; | 978 | break; |
903 | } | 979 | } |
@@ -974,6 +1050,10 @@ CharDriverState *text_console_init(DisplayState *ds) | @@ -974,6 +1050,10 @@ CharDriverState *text_console_init(DisplayState *ds) | ||
974 | chr->chr_add_read_handler = console_chr_add_read_handler; | 1050 | chr->chr_add_read_handler = console_chr_add_read_handler; |
975 | chr->chr_send_event = console_send_event; | 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 | if (!color_inited) { | 1057 | if (!color_inited) { |
978 | color_inited = 1; | 1058 | color_inited = 1; |
979 | for(j = 0; j < 2; j++) { | 1059 | for(j = 0; j < 2; j++) { |