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++) { |