void wskbd_get_mapentry(const struct wskbd_mapdata *mapdata, int kc, struct wscons_keymap *mapentry) { kbd_t cur; const keysym_t *kp; const struct wscons_keydesc *mp; int l; keysym_t ksg; mapentry->command = KS_voidSymbol; mapentry->group1[0] = KS_voidSymbol; mapentry->group1[1] = KS_voidSymbol; mapentry->group2[0] = KS_voidSymbol; mapentry->group2[1] = KS_voidSymbol; for (cur = mapdata->layout & ~KB_HANDLEDBYWSKBD; cur != 0; ) { mp = mapdata->keydesc; while (mp->map_size > 0) { if (mp->name == cur) break; mp++; } /* If map not found, return */ if (mp->map_size <= 0) return; for (kp = mp->map; kp < mp->map + mp->map_size; kp++) { ksg = KS_GROUP(*kp); if (ksg == KS_GROUP_Keycode && KS_VALUE(*kp) == kc) { /* First skip keycode and possible command */ kp++; if (KS_GROUP(*kp) == KS_GROUP_Command || *kp == KS_Cmd || *kp == KS_Cmd1 || *kp == KS_Cmd2) mapentry->command = *kp++; for (l = 0; kp + l < mp->map + mp->map_size; l++) { ksg = KS_GROUP(kp[l]); if (ksg == KS_GROUP_Keycode) break; } if (l > 4) panic("wskbd_get_mapentry: %d(%d): bad entry", mp->name, *kp); fillmapentry(kp, l, mapentry); return; } } cur = mp->base; } }
/* * Console interface. */ int wskbd_cngetc(dev_t dev) { static int num = 0; static int pos; u_int type; int data; keysym_t ks; if (!wskbd_console_initted) return 0; if (wskbd_console_device != NULL && !wskbd_console_device->sc_translating) return 0; for(;;) { if (num-- > 0) { ks = wskbd_console_data.t_symbols[pos++]; if (KS_GROUP(ks) == KS_GROUP_Ascii) return (KS_VALUE(ks)); } else { (*wskbd_console_data.t_consops->getc) (wskbd_console_data.t_consaccesscookie, &type, &data); num = wskbd_translate(&wskbd_console_data, type, data); pos = 0; } } }
keysym_t ksym_upcase(keysym_t ksym) { if (ksym >= KS_f1 && ksym <= KS_f20) return(KS_F1 - KS_f1 + ksym); if (KS_GROUP(ksym) == KS_GROUP_Ascii && ksym <= 0xff && latin1_to_upper[ksym] != 0x00) return(latin1_to_upper[ksym]); return(ksym); }
/* * Console interface. */ int wskbd_cngetc(dev_t dev) { static int num = 0; static int pos; u_int type; int data; keysym_t ks; if (!wskbd_console_initted) return 0; if (wskbd_console_device != NULL && !wskbd_console_device->sc_translating) return 0; for(;;) { if (num-- > 0) { ks = wskbd_console_data.t_symbols[pos++]; if (KS_GROUP(ks) == KS_GROUP_Plain) return (KS_VALUE(ks)); } else { (*wskbd_console_data.t_consops->getc) (wskbd_console_data.t_consaccesscookie, &type, &data); if (type == WSCONS_EVENT_ASCII) { /* * We assume that when the driver falls back * to deliver pure ASCII it is in a state that * it can not track press/release events * reliable - so we clear all previously * accumulated modifier state. */ wskbd_console_data.t_modifiers = 0; return(data); } num = wskbd_translate(&wskbd_console_data, type, data); pos = 0; } } }
int wsemul_sun_translate(void *cookie, kbd_t layout, keysym_t in, const u_char **out) { struct wsemul_sun_emuldata *edp = cookie; if (KS_GROUP(in) == KS_GROUP_Ascii) { *out = edp->translatebuf; return (wsemul_utf8_translate(KS_VALUE(in), layout, edp->translatebuf, edp->flags & SUN_EMUL_FLAGS_UTF8)); } if (KS_GROUP(in) == KS_GROUP_Keypad && (in & 0x80) == 0) { edp->translatebuf[0] = in & 0xff; /* turn into ASCII */ *out = edp->translatebuf; return (1); } if (in >= KS_f1 && in <= KS_f12) { *out = sun_fkeys[in - KS_f1]; return (6); } if (in >= KS_F1 && in <= KS_F12) { *out = sun_fkeys[in - KS_F1]; return (6); } if (in >= KS_KP_F1 && in <= KS_KP_F4) { *out = sun_fkeys[in - KS_KP_F1]; return (6); } if (in >= KS_Help && in <= KS_Cut && sun_lkeys[in - KS_Help] != NULL) { *out = sun_lkeys[in - KS_Help]; return (6); } switch (in) { case KS_Home: case KS_KP_Home: case KS_KP_Begin: *out = "\033[214z"; return (6); case KS_End: case KS_KP_End: *out = "\033[220z"; return (6); case KS_Insert: case KS_KP_Insert: *out = "\033[247z"; return (6); case KS_Prior: case KS_KP_Prior: *out = "\033[216z"; return (6); case KS_Next: case KS_KP_Next: *out = "\033[222z"; return (6); case KS_Up: case KS_KP_Up: *out = "\033[A"; return (3); case KS_Down: case KS_KP_Down: *out = "\033[B"; return (3); case KS_Left: case KS_KP_Left: *out = "\033[D"; return (3); case KS_Right: case KS_KP_Right: *out = "\033[C"; return (3); case KS_KP_Delete: *out = "\177"; return (1); } return (0); }
int wskbd_load_keymap(const struct wskbd_mapdata *mapdata, struct wscons_keymap **map, int *maplen) { int i, s, kc, stack_ptr; const keysym_t *kp; const struct wscons_keydesc *mp, *stack[10]; kbd_t cur; keysym_t ksg; for (cur = mapdata->layout & ~KB_HANDLEDBYWSKBD, stack_ptr = 0; cur != 0; stack_ptr++) { mp = mapdata->keydesc; while (mp->map_size > 0) { if (cur == 0 || mp->name == cur) { break; } mp++; } if (stack_ptr == nitems(stack)) panic("wskbd_load_keymap: %d: recursion too deep", mapdata->layout); if (mp->map_size <= 0) return(EINVAL); stack[stack_ptr] = mp; cur = mp->base; } for (i = 0, s = stack_ptr - 1; s >= 0; s--) { mp = stack[s]; for (kp = mp->map; kp < mp->map + mp->map_size; kp++) { ksg = KS_GROUP(*kp); if (ksg == KS_GROUP_Keycode && KS_VALUE(*kp) > i) i = KS_VALUE(*kp); } } wskbd_init_keymap(i + 1, map, maplen); for (s = stack_ptr - 1; s >= 0; s--) { mp = stack[s]; for (kp = mp->map; kp < mp->map + mp->map_size; ) { ksg = KS_GROUP(*kp); if (ksg != KS_GROUP_Keycode) panic("wskbd_load_keymap: %d(%d): bad entry", mp->name, *kp); kc = KS_VALUE(*kp); kp++; if (KS_GROUP(*kp) == KS_GROUP_Command || *kp == KS_Cmd || *kp == KS_Cmd1 || *kp == KS_Cmd2) { (*map)[kc].command = *kp; kp++; } for (i = 0; kp + i < mp->map + mp->map_size; i++) { ksg = KS_GROUP(kp[i]); if (ksg == KS_GROUP_Keycode) break; } if (i > 4) panic("wskbd_load_keymap: %d(%d): bad entry", mp->name, *kp); fillmapentry(kp, i, &(*map)[kc]); kp += i; } } return(0); }
int wskbd_translate(struct wskbd_internal *id, u_int type, int value) { struct wskbd_softc *sc = id->t_sc; keysym_t ksym, res, *group; struct wscons_keymap kpbuf, *kp; int gindex, iscommand = 0; if (type == WSCONS_EVENT_ALL_KEYS_UP) { #if NWSDISPLAY > 0 if (sc != NULL && sc->sc_repeating) { sc->sc_repeating = 0; timeout_del(&sc->sc_repeat_ch); } #endif id->t_modifiers &= ~(MOD_SHIFT_L | MOD_SHIFT_R | MOD_CONTROL_L | MOD_CONTROL_R | MOD_META_L | MOD_META_R | MOD_MODESHIFT | MOD_MODELOCK | MOD_COMMAND | MOD_COMMAND1 | MOD_COMMAND2); return (0); } if (sc != NULL) { if (value < 0 || value >= sc->sc_maplen) { #ifdef DEBUG printf("wskbd_translate: keycode %d out of range\n", value); #endif return (0); } kp = sc->sc_map + value; } else { kp = &kpbuf; wskbd_get_mapentry(&id->t_keymap, value, kp); } /* if this key has a command, process it first */ if (sc != NULL && kp->command != KS_voidSymbol) iscommand = internal_command(sc, &type, kp->command, kp->group1[0]); /* Now update modifiers */ switch (kp->group1[0]) { case KS_Shift_L: update_modifier(id, type, 0, MOD_SHIFT_L); break; case KS_Shift_R: update_modifier(id, type, 0, MOD_SHIFT_R); break; case KS_Shift_Lock: update_modifier(id, type, 1, MOD_SHIFTLOCK); break; case KS_Caps_Lock: update_modifier(id, type, 1, MOD_CAPSLOCK); break; case KS_Control_L: update_modifier(id, type, 0, MOD_CONTROL_L); break; case KS_Control_R: update_modifier(id, type, 0, MOD_CONTROL_R); break; case KS_Alt_L: update_modifier(id, type, 0, MOD_META_L); break; case KS_Alt_R: update_modifier(id, type, 0, MOD_META_R); break; case KS_Mode_switch: update_modifier(id, type, 0, MOD_MODESHIFT); break; case KS_Mode_Lock: update_modifier(id, type, 1, MOD_MODELOCK); break; case KS_Num_Lock: update_modifier(id, type, 1, MOD_NUMLOCK); break; #if NWSDISPLAY > 0 case KS_Hold_Screen: if (sc != NULL) { update_modifier(id, type, 1, MOD_HOLDSCREEN); if (sc->sc_displaydv != NULL) wsdisplay_kbdholdscreen(sc->sc_displaydv, id->t_modifiers & MOD_HOLDSCREEN); } break; default: if (sc != NULL && sc->sc_repeating && ((type == WSCONS_EVENT_KEY_UP && value != sc->sc_repkey) || (type == WSCONS_EVENT_KEY_DOWN && value == sc->sc_repkey))) return (0); break; #endif } #if NWSDISPLAY > 0 if (sc != NULL) { if (sc->sc_repeating) { sc->sc_repeating = 0; timeout_del(&sc->sc_repeat_ch); } sc->sc_repkey = value; } #endif /* If this is a key release or we are in command mode, we are done */ if (type != WSCONS_EVENT_KEY_DOWN || iscommand) return (0); /* Get the keysym */ if (id->t_modifiers & (MOD_MODESHIFT|MOD_MODELOCK) && !MOD_ONESET(id, MOD_ANYCONTROL)) group = & kp->group2[0]; else group = & kp->group1[0]; if ((id->t_modifiers & MOD_NUMLOCK) && KS_GROUP(group[1]) == KS_GROUP_Keypad) { gindex = !MOD_ONESET(id, MOD_ANYSHIFT); ksym = group[gindex]; } else { /* CAPS alone should only affect letter keys */ if ((id->t_modifiers & (MOD_CAPSLOCK | MOD_ANYSHIFT)) == MOD_CAPSLOCK) { gindex = 0; ksym = ksym_upcase(group[0]); } else { gindex = MOD_ONESET(id, MOD_ANYSHIFT); ksym = group[gindex]; } } /* Submit Audio keys for hotkey processing */ if (KS_GROUP(ksym) == KS_GROUP_Function) { switch (ksym) { #if NAUDIO > 0 case KS_AudioMute: wskbd_set_mixervolume(0, 1); return (0); case KS_AudioLower: wskbd_set_mixervolume(-1, 1); return (0); case KS_AudioRaise: wskbd_set_mixervolume(1, 1); return (0); #endif default: break; } } /* Process compose sequence and dead accents */ res = KS_voidSymbol; switch (KS_GROUP(ksym)) { case KS_GROUP_Ascii: case KS_GROUP_Keypad: case KS_GROUP_Function: res = ksym; break; case KS_GROUP_Mod: if (ksym == KS_Multi_key) { update_modifier(id, 1, 0, MOD_COMPOSE); id->t_composelen = 2; } break; case KS_GROUP_Dead: if (id->t_composelen == 0) { update_modifier(id, 1, 0, MOD_COMPOSE); id->t_composelen = 1; id->t_composebuf[0] = ksym; } else res = ksym; break; } if (res == KS_voidSymbol) return (0); if (id->t_composelen > 0) { /* * If the compose key also serves as AltGr (i.e. set to both * KS_Multi_key and KS_Mode_switch), and would provide a valid, * distinct combination as AltGr, leave compose mode. */ if (id->t_composelen == 2 && group == &kp->group2[0]) { if (kp->group1[gindex] != kp->group2[gindex]) id->t_composelen = 0; } if (id->t_composelen != 0) { id->t_composebuf[2 - id->t_composelen] = res; if (--id->t_composelen == 0) { res = wskbd_compose_value(id->t_composebuf); update_modifier(id, 0, 0, MOD_COMPOSE); } else { return (0); } } } /* We are done, return the symbol */ if (KS_GROUP(res) == KS_GROUP_Ascii) { if (MOD_ONESET(id, MOD_ANYCONTROL)) { if ((res >= KS_at && res <= KS_z) || res == KS_space) res = res & 0x1f; else if (res == KS_2) res = 0x00; else if (res >= KS_3 && res <= KS_7) res = KS_Escape + (res - KS_3); else if (res == KS_8) res = KS_Delete; } if (MOD_ONESET(id, MOD_ANYMETA)) { if (id->t_flags & WSKFL_METAESC) { id->t_symbols[0] = KS_Escape; id->t_symbols[1] = res; return (2); } else res |= 0x80; } } id->t_symbols[0] = res; return (1); }
int wsemul_sun_translate(void *cookie, keysym_t in, const char **out) { static char c; if (KS_GROUP(in) == KS_GROUP_Keypad && (in & 0x80) == 0) { c = in & 0xff; /* turn into ASCII */ *out = &c; return (1); } if (in >= KS_f1 && in <= KS_f12) { *out = sun_fkeys[in - KS_f1]; return (6); } if (in >= KS_F1 && in <= KS_F12) { *out = sun_fkeys[in - KS_F1]; return (6); } if (in >= KS_KP_F1 && in <= KS_KP_F4) { *out = sun_fkeys[in - KS_KP_F1]; return (6); } if (in >= KS_Help && in <= KS_Cut && sun_lkeys[in - KS_Help] != NULL) { *out = sun_lkeys[in - KS_Help]; return (6); } switch (in) { case KS_Home: case KS_KP_Home: case KS_KP_Begin: *out = "\033[214z"; return (6); case KS_End: case KS_KP_End: *out = "\033[220z"; return (6); case KS_Insert: case KS_KP_Insert: *out = "\033[247z"; return (6); case KS_Prior: case KS_KP_Prior: *out = "\033[216z"; return (6); case KS_Next: case KS_KP_Next: *out = "\033[222z"; return (6); case KS_Up: case KS_KP_Up: *out = "\033[A"; return (3); case KS_Down: case KS_KP_Down: *out = "\033[B"; return (3); case KS_Left: case KS_KP_Left: *out = "\033[D"; return (3); case KS_Right: case KS_KP_Right: *out = "\033[C"; return (3); case KS_KP_Delete: *out = "\177"; return (1); } return (0); }
static int wskbd_translate(struct wskbd_internal *id, u_int type, int value) { struct wskbd_softc *sc = id->t_sc; keysym_t ksym, res, *group; struct wscons_keymap kpbuf, *kp; int iscommand = 0; int ishotkey = 0; if (type == WSCONS_EVENT_ALL_KEYS_UP) { id->t_modifiers &= ~(MOD_SHIFT_L | MOD_SHIFT_R | MOD_CONTROL_L | MOD_CONTROL_R | MOD_META_L | MOD_META_R | MOD_MODESHIFT | MOD_COMMAND | MOD_COMMAND1 | MOD_COMMAND2); update_leds(id); return (0); } if (sc != NULL) { if (sc->sc_hotkey != NULL) ishotkey = sc->sc_hotkey(sc, sc->sc_hotkeycookie, type, value); if (ishotkey) return 0; if (value < 0 || value >= sc->sc_maplen) { #ifdef DEBUG printf("%s: keycode %d out of range\n", __func__, value); #endif return (0); } kp = sc->sc_map + value; } else { kp = &kpbuf; wskbd_get_mapentry(id->t_keymap, value, kp); } /* if this key has a command, process it first */ if (sc != NULL && kp->command != KS_voidSymbol) iscommand = internal_command(sc, &type, kp->command, kp->group1[0]); /* Now update modifiers */ switch (kp->group1[0]) { case KS_Shift_L: update_modifier(id, type, 0, MOD_SHIFT_L); break; case KS_Shift_R: update_modifier(id, type, 0, MOD_SHIFT_R); break; case KS_Shift_Lock: update_modifier(id, type, 1, MOD_SHIFTLOCK); break; case KS_Caps_Lock: update_modifier(id, type, 1, MOD_CAPSLOCK); break; case KS_Control_L: update_modifier(id, type, 0, MOD_CONTROL_L); break; case KS_Control_R: update_modifier(id, type, 0, MOD_CONTROL_R); break; case KS_Alt_L: update_modifier(id, type, 0, MOD_META_L); break; case KS_Alt_R: update_modifier(id, type, 0, MOD_META_R); break; case KS_Mode_switch: update_modifier(id, type, 0, MOD_MODESHIFT); break; case KS_Num_Lock: update_modifier(id, type, 1, MOD_NUMLOCK); break; #if NWSDISPLAY > 0 case KS_Hold_Screen: if (sc != NULL) { update_modifier(id, type, 1, MOD_HOLDSCREEN); wskbd_holdscreen(sc, id->t_modifiers & MOD_HOLDSCREEN); } break; #endif } /* If this is a key release or we are in command mode, we are done */ if (type != WSCONS_EVENT_KEY_DOWN || iscommand) { update_leds(id); return (0); } /* Get the keysym */ if (id->t_modifiers & MOD_MODESHIFT) group = & kp->group2[0]; else group = & kp->group1[0]; if ((id->t_modifiers & MOD_NUMLOCK) != 0 && KS_GROUP(group[1]) == KS_GROUP_Keypad) { if (MOD_ONESET(id, MOD_ANYSHIFT)) ksym = group[0]; else ksym = group[1]; } else if (! MOD_ONESET(id, MOD_ANYSHIFT | MOD_CAPSLOCK)) { ksym = group[0]; } else if (MOD_ONESET(id, MOD_CAPSLOCK)) { if (! MOD_ONESET(id, MOD_SHIFT_L | MOD_SHIFT_R)) ksym = group[0]; else ksym = group[1]; if (ksym >= KS_a && ksym <= KS_z) ksym += KS_A - KS_a; else if (ksym >= KS_agrave && ksym <= KS_thorn && ksym != KS_division) ksym += KS_Agrave - KS_agrave; } else if (MOD_ONESET(id, MOD_ANYSHIFT)) { ksym = group[1]; } else { ksym = group[0]; } /* Process compose sequence and dead accents */ res = KS_voidSymbol; switch (KS_GROUP(ksym)) { case KS_GROUP_Plain: case KS_GROUP_Keypad: case KS_GROUP_Function: res = ksym; break; case KS_GROUP_Mod: if (ksym == KS_Multi_key) { update_modifier(id, 1, 0, MOD_COMPOSE); id->t_composelen = 2; } break; case KS_GROUP_Dead: if (id->t_composelen == 0) { update_modifier(id, 1, 0, MOD_COMPOSE); id->t_composelen = 1; id->t_composebuf[0] = ksym; } else res = ksym; break; } if (res == KS_voidSymbol) { update_leds(id); return (0); } if (id->t_composelen > 0) { id->t_composebuf[2 - id->t_composelen] = res; if (--id->t_composelen == 0) { res = wskbd_compose_value(id->t_composebuf); update_modifier(id, 0, 0, MOD_COMPOSE); } else { return (0); } } update_leds(id); /* We are done, return the symbol */ if (KS_GROUP(res) == KS_GROUP_Plain) { if (MOD_ONESET(id, MOD_ANYCONTROL)) { if ((res >= KS_at && res <= KS_z) || res == KS_space) res = res & 0x1f; else if (res == KS_2) res = 0x00; else if (res >= KS_3 && res <= KS_7) res = KS_Escape + (res - KS_3); else if (res == KS_8) res = KS_Delete; /* convert CTL-/ to ^_ as xterm does (undo in emacs) */ else if (res == KS_slash) res = KS_underscore & 0x1f; } if (MOD_ONESET(id, MOD_ANYMETA)) { if (id->t_flags & WSKFL_METAESC) { id->t_symbols[0] = KS_Escape; id->t_symbols[1] = res; return (2); } else res |= 0x80; } } id->t_symbols[0] = res; return (1); }