mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-04 00:03:54 -06:00
curses: support wide input
This makes use of wide curses functions instead of 8bit functions. This allows to type e.g. accented letters. Unfortunately, key codes are then returned with values that could be confused with wide characters by ncurses, so we need to add a maybe_keycode variable to know whether the returned value is a key code or a character (curses with wide support), or possibly both (curses without wide support). The translation tables thus also need to be separated into key code translation and character translation. The curses2foo helper makes it easier to use them. Signed-off-by: Samuel Thibault <samuel.thibault@ens-lyon.org> Message-id: 20190304210532.7840-1-samuel.thibault@ens-lyon.org Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
This commit is contained in:
parent
633786fea7
commit
459a707ecc
2 changed files with 127 additions and 62 deletions
76
ui/curses.c
76
ui/curses.c
|
@ -42,6 +42,12 @@
|
|||
#define FONT_HEIGHT 16
|
||||
#define FONT_WIDTH 8
|
||||
|
||||
enum maybe_keycode {
|
||||
CURSES_KEYCODE,
|
||||
CURSES_CHAR,
|
||||
CURSES_CHAR_OR_KEYCODE,
|
||||
};
|
||||
|
||||
static DisplayChangeListener *dcl;
|
||||
static console_ch_t screen[160 * 100];
|
||||
static WINDOW *screenpad = NULL;
|
||||
|
@ -194,9 +200,54 @@ static void curses_cursor_position(DisplayChangeListener *dcl,
|
|||
|
||||
static kbd_layout_t *kbd_layout = NULL;
|
||||
|
||||
static wint_t console_getch(enum maybe_keycode *maybe_keycode)
|
||||
{
|
||||
wint_t ret;
|
||||
switch (get_wch(&ret)) {
|
||||
case KEY_CODE_YES:
|
||||
*maybe_keycode = CURSES_KEYCODE;
|
||||
break;
|
||||
case OK:
|
||||
*maybe_keycode = CURSES_CHAR;
|
||||
break;
|
||||
case ERR:
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int curses2foo(const int _curses2foo[], const int _curseskey2foo[],
|
||||
int chr, enum maybe_keycode maybe_keycode)
|
||||
{
|
||||
int ret = -1;
|
||||
if (maybe_keycode == CURSES_CHAR) {
|
||||
if (chr < CURSES_CHARS) {
|
||||
ret = _curses2foo[chr];
|
||||
}
|
||||
} else {
|
||||
if (chr < CURSES_KEYS) {
|
||||
ret = _curseskey2foo[chr];
|
||||
}
|
||||
if (ret == -1 && maybe_keycode == CURSES_CHAR_OR_KEYCODE &&
|
||||
chr < CURSES_CHARS) {
|
||||
ret = _curses2foo[chr];
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define curses2keycode(chr, maybe_keycode) \
|
||||
curses2foo(_curses2keycode, _curseskey2keycode, chr, maybe_keycode)
|
||||
#define curses2keysym(chr, maybe_keycode) \
|
||||
curses2foo(_curses2keysym, _curseskey2keysym, chr, maybe_keycode)
|
||||
#define curses2qemu(chr, maybe_keycode) \
|
||||
curses2foo(_curses2qemu, _curseskey2qemu, chr, maybe_keycode)
|
||||
|
||||
static void curses_refresh(DisplayChangeListener *dcl)
|
||||
{
|
||||
int chr, keysym, keycode, keycode_alt;
|
||||
enum maybe_keycode maybe_keycode;
|
||||
|
||||
curses_winch_check();
|
||||
|
||||
|
@ -212,14 +263,14 @@ static void curses_refresh(DisplayChangeListener *dcl)
|
|||
|
||||
while (1) {
|
||||
/* while there are any pending key strokes to process */
|
||||
chr = getch();
|
||||
chr = console_getch(&maybe_keycode);
|
||||
|
||||
if (chr == ERR)
|
||||
if (chr == -1)
|
||||
break;
|
||||
|
||||
#ifdef KEY_RESIZE
|
||||
/* this shouldn't occur when we use a custom SIGWINCH handler */
|
||||
if (chr == KEY_RESIZE) {
|
||||
if (maybe_keycode != CURSES_CHAR && chr == KEY_RESIZE) {
|
||||
clear();
|
||||
refresh();
|
||||
curses_calc_pad();
|
||||
|
@ -228,17 +279,19 @@ static void curses_refresh(DisplayChangeListener *dcl)
|
|||
}
|
||||
#endif
|
||||
|
||||
keycode = curses2keycode[chr];
|
||||
keycode = curses2keycode(chr, maybe_keycode);
|
||||
keycode_alt = 0;
|
||||
|
||||
/* alt or esc key */
|
||||
if (keycode == 1) {
|
||||
int nextchr = getch();
|
||||
enum maybe_keycode next_maybe_keycode;
|
||||
int nextchr = console_getch(&next_maybe_keycode);
|
||||
|
||||
if (nextchr != ERR) {
|
||||
if (nextchr != -1) {
|
||||
chr = nextchr;
|
||||
maybe_keycode = next_maybe_keycode;
|
||||
keycode_alt = ALT;
|
||||
keycode = curses2keycode[chr];
|
||||
keycode = curses2keycode(chr, maybe_keycode);
|
||||
|
||||
if (keycode != -1) {
|
||||
keycode |= ALT;
|
||||
|
@ -258,9 +311,7 @@ static void curses_refresh(DisplayChangeListener *dcl)
|
|||
}
|
||||
|
||||
if (kbd_layout) {
|
||||
keysym = -1;
|
||||
if (chr < CURSES_KEYS)
|
||||
keysym = curses2keysym[chr];
|
||||
keysym = curses2keysym(chr, maybe_keycode);
|
||||
|
||||
if (keysym == -1) {
|
||||
if (chr < ' ') {
|
||||
|
@ -326,10 +377,7 @@ static void curses_refresh(DisplayChangeListener *dcl)
|
|||
qemu_input_event_send_key_delay(0);
|
||||
}
|
||||
} else {
|
||||
keysym = -1;
|
||||
if (chr < CURSES_KEYS) {
|
||||
keysym = curses2qemu[chr];
|
||||
}
|
||||
keysym = curses2qemu(chr, maybe_keycode);
|
||||
if (keysym == -1)
|
||||
keysym = chr;
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue