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