Пример #1
0
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;
	}
}
Пример #2
0
/*
 * 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;
		}
	}
}
Пример #3
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);
}
Пример #4
0
/*
 * 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;
		}
	}
}
Пример #5
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);
}
Пример #6
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);
}
Пример #7
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);
}
Пример #8
0
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);
}
Пример #9
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);
}