On Sun, Feb 28, 2010 at 09:03:00PM +0100, Samuel Thibault wrote: > Hello, > > The combination of keymap support (-k option) and curses is currently > very broken. The patch below fixes it by first extending keymap support > to interpret the shift, ctrl, altgr and addupper keywords in keymaps, > and to fix curses into properly using keymaps. > > Samuel > > Signed-off-by: Samuel Thibault <samuel.thiba...@ens-lyon.org> > > commit 36f0635cb65e1735a7e231d609da98efcda756c5 > Author: Samuel Thibault <samuel.thiba...@ens-lyon.org> > Date: Sun Feb 28 20:48:39 2010 +0100 > > Fix curses with -k option
Thanks, applied. > diff --git a/curses.c b/curses.c > index 3ce12b9..4b5beac 100644 > --- a/curses.c > +++ b/curses.c > @@ -159,11 +159,10 @@ static void curses_cursor_position(DisplayState *ds, > int x, int y) > #include "curses_keys.h" > > static kbd_layout_t *kbd_layout = NULL; > -static int keycode2keysym[CURSES_KEYS]; > > static void curses_refresh(DisplayState *ds) > { > - int chr, nextchr, keysym, keycode; > + int chr, nextchr, keysym, keycode, keycode_alt; > > if (invalidate) { > clear(); > @@ -204,43 +203,58 @@ static void curses_refresh(DisplayState *ds) > #endif > > keycode = curses2keycode[chr]; > - if (keycode == -1) > - continue; > + keycode_alt = 0; > > /* alt key */ > if (keycode == 1) { > nextchr = getch(); > > if (nextchr != ERR) { > + chr = nextchr; > + keycode_alt = ALT; > keycode = curses2keycode[nextchr]; > nextchr = ERR; > - if (keycode == -1) > - continue; > > - keycode |= ALT; > + if (keycode != -1) { > + keycode |= ALT; > > - /* process keys reserved for qemu */ > - if (keycode >= QEMU_KEY_CONSOLE0 && > - keycode < QEMU_KEY_CONSOLE0 + 9) { > - erase(); > - wnoutrefresh(stdscr); > - console_select(keycode - QEMU_KEY_CONSOLE0); > + /* process keys reserved for qemu */ > + if (keycode >= QEMU_KEY_CONSOLE0 && > + keycode < QEMU_KEY_CONSOLE0 + 9) { > + erase(); > + wnoutrefresh(stdscr); > + console_select(keycode - QEMU_KEY_CONSOLE0); > > - invalidate = 1; > - continue; > + invalidate = 1; > + continue; > + } > } > } > } > > - if (kbd_layout && !(keycode & GREY)) { > - keysym = keycode2keysym[keycode & KEY_MASK]; > - if (keysym == -1) > - keysym = chr; > + if (kbd_layout) { > + keysym = -1; > + if (chr < CURSES_KEYS) > + keysym = curses2keysym[chr]; > + > + if (keysym == -1) { > + if (chr < ' ') > + keysym = (chr + '@' - 'A' + 'a') | KEYSYM_CNTRL; > + else > + keysym = chr; > + } > > - keycode &= ~KEY_MASK; > - keycode |= keysym2scancode(kbd_layout, keysym); > + keycode = keysym2scancode(kbd_layout, keysym & KEYSYM_MASK); > + if (keycode == 0) > + continue; > + > + keycode |= (keysym & ~KEYSYM_MASK) >> 16; > + keycode |= keycode_alt; > } > > + if (keycode == -1) > + continue; > + > if (is_graphic_console()) { > /* since terminals don't know about key press and release > * events, we need to emit both for each key received */ > @@ -250,12 +264,20 @@ static void curses_refresh(DisplayState *ds) > kbd_put_keycode(CNTRL_CODE); > if (keycode & ALT) > kbd_put_keycode(ALT_CODE); > + if (keycode & ALTGR) { > + kbd_put_keycode(SCANCODE_EMUL0); > + kbd_put_keycode(ALT_CODE); > + } > if (keycode & GREY) > kbd_put_keycode(GREY_CODE); > kbd_put_keycode(keycode & KEY_MASK); > if (keycode & GREY) > kbd_put_keycode(GREY_CODE); > kbd_put_keycode((keycode & KEY_MASK) | KEY_RELEASE); > + if (keycode & ALTGR) { > + kbd_put_keycode(SCANCODE_EMUL0); > + kbd_put_keycode(ALT_CODE | KEY_RELEASE); > + } > if (keycode & ALT) > kbd_put_keycode(ALT_CODE | KEY_RELEASE); > if (keycode & CNTRL) > @@ -263,7 +285,7 @@ static void curses_refresh(DisplayState *ds) > if (keycode & SHIFT) > kbd_put_keycode(SHIFT_CODE | KEY_RELEASE); > } else { > - keysym = curses2keysym[chr]; > + keysym = curses2qemu[chr]; > if (keysym == -1) > keysym = chr; > > @@ -301,8 +323,6 @@ static void curses_setup(void) > > static void curses_keyboard_setup(void) > { > - int i, keycode, keysym; > - > #if defined(__APPLE__) > /* always use generic keymaps */ > if (!keyboard_layout) > @@ -313,27 +333,6 @@ static void curses_keyboard_setup(void) > if (!kbd_layout) > exit(1); > } > - > - for (i = 0; i < CURSES_KEYS; i ++) > - keycode2keysym[i] = -1; > - > - for (i = 0; i < CURSES_KEYS; i ++) { > - if (curses2keycode[i] == -1) > - continue; > - > - keycode = curses2keycode[i] & KEY_MASK; > - if (keycode2keysym[keycode] >= 0) > - continue; > - > - for (keysym = 0; keysym < CURSES_KEYS; keysym ++) > - if (curses2keycode[keysym] == keycode) { > - keycode2keysym[keycode] = keysym; > - break; > - } > - > - if (keysym >= CURSES_KEYS) > - keycode2keysym[keycode] = i; > - } > } > > void curses_display_init(DisplayState *ds, int full_screen) > diff --git a/curses_keys.h b/curses_keys.h > index 9c1aa7f..36b8b9b 100644 > --- a/curses_keys.h > +++ b/curses_keys.h > @@ -28,20 +28,36 @@ > > #define KEY_RELEASE 0x80 > #define KEY_MASK 0x7f > -#define SHIFT_CODE 0x2a > -#define SHIFT 0x0080 > #define GREY_CODE 0xe0 > -#define GREY 0x0100 > +#define GREY SCANCODE_GREY > +#define SHIFT_CODE 0x2a > +#define SHIFT SCANCODE_SHIFT > #define CNTRL_CODE 0x1d > -#define CNTRL 0x0200 > +#define CNTRL SCANCODE_CTRL > #define ALT_CODE 0x38 > -#define ALT 0x0400 > +#define ALT SCANCODE_ALT > +#define ALTGR SCANCODE_ALTGR > + > +#define KEYSYM_MASK 0x0ffffff > +#define KEYSYM_SHIFT (SCANCODE_SHIFT << 16) > +#define KEYSYM_CNTRL (SCANCODE_CTRL << 16) > +#define KEYSYM_ALT (SCANCODE_ALT << 16) > +#define KEYSYM_ALTGR (SCANCODE_ALTGR << 16) > > /* curses won't detect a Control + Alt + 1, so use Alt + 1 */ > #define QEMU_KEY_CONSOLE0 (2 | ALT) /* (curses2keycode['1'] | ALT) */ > > #define CURSES_KEYS KEY_MAX /* KEY_MAX defined in <curses.h> */ > > +static const int curses2keysym[CURSES_KEYS] = { > + [0 ... (CURSES_KEYS - 1)] = -1, > + > + [0x7f] = KEY_BACKSPACE, > + ['\r'] = KEY_ENTER, > + ['\n'] = KEY_ENTER, > + [KEY_BTAB] = '\t' | KEYSYM_SHIFT, > +}; > + > static const int curses2keycode[CURSES_KEYS] = { > [0 ... (CURSES_KEYS - 1)] = -1, > > @@ -225,7 +241,7 @@ static const int curses2keycode[CURSES_KEYS] = { > > }; > > -static const int curses2keysym[CURSES_KEYS] = { > +static const int curses2qemu[CURSES_KEYS] = { > [0 ... (CURSES_KEYS - 1)] = -1, > > ['\n'] = '\n', > @@ -449,9 +465,9 @@ static const name2keysym_t name2keysym[] = { > { "ydiaeresis", 0x0ff }, > > /* Special keys */ > - { "BackSpace", 0x07f }, > + { "BackSpace", KEY_BACKSPACE }, > { "Tab", '\t' }, > - { "Return", '\n' }, > + { "Return", KEY_ENTER }, > { "Right", KEY_RIGHT }, > { "Left", KEY_LEFT }, > { "Up", KEY_UP }, > diff --git a/keymaps.c b/keymaps.c > index 6685562..78c7ea3 100644 > --- a/keymaps.c > +++ b/keymaps.c > @@ -59,6 +59,29 @@ static void add_to_key_range(struct key_range **krp, int > code) { > } > } > > +static void add_keysym(char *line, int keysym, int keycode, kbd_layout_t *k) > { > + if (keysym < MAX_NORMAL_KEYCODE) { > + //fprintf(stderr,"Setting keysym %s (%d) to %d\n",line,keysym,keycode); > + k->keysym2keycode[keysym] = keycode; > + } else { > + if (k->extra_count >= MAX_EXTRA_COUNT) { > + fprintf(stderr, > + "Warning: Could not assign keysym %s (0x%x) because of > memory constraints.\n", > + line, keysym); > + } else { > +#if 0 > + fprintf(stderr, "Setting %d: %d,%d\n", > + k->extra_count, keysym, keycode); > +#endif > + k->keysym2keycode_extra[k->extra_count]. > + keysym = keysym; > + k->keysym2keycode_extra[k->extra_count]. > + keycode = keycode; > + k->extra_count++; > + } > + } > +} > + > static kbd_layout_t *parse_keyboard_layout(const name2keysym_t *table, > const char *language, > kbd_layout_t * k) > @@ -111,27 +134,22 @@ static kbd_layout_t *parse_keyboard_layout(const > name2keysym_t *table, > //fprintf(stderr, "keypad keysym %04x keycode %d\n", > keysym, keycode); > } > > - /* if(keycode&0x80) > - keycode=(keycode<<8)^0x80e0; */ > - if (keysym < MAX_NORMAL_KEYCODE) { > - //fprintf(stderr,"Setting keysym %s (%d) to > %d\n",line,keysym,keycode); > - k->keysym2keycode[keysym] = keycode; > - } else { > - if (k->extra_count >= MAX_EXTRA_COUNT) { > - fprintf(stderr, > - "Warning: Could not assign keysym %s (0x%x) > because of memory constraints.\n", > - line, keysym); > - } else { > -#if 0 > - fprintf(stderr, "Setting %d: %d,%d\n", > - k->extra_count, keysym, keycode); > -#endif > - k->keysym2keycode_extra[k->extra_count]. > - keysym = keysym; > - k->keysym2keycode_extra[k->extra_count]. > - keycode = keycode; > - k->extra_count++; > - } > + if (rest && strstr(rest, "shift")) > + keycode |= SCANCODE_SHIFT; > + if (rest && strstr(rest, "altgr")) > + keycode |= SCANCODE_ALTGR; > + if (rest && strstr(rest, "ctrl")) > + keycode |= SCANCODE_CTRL; > + > + add_keysym(line, keysym, keycode, k); > + > + if (rest && strstr(rest, "addupper")) { > + char *c; > + for (c = line; *c; c++) > + *c = toupper(*c); > + keysym = get_keysym(table, line); > + if (keysym) > + add_keysym(line, keysym, keycode | SCANCODE_SHIFT, > k); > } > } > } > diff --git a/keymaps.h b/keymaps.h > index 17f6efd..a7600d5 100644 > --- a/keymaps.h > +++ b/keymaps.h > @@ -51,6 +51,23 @@ typedef struct { > struct key_range *numlock_range; > } kbd_layout_t; > > +/* scancode without modifiers */ > +#define SCANCODE_KEYMASK 0xff > +/* scancode without grey or up bit */ > +#define SCANCODE_KEYCODEMASK 0x7f > + > +/* "grey" keys will usually need a 0xe0 prefix */ > +#define SCANCODE_GREY 0x80 > +#define SCANCODE_EMUL0 0xE0 > +/* "up" flag */ > +#define SCANCODE_UP 0x80 > + > +/* Additional modifiers to use if not catched another way. */ > +#define SCANCODE_SHIFT 0x100 > +#define SCANCODE_CTRL 0x200 > +#define SCANCODE_ALT 0x400 > +#define SCANCODE_ALTGR 0x800 > + > > void *init_keyboard_layout(const name2keysym_t *table, const char *language); > int keysym2scancode(void *kbd_layout, int keysym); > diff --git a/sdl.c b/sdl.c > index a9b4323..f26035c 100644 > --- a/sdl.c > +++ b/sdl.c > @@ -248,7 +248,7 @@ static uint8_t sdl_keyevent_to_keycode_generic(const > SDL_KeyboardEvent *ev) > if (keysym == 92 && ev->keysym.scancode == 133) { > keysym = 0xa5; > } > - return keysym2scancode(kbd_layout, keysym); > + return keysym2scancode(kbd_layout, keysym) & SCANCODE_KEYMASK; > } > > /* specific keyboard conversions from scan codes */ > @@ -343,9 +343,9 @@ static void reset_keys(void) > int i; > for(i = 0; i < 256; i++) { > if (modifiers_state[i]) { > - if (i & 0x80) > - kbd_put_keycode(0xe0); > - kbd_put_keycode(i | 0x80); > + if (i & SCANCODE_GREY) > + kbd_put_keycode(SCANCODE_EMUL0); > + kbd_put_keycode(i | SCANCODE_UP); > modifiers_state[i] = 0; > } > } > @@ -359,7 +359,7 @@ static void sdl_process_key(SDL_KeyboardEvent *ev) > /* specific case */ > v = 0; > if (ev->type == SDL_KEYUP) > - v |= 0x80; > + v |= SCANCODE_UP; > kbd_put_keycode(0xe1); > kbd_put_keycode(0x1d | v); > kbd_put_keycode(0x45 | v); > @@ -392,17 +392,17 @@ static void sdl_process_key(SDL_KeyboardEvent *ev) > case 0x3a: /* caps lock */ > /* SDL does not send the key up event, so we generate it */ > kbd_put_keycode(keycode); > - kbd_put_keycode(keycode | 0x80); > + kbd_put_keycode(keycode | SCANCODE_UP); > return; > } > > /* now send the key code */ > - if (keycode & 0x80) > - kbd_put_keycode(0xe0); > + if (keycode & SCANCODE_GREY) > + kbd_put_keycode(SCANCODE_EMUL0); > if (ev->type == SDL_KEYUP) > - kbd_put_keycode(keycode | 0x80); > + kbd_put_keycode(keycode | SCANCODE_UP); > else > - kbd_put_keycode(keycode & 0x7f); > + kbd_put_keycode(keycode & SCANCODE_KEYCODEMASK); > } > > static void sdl_update_caption(void) > diff --git a/vnc.c b/vnc.c > index db34b0e..01353a9 100644 > --- a/vnc.c > +++ b/vnc.c > @@ -1482,9 +1482,9 @@ static void reset_keys(VncState *vs) > int i; > for(i = 0; i < 256; i++) { > if (vs->modifiers_state[i]) { > - if (i & 0x80) > - kbd_put_keycode(0xe0); > - kbd_put_keycode(i | 0x80); > + if (i & SCANCODE_GREY) > + kbd_put_keycode(SCANCODE_EMUL0); > + kbd_put_keycode(i | SCANCODE_UP); > vs->modifiers_state[i] = 0; > } > } > @@ -1492,8 +1492,13 @@ static void reset_keys(VncState *vs) > > static void press_key(VncState *vs, int keysym) > { > - kbd_put_keycode(keysym2scancode(vs->vd->kbd_layout, keysym) & 0x7f); > - kbd_put_keycode(keysym2scancode(vs->vd->kbd_layout, keysym) | 0x80); > + int keycode = keysym2scancode(vs->vd->kbd_layout, keysym) & > SCANCODE_KEYMASK; > + if (keycode & SCANCODE_GREY) > + kbd_put_keycode(SCANCODE_EMUL0); > + kbd_put_keycode(keycode & SCANCODE_KEYCODEMASK); > + if (keycode & SCANCODE_GREY) > + kbd_put_keycode(SCANCODE_EMUL0); > + kbd_put_keycode(keycode | SCANCODE_UP); > } > > static void do_key_event(VncState *vs, int down, int keycode, int sym) > @@ -1566,12 +1571,12 @@ static void do_key_event(VncState *vs, int down, int > keycode, int sym) > } > > if (is_graphic_console()) { > - if (keycode & 0x80) > - kbd_put_keycode(0xe0); > + if (keycode & SCANCODE_GREY) > + kbd_put_keycode(SCANCODE_EMUL0); > if (down) > - kbd_put_keycode(keycode & 0x7f); > + kbd_put_keycode(keycode & SCANCODE_KEYCODEMASK); > else > - kbd_put_keycode(keycode | 0x80); > + kbd_put_keycode(keycode | SCANCODE_UP); > } else { > /* QEMU console emulation */ > if (down) { > @@ -1679,7 +1684,7 @@ static void key_event(VncState *vs, int down, uint32_t > sym) > lsym = lsym - 'A' + 'a'; > } > > - keycode = keysym2scancode(vs->vd->kbd_layout, lsym & 0xFFFF); > + keycode = keysym2scancode(vs->vd->kbd_layout, lsym & 0xFFFF) & > SCANCODE_KEYMASK; > do_key_event(vs, down, keycode, sym); > } > > > > -- Aurelien Jarno GPG: 1024D/F1BCDB73 aurel...@aurel32.net http://www.aurel32.net