--- qemu-old/keymaps/es Sun Dec 12 18:56:30 2004 +++ qemu-new/keymaps/es Tue Aug 08 23:41:55 2006 @@ -103,3 +103,58 @@ underscore 0x35 shift dead_belowdot 0x35 altgr dead_abovedot 0x35 shift altgr + + +# Dead keys +aacute 0x1e dead_acute +Aacute 0x1e dead_acute shift +eacute 0x12 dead_acute +Eacute 0x12 dead_acute shift +iacute 0x17 dead_acute +Iacute 0x17 dead_acute shift +oacute 0x18 dead_acute +Oacute 0x18 dead_acute shift +uacute 0x16 dead_acute +Uacute 0x16 dead_acute shift +yacute 0x15 dead_acute +Yacute 0x15 dead_acute shift + +agrave 0x1e dead_grave +Agrave 0x1e dead_grave shift +egrave 0x12 dead_grave +Egrave 0x12 dead_grave shift +igrave 0x17 dead_grave +Igrave 0x17 dead_grave shift +ograve 0x18 dead_grave +Ograve 0x18 dead_grave shift +ugrave 0x16 dead_grave +Ugrave 0x16 dead_grave shift + +adiaeresis 0x1e dead_diaeresis +Adiaeresis 0x1e dead_diaeresis shift +ediaeresis 0x12 dead_diaeresis +Ediaeresis 0x12 dead_diaeresis shift +idiaeresis 0x17 dead_diaeresis +Idiaeresis 0x17 dead_diaeresis shift +odiaeresis 0x18 dead_diaeresis +Odiaeresis 0x18 dead_diaeresis shift +udiaeresis 0x16 dead_diaeresis +Udiaeresis 0x16 dead_diaeresis shift +ydiaeresis 0x15 dead_diaeresis + +acircumflex 0x1e dead_circumflex +Acircumflex 0x1e dead_circumflex shift +ecircumflex 0x12 dead_circumflex +Ecircumflex 0x12 dead_circumflex shift +icircumflex 0x17 dead_circumflex +Icircumflex 0x17 dead_circumflex shift +ocircumflex 0x18 dead_circumflex +Ocircumflex 0x18 dead_circumflex shift +ucircumflex 0x16 dead_circumflex +Ucircumflex 0x16 dead_circumflex shift + +acute 0x39 dead_acute +grave 0x39 dead_grave +diaeresis 0x39 dead_diaeresis +asciicircum 0x39 dead_circumflex + --- qemu-old/keymaps.c Sun Apr 30 23:28:35 2006 +++ qemu-new/keymaps.c Tue Aug 08 23:39:58 2006 @@ -22,6 +22,7 @@ * THE SOFTWARE. */ + static int get_keysym(const char *name) { name2keysym_t *p; @@ -32,13 +33,26 @@ return 0; } + +#define KEYMOD_SHIFT 0x01 +#define KEYMOD_CTRL 0x02 +#define KEYMOD_ALT 0x04 +#define KEYMOD_DEAD 0x08 + #define MAX_NORMAL_KEYCODE 512 #define MAX_EXTRA_COUNT 256 + typedef struct { - uint16_t keysym2keycode[MAX_NORMAL_KEYCODE]; + uint16_t keycode; + uint8_t keymod; + int deadsym; +} keydata_t; + +typedef struct { + keydata_t keysym2keycode[MAX_NORMAL_KEYCODE]; struct { int keysym; - uint16_t keycode; + keydata_t kdata; } keysym2keycode_extra[MAX_EXTRA_COUNT]; int extra_count; } kbd_layout_t; @@ -50,6 +64,7 @@ char file_name[1024]; char line[1024]; int len; + int upper; snprintf(file_name, sizeof(file_name), "%s/keymaps/%s", bios_dir, language); @@ -82,17 +97,61 @@ if (*end_of_keysym) { int keysym; *end_of_keysym = 0; + uint8_t keymod; + int deadsym; + + keymod = 0; + deadsym = 0; + upper = 0; +redo: + if (upper==1){ + char *c; + for(c=line;*c;c++) + *c=toupper(*c); + keymod |= KEYMOD_SHIFT; + upper++; + } keysym = get_keysym(line); if (keysym == 0) { // fprintf(stderr, "Warning: unknown keysym %s\n", line); } else { const char *rest = end_of_keysym + 1; int keycode = strtol(rest, NULL, 0); + char *modifier; + modifier = strtok (rest," "); + modifier = strtok (NULL," "); + while ( modifier != NULL) { + if (!strcmp(modifier, "shift")) { + keymod |= KEYMOD_SHIFT; + } else + if (!strcmp(modifier, "addupper")) { + upper++; + } else + if (!strcmp(modifier, "ctrl")) { + keymod |= KEYMOD_CTRL; + } else + if (!strcmp(modifier, "alt")) { + keymod |= KEYMOD_ALT; + } else + if (!strcmp(modifier, "altgr")) { + keymod |= KEYMOD_CTRL | KEYMOD_ALT; + } else + if (!strncmp(modifier, "dead_",5)) { + keymod |= KEYMOD_DEAD; + deadsym = get_keysym(modifier); + } + modifier = strtok (NULL," "); + } /* 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; + k->keysym2keycode[keysym]. + keycode = keycode; + k->keysym2keycode[keysym]. + keymod = keymod; + k->keysym2keycode[keysym]. + deadsym = deadsym; } else { if (k->extra_count >= MAX_EXTRA_COUNT) { fprintf(stderr, @@ -105,11 +164,18 @@ #endif k->keysym2keycode_extra[k->extra_count]. keysym = keysym; - k->keysym2keycode_extra[k->extra_count]. + k->keysym2keycode_extra[k->extra_count].kdata. keycode = keycode; + k->keysym2keycode_extra[k->extra_count].kdata. + keymod = keymod; + k->keysym2keycode_extra[k->extra_count].kdata. + deadsym = deadsym; + k->extra_count++; } } + if (upper==1) + goto redo; } } } @@ -123,14 +189,11 @@ return parse_keyboard_layout(language, 0); } -static int keysym2scancode(void *kbd_layout, int keysym) +static keydata_t *find_keysym(void *kbd_layout, int keysym) { kbd_layout_t *k = kbd_layout; if (keysym < MAX_NORMAL_KEYCODE) { - if (k->keysym2keycode[keysym] == 0) - fprintf(stderr, "Warning: no scancode found for keysym %d\n", - keysym); - return k->keysym2keycode[keysym]; + return &k->keysym2keycode[keysym]; } else { int i; #ifdef XK_ISO_Left_Tab @@ -138,8 +201,9 @@ keysym = XK_Tab; #endif for (i = 0; i < k->extra_count; i++) - if (k->keysym2keycode_extra[i].keysym == keysym) - return k->keysym2keycode_extra[i].keycode; + if (k->keysym2keycode_extra[i].keysym == keysym) { + return &k->keysym2keycode_extra[i].kdata; } - return 0; + } + return NULL; } --- qemu-old/sdl.c Tue Jun 13 14:03:53 2006 +++ qemu-new/sdl.c Tue Aug 08 23:40:08 2006 @@ -104,7 +104,11 @@ keysym = ev->keysym.sym; if (keysym == 0 && ev->keysym.scancode == 113) keysym = SDLK_MODE; - return keysym2scancode(kbd_layout, keysym); + keydata_t *eventdata = find_keysym(kbd_layout, keysym); + if (eventdata==NULL) + return 0; + else + return eventdata->keycode; } /* specific keyboard conversions from scan codes */ --- qemu-old/vnc.c Tue Jun 13 18:35:24 2006 +++ qemu-new/vnc.c Tue Aug 08 23:41:37 2006 @@ -31,6 +31,23 @@ #include "vnc_keysym.h" #include "keymaps.c" + +static uint8_t modifiers_state[2][256]; + +typedef struct { + int left; + int right; + int bit; +} modifier_t; + +static modifier_t test_modifier[]={ + {0x2a, 0x36, KEYMOD_SHIFT}, + {0x1d, 0x9d, KEYMOD_CTRL}, + {0x38, 0xb8, KEYMOD_ALT}, + {0,0,0}, +}; + + typedef struct Buffer { size_t capacity; @@ -699,12 +716,9 @@ } } -static void do_key_event(VncState *vs, int down, uint32_t sym) -{ - int keycode; - - keycode = keysym2scancode(vs->kbd_layout, sym & 0xFFFF); +static void do_keycode(int keycode, int down) +{ if (keycode & 0x80) kbd_put_keycode(0xe0); if (down) @@ -713,11 +727,88 @@ kbd_put_keycode(keycode | 0x80); } +static void do_modifier(int keycode, int down, int level) +{ + do_keycode(keycode,down); + modifiers_state[level][keycode] = down; + if (level==0) { + modifiers_state[1][keycode] = down; + } +} + +static void set_modifiers(uint8_t reqstate,int down,int full) +{ + modifier_t *m; + for(m=test_modifier; m->bit; m++) { + int requested = reqstate & m->bit; + /* Release unwanted modifiers */ + if (!down || full) { + if (modifiers_state[1][m->left] && !requested) + do_modifier(m->left,0,1); + if (modifiers_state[1][m->right] && !requested) + do_modifier(m->right,0,1); + } + /* Press desired modifiers */ + if (down || full) { + int already_set = modifiers_state[1][m->left] | modifiers_state[1][m->right]; + if (!already_set && requested) + do_modifier(m->left,1,1); + } + } +} + +static void restore_modifiers() +{ + /* Restore modifiers from reference */ + modifier_t *m; + for(m=test_modifier; m->bit; m++) { + if (modifiers_state[0][m->left] != modifiers_state[1][m->left]) + do_modifier(m->left,modifiers_state[0][m->left],0); + if (modifiers_state[0][m->right] != modifiers_state[1][m->right]) + do_modifier(m->right,modifiers_state[0][m->right],0); + } +} + static void key_event(VncState *vs, int down, uint32_t sym) { - if (sym >= 'A' && sym <= 'Z') - sym = sym - 'A' + 'a'; - do_key_event(vs, down, sym); + keydata_t *eventdata; + eventdata = find_keysym(vs->kbd_layout, sym & 0xFFFF); + if (eventdata==NULL) + return; + switch(eventdata->keycode) { + case 0x2a: /* Left Shift */ + case 0x36: /* Right Shift */ + case 0x1d: /* Left CTRL */ + case 0x9d: /* Right CTRL */ + case 0x38: /* Left ALT */ + case 0xb8: /* Right ALT */ + do_modifier(eventdata->keycode, down, 0); + return; + case 0x3a: /* caps lock */ + /* TODO: handle properly caps lock + shift combinations */ + return; + break; + } + + if (down) { + /* Send deadkey */ + if (eventdata->keymod & KEYMOD_DEAD) { + keydata_t *deaddata; + deaddata = find_keysym(vs->kbd_layout, eventdata->deadsym); + if (deaddata!=NULL) { + set_modifiers(deaddata->keymod,0,1); + do_keycode(deaddata->keycode,1); + do_keycode(deaddata->keycode,0); + restore_modifiers(); + } + } + set_modifiers(eventdata->keymod,1,0); + } + + do_keycode(eventdata->keycode,down); + + if (!down) + restore_modifiers(); } static void framebuffer_update_request(VncState *vs, int incremental, --- qemu-old/vnc_keysym.h Sun Apr 30 23:28:36 2006 +++ qemu-new/vnc_keysym.h Tue Aug 08 23:39:35 2006 @@ -247,6 +247,33 @@ {"F14", 0xffcb}, /* XK_F14 */ {"F15", 0xffcc}, /* XK_F15 */ {"Sys_Req", 0xff15}, /* XK_Sys_Req */ +{"KP_Space", 0xff80}, /* XK_KP_Space */ +{"KP_Tab", 0xff89}, /* XK_KP_Tab */ +{"KP_Enter", 0xff8d}, /* XK_KP_Enter */ +{"KP_F1", 0xff91}, /* XK_KP_F1 */ +{"KP_F2", 0xff92}, /* XK_KP_F2 */ +{"KP_F3", 0xff93}, /* XK_KP_F3 */ +{"KP_F4", 0xff94}, /* XK_KP_F4 */ +{"KP_Home", 0xff95}, /* XK_KP_Home */ +{"KP_Left", 0xff96}, /* XK_KP_Left */ +{"KP_Up", 0xff97}, /* XK_KP_Up */ +{"KP_Right", 0xff98}, /* XK_KP_Right */ +{"KP_Down", 0xff99}, /* XK_KP_Down */ +{"KP_Prior", 0xff9a}, /* XK_KP_Prior */ +{"KP_Page_Up", 0xff9a}, /* XK_KP_Page_Up */ +{"KP_Next", 0xff9b}, /* XK_KP_Next */ +{"KP_Page_Down", 0xff9b}, /* XK_KP_Page_Down */ +{"KP_End", 0xff9c}, /* XK_KP_End */ +{"KP_Begin", 0xff9d}, /* XK_KP_Begin */ +{"KP_Insert", 0xff9e}, /* XK_KP_Insert */ +{"KP_Delete", 0xff9f}, /* XK_KP_Delete */ +{"KP_Equal", 0xffbd}, /* XK_KP_Equal */ +{"KP_Multiply", 0xffaa}, /* XK_KP_Multiply */ +{"KP_Add", 0xffab}, /* XK_KP_Add */ +{"KP_Separator", 0xffac}, /* XK_KP_Separator */ +{"KP_Subtract", 0xffad}, /* XK_KP_Subtract */ +{"KP_Decimal", 0xffae}, /* XK_KP_Decimal */ +{"KP_Divide", 0xffaf}, /* XK_KP_Divide */ {"KP_0", 0xffb0}, /* XK_KP_0 */ {"KP_1", 0xffb1}, /* XK_KP_1 */ {"KP_2", 0xffb2}, /* XK_KP_2 */ @@ -257,13 +284,6 @@ {"KP_7", 0xffb7}, /* XK_KP_7 */ {"KP_8", 0xffb8}, /* XK_KP_8 */ {"KP_9", 0xffb9}, /* XK_KP_9 */ -{"KP_Add", 0xffab}, /* XK_KP_Add */ -{"KP_Decimal", 0xffae}, /* XK_KP_Decimal */ -{"KP_Divide", 0xffaf}, /* XK_KP_Divide */ -{"KP_Enter", 0xff8d}, /* XK_KP_Enter */ -{"KP_Equal", 0xffbd}, /* XK_KP_Equal */ -{"KP_Multiply", 0xffaa}, /* XK_KP_Multiply */ -{"KP_Subtract", 0xffad}, /* XK_KP_Subtract */ {"help", 0xff6a}, /* XK_Help */ {"Menu", 0xff67}, /* XK_Menu */ {"Print", 0xff61}, /* XK_Print */ @@ -271,5 +291,27 @@ {"Num_Lock", 0xff7f}, /* XK_Num_Lock */ {"Pause", 0xff13}, /* XK_Pause */ {"Escape", 0xff1b}, /* XK_Escape */ + +/* dead keys */ +{"dead_grave", 0xfe50}, /* XK_dead_grave */ +{"dead_acute", 0xfe51}, /* XK_dead_acute */ +{"dead_circumflex", 0xfe52}, /* XK_dead_circumflex */ +{"dead_tilde", 0xfe53}, /* XK_dead_tilde */ +{"dead_macron", 0xfe54}, /* XK_dead_macron */ +{"dead_breve", 0xfe55}, /* XK_dead_breve */ +{"dead_abovedot", 0xfe56}, /* XK_dead_abovedot */ +{"dead_diaeresis", 0xfe57}, /* XK_dead_diaeresis */ +{"dead_abovering", 0xfe58}, /* XK_dead_abovering */ +{"dead_doubleacute", 0xfe59}, /* XK_dead_doubleacute */ +{"dead_caron", 0xfe5a}, /* XK_dead_caron */ +{"dead_cedilla", 0xfe5b}, /* XK_dead_cedilla */ +{"dead_ogonek", 0xfe5c}, /* XK_dead_ogonek */ +{"dead_iota", 0xfe5d}, /* XK_dead_iota */ +{"dead_voiced_sound", 0xfe5e}, /* XK_dead_voiced_sound */ +{"dead_semivoiced_sound", 0xfe5f}, /* XK_dead_semivoiced_sound */ +{"dead_belowdot", 0xfe60}, /* XK_dead_belowdot */ +{"dead_hook", 0xfe61}, /* XK_dead_hook */ +{"dead_horn", 0xfe62}, /* XK_dead_horn */ + {0,0}, };