mirror of
				https://github.com/tmux/tmux.git
				synced 2025-10-26 12:27:15 +00:00 
			
		
		
		
	Merge branch 'master' into sixel
This commit is contained in:
		
							
								
								
									
										694
									
								
								tty-keys.c
									
									
									
									
									
								
							
							
						
						
									
										694
									
								
								tty-keys.c
									
									
									
									
									
								
							| @@ -21,6 +21,7 @@ | ||||
|  | ||||
| #include <netinet/in.h> | ||||
|  | ||||
| #include <ctype.h> | ||||
| #include <limits.h> | ||||
| #include <resolv.h> | ||||
| #include <stdlib.h> | ||||
| @@ -46,61 +47,98 @@ static struct tty_key *tty_keys_find(struct tty *, const char *, size_t, | ||||
| static int	tty_keys_next1(struct tty *, const char *, size_t, key_code *, | ||||
| 		    size_t *, int); | ||||
| static void	tty_keys_callback(int, short, void *); | ||||
| static int	tty_keys_extended_key(struct tty *, const char *, size_t, | ||||
| 		    size_t *, key_code *); | ||||
| static int	tty_keys_mouse(struct tty *, const char *, size_t, size_t *, | ||||
| 		    struct mouse_event *); | ||||
| static int	tty_keys_clipboard(struct tty *, const char *, size_t, | ||||
| 		    size_t *); | ||||
| static int	tty_keys_device_attributes(struct tty *, const char *, size_t, | ||||
| 		    size_t *); | ||||
| static int	tty_keys_device_status_report(struct tty *, const char *, | ||||
| static int	tty_keys_extended_device_attributes(struct tty *, const char *, | ||||
| 		    size_t, size_t *); | ||||
|  | ||||
| /* A key tree entry. */ | ||||
| struct tty_key { | ||||
| 	char		 ch; | ||||
| 	key_code	 key; | ||||
|  | ||||
| 	struct tty_key	*left; | ||||
| 	struct tty_key	*right; | ||||
|  | ||||
| 	struct tty_key	*next; | ||||
| }; | ||||
|  | ||||
| /* Default raw keys. */ | ||||
| struct tty_default_key_raw { | ||||
| 	const char	       *string; | ||||
| 	key_code	 	key; | ||||
| 	key_code		key; | ||||
| }; | ||||
| static const struct tty_default_key_raw tty_default_raw_keys[] = { | ||||
| 	/* Application escape. */ | ||||
| 	{ "\033O[", '\033' }, | ||||
|  | ||||
| 	/* | ||||
| 	 * Numeric keypad. Just use the vt100 escape sequences here and always | ||||
| 	 * put the terminal into keypad_xmit mode. Translation of numbers | ||||
| 	 * mode/applications mode is done in input-keys.c. | ||||
| 	 */ | ||||
| 	{ "\033Oo", KEYC_KP_SLASH }, | ||||
| 	{ "\033Oj", KEYC_KP_STAR }, | ||||
| 	{ "\033Om", KEYC_KP_MINUS }, | ||||
| 	{ "\033Ow", KEYC_KP_SEVEN }, | ||||
| 	{ "\033Ox", KEYC_KP_EIGHT }, | ||||
| 	{ "\033Oy", KEYC_KP_NINE }, | ||||
| 	{ "\033Ok", KEYC_KP_PLUS }, | ||||
| 	{ "\033Ot", KEYC_KP_FOUR }, | ||||
| 	{ "\033Ou", KEYC_KP_FIVE }, | ||||
| 	{ "\033Ov", KEYC_KP_SIX }, | ||||
| 	{ "\033Oq", KEYC_KP_ONE }, | ||||
| 	{ "\033Or", KEYC_KP_TWO }, | ||||
| 	{ "\033Os", KEYC_KP_THREE }, | ||||
| 	{ "\033OM", KEYC_KP_ENTER }, | ||||
| 	{ "\033Op", KEYC_KP_ZERO }, | ||||
| 	{ "\033On", KEYC_KP_PERIOD }, | ||||
| 	{ "\033Oo", KEYC_KP_SLASH|KEYC_KEYPAD }, | ||||
| 	{ "\033Oj", KEYC_KP_STAR|KEYC_KEYPAD }, | ||||
| 	{ "\033Om", KEYC_KP_MINUS|KEYC_KEYPAD }, | ||||
| 	{ "\033Ow", KEYC_KP_SEVEN|KEYC_KEYPAD }, | ||||
| 	{ "\033Ox", KEYC_KP_EIGHT|KEYC_KEYPAD }, | ||||
| 	{ "\033Oy", KEYC_KP_NINE|KEYC_KEYPAD }, | ||||
| 	{ "\033Ok", KEYC_KP_PLUS|KEYC_KEYPAD }, | ||||
| 	{ "\033Ot", KEYC_KP_FOUR|KEYC_KEYPAD }, | ||||
| 	{ "\033Ou", KEYC_KP_FIVE|KEYC_KEYPAD }, | ||||
| 	{ "\033Ov", KEYC_KP_SIX|KEYC_KEYPAD }, | ||||
| 	{ "\033Oq", KEYC_KP_ONE|KEYC_KEYPAD }, | ||||
| 	{ "\033Or", KEYC_KP_TWO|KEYC_KEYPAD }, | ||||
| 	{ "\033Os", KEYC_KP_THREE|KEYC_KEYPAD }, | ||||
| 	{ "\033OM", KEYC_KP_ENTER|KEYC_KEYPAD }, | ||||
| 	{ "\033Op", KEYC_KP_ZERO|KEYC_KEYPAD }, | ||||
| 	{ "\033On", KEYC_KP_PERIOD|KEYC_KEYPAD }, | ||||
|  | ||||
| 	/* Arrow keys. */ | ||||
| 	{ "\033OA", KEYC_UP }, | ||||
| 	{ "\033OB", KEYC_DOWN }, | ||||
| 	{ "\033OC", KEYC_RIGHT }, | ||||
| 	{ "\033OD", KEYC_LEFT }, | ||||
| 	{ "\033OA", KEYC_UP|KEYC_CURSOR }, | ||||
| 	{ "\033OB", KEYC_DOWN|KEYC_CURSOR }, | ||||
| 	{ "\033OC", KEYC_RIGHT|KEYC_CURSOR }, | ||||
| 	{ "\033OD", KEYC_LEFT|KEYC_CURSOR }, | ||||
|  | ||||
| 	{ "\033[A", KEYC_UP }, | ||||
| 	{ "\033[B", KEYC_DOWN }, | ||||
| 	{ "\033[C", KEYC_RIGHT }, | ||||
| 	{ "\033[D", KEYC_LEFT }, | ||||
| 	{ "\033[A", KEYC_UP|KEYC_CURSOR }, | ||||
| 	{ "\033[B", KEYC_DOWN|KEYC_CURSOR }, | ||||
| 	{ "\033[C", KEYC_RIGHT|KEYC_CURSOR }, | ||||
| 	{ "\033[D", KEYC_LEFT|KEYC_CURSOR }, | ||||
|  | ||||
| 	/* | ||||
| 	 * Meta arrow keys. These do not get the IMPLIED_META flag so they | ||||
| 	 * don't match the xterm-style meta keys in the output tree - Escape+Up | ||||
| 	 * should stay as Escape+Up and not become M-Up. | ||||
| 	 */ | ||||
| 	{ "\033\033OA", KEYC_UP|KEYC_CURSOR|KEYC_META }, | ||||
| 	{ "\033\033OB", KEYC_DOWN|KEYC_CURSOR|KEYC_META }, | ||||
| 	{ "\033\033OC", KEYC_RIGHT|KEYC_CURSOR|KEYC_META }, | ||||
| 	{ "\033\033OD", KEYC_LEFT|KEYC_CURSOR|KEYC_META }, | ||||
|  | ||||
| 	{ "\033\033[A", KEYC_UP|KEYC_CURSOR|KEYC_META }, | ||||
| 	{ "\033\033[B", KEYC_DOWN|KEYC_CURSOR|KEYC_META }, | ||||
| 	{ "\033\033[C", KEYC_RIGHT|KEYC_CURSOR|KEYC_META }, | ||||
| 	{ "\033\033[D", KEYC_LEFT|KEYC_CURSOR|KEYC_META }, | ||||
|  | ||||
| 	/* Other (xterm) "cursor" keys. */ | ||||
| 	{ "\033OH", KEYC_HOME }, | ||||
| 	{ "\033OF", KEYC_END }, | ||||
|  | ||||
| 	{ "\033\033OH", KEYC_HOME|KEYC_META|KEYC_IMPLIED_META }, | ||||
| 	{ "\033\033OF", KEYC_END|KEYC_META|KEYC_IMPLIED_META }, | ||||
|  | ||||
| 	{ "\033[H", KEYC_HOME }, | ||||
| 	{ "\033[F", KEYC_END }, | ||||
|  | ||||
| 	{ "\033\033[H", KEYC_HOME|KEYC_META|KEYC_IMPLIED_META }, | ||||
| 	{ "\033\033[F", KEYC_END|KEYC_META|KEYC_IMPLIED_META }, | ||||
|  | ||||
| 	/* rxvt-style arrow + modifier keys. */ | ||||
| 	{ "\033Oa", KEYC_UP|KEYC_CTRL }, | ||||
| 	{ "\033Ob", KEYC_DOWN|KEYC_CTRL }, | ||||
| @@ -179,15 +217,64 @@ static const struct tty_default_key_raw tty_default_raw_keys[] = { | ||||
| 	{ "\033[201~", KEYC_PASTE_END }, | ||||
| }; | ||||
|  | ||||
| /* Default xterm keys. */ | ||||
| struct tty_default_key_xterm { | ||||
| 	const char	*template; | ||||
| 	key_code	 key; | ||||
| }; | ||||
| static const struct tty_default_key_xterm tty_default_xterm_keys[] = { | ||||
| 	{ "\033[1;_P", KEYC_F1 }, | ||||
| 	{ "\033O1;_P", KEYC_F1 }, | ||||
| 	{ "\033O_P", KEYC_F1 }, | ||||
| 	{ "\033[1;_Q", KEYC_F2 }, | ||||
| 	{ "\033O1;_Q", KEYC_F2 }, | ||||
| 	{ "\033O_Q", KEYC_F2 }, | ||||
| 	{ "\033[1;_R", KEYC_F3 }, | ||||
| 	{ "\033O1;_R", KEYC_F3 }, | ||||
| 	{ "\033O_R", KEYC_F3 }, | ||||
| 	{ "\033[1;_S", KEYC_F4 }, | ||||
| 	{ "\033O1;_S", KEYC_F4 }, | ||||
| 	{ "\033O_S", KEYC_F4 }, | ||||
| 	{ "\033[15;_~", KEYC_F5 }, | ||||
| 	{ "\033[17;_~", KEYC_F6 }, | ||||
| 	{ "\033[18;_~", KEYC_F7 }, | ||||
| 	{ "\033[19;_~", KEYC_F8 }, | ||||
| 	{ "\033[20;_~", KEYC_F9 }, | ||||
| 	{ "\033[21;_~", KEYC_F10 }, | ||||
| 	{ "\033[23;_~", KEYC_F11 }, | ||||
| 	{ "\033[24;_~", KEYC_F12 }, | ||||
| 	{ "\033[1;_A", KEYC_UP }, | ||||
| 	{ "\033[1;_B", KEYC_DOWN }, | ||||
| 	{ "\033[1;_C", KEYC_RIGHT }, | ||||
| 	{ "\033[1;_D", KEYC_LEFT }, | ||||
| 	{ "\033[1;_H", KEYC_HOME }, | ||||
| 	{ "\033[1;_F", KEYC_END }, | ||||
| 	{ "\033[5;_~", KEYC_PPAGE }, | ||||
| 	{ "\033[6;_~", KEYC_NPAGE }, | ||||
| 	{ "\033[2;_~", KEYC_IC }, | ||||
| 	{ "\033[3;_~", KEYC_DC }, | ||||
| }; | ||||
| static const key_code tty_default_xterm_modifiers[] = { | ||||
| 	0, | ||||
| 	0, | ||||
| 	KEYC_SHIFT, | ||||
| 	KEYC_META|KEYC_IMPLIED_META, | ||||
| 	KEYC_SHIFT|KEYC_META|KEYC_IMPLIED_META, | ||||
| 	KEYC_CTRL, | ||||
| 	KEYC_SHIFT|KEYC_CTRL, | ||||
| 	KEYC_META|KEYC_IMPLIED_META|KEYC_CTRL, | ||||
| 	KEYC_SHIFT|KEYC_META|KEYC_IMPLIED_META|KEYC_CTRL, | ||||
| 	KEYC_META|KEYC_IMPLIED_META | ||||
| }; | ||||
|  | ||||
| /* | ||||
|  * Default terminfo(5) keys. Any keys that have builtin modifiers | ||||
|  * (that is, where the key itself contains the modifiers) has the | ||||
|  * KEYC_XTERM flag set so a leading escape is not treated as meta (and | ||||
|  * probably removed). | ||||
|  * Default terminfo(5) keys. Any keys that have builtin modifiers (that is, | ||||
|  * where the key itself contains the modifiers) has the KEYC_XTERM flag set so | ||||
|  * a leading escape is not treated as meta (and probably removed). | ||||
|  */ | ||||
| struct tty_default_key_code { | ||||
| 	enum tty_code_code	code; | ||||
| 	key_code	 	key; | ||||
| 	key_code		key; | ||||
| }; | ||||
| static const struct tty_default_key_code tty_default_code_keys[] = { | ||||
| 	/* Function keys. */ | ||||
| @@ -204,61 +291,61 @@ static const struct tty_default_key_code tty_default_code_keys[] = { | ||||
| 	{ TTYC_KF11, KEYC_F11 }, | ||||
| 	{ TTYC_KF12, KEYC_F12 }, | ||||
|  | ||||
| 	{ TTYC_KF13, KEYC_F1|KEYC_SHIFT|KEYC_XTERM }, | ||||
| 	{ TTYC_KF14, KEYC_F2|KEYC_SHIFT|KEYC_XTERM }, | ||||
| 	{ TTYC_KF15, KEYC_F3|KEYC_SHIFT|KEYC_XTERM }, | ||||
| 	{ TTYC_KF16, KEYC_F4|KEYC_SHIFT|KEYC_XTERM }, | ||||
| 	{ TTYC_KF17, KEYC_F5|KEYC_SHIFT|KEYC_XTERM }, | ||||
| 	{ TTYC_KF18, KEYC_F6|KEYC_SHIFT|KEYC_XTERM }, | ||||
| 	{ TTYC_KF19, KEYC_F7|KEYC_SHIFT|KEYC_XTERM }, | ||||
| 	{ TTYC_KF20, KEYC_F8|KEYC_SHIFT|KEYC_XTERM }, | ||||
| 	{ TTYC_KF21, KEYC_F9|KEYC_SHIFT|KEYC_XTERM }, | ||||
| 	{ TTYC_KF22, KEYC_F10|KEYC_SHIFT|KEYC_XTERM }, | ||||
| 	{ TTYC_KF23, KEYC_F11|KEYC_SHIFT|KEYC_XTERM }, | ||||
| 	{ TTYC_KF24, KEYC_F12|KEYC_SHIFT|KEYC_XTERM }, | ||||
| 	{ TTYC_KF13, KEYC_F1|KEYC_SHIFT }, | ||||
| 	{ TTYC_KF14, KEYC_F2|KEYC_SHIFT }, | ||||
| 	{ TTYC_KF15, KEYC_F3|KEYC_SHIFT }, | ||||
| 	{ TTYC_KF16, KEYC_F4|KEYC_SHIFT }, | ||||
| 	{ TTYC_KF17, KEYC_F5|KEYC_SHIFT }, | ||||
| 	{ TTYC_KF18, KEYC_F6|KEYC_SHIFT }, | ||||
| 	{ TTYC_KF19, KEYC_F7|KEYC_SHIFT }, | ||||
| 	{ TTYC_KF20, KEYC_F8|KEYC_SHIFT }, | ||||
| 	{ TTYC_KF21, KEYC_F9|KEYC_SHIFT }, | ||||
| 	{ TTYC_KF22, KEYC_F10|KEYC_SHIFT }, | ||||
| 	{ TTYC_KF23, KEYC_F11|KEYC_SHIFT }, | ||||
| 	{ TTYC_KF24, KEYC_F12|KEYC_SHIFT }, | ||||
|  | ||||
| 	{ TTYC_KF25, KEYC_F1|KEYC_CTRL|KEYC_XTERM }, | ||||
| 	{ TTYC_KF26, KEYC_F2|KEYC_CTRL|KEYC_XTERM }, | ||||
| 	{ TTYC_KF27, KEYC_F3|KEYC_CTRL|KEYC_XTERM }, | ||||
| 	{ TTYC_KF28, KEYC_F4|KEYC_CTRL|KEYC_XTERM }, | ||||
| 	{ TTYC_KF29, KEYC_F5|KEYC_CTRL|KEYC_XTERM }, | ||||
| 	{ TTYC_KF30, KEYC_F6|KEYC_CTRL|KEYC_XTERM }, | ||||
| 	{ TTYC_KF31, KEYC_F7|KEYC_CTRL|KEYC_XTERM }, | ||||
| 	{ TTYC_KF32, KEYC_F8|KEYC_CTRL|KEYC_XTERM }, | ||||
| 	{ TTYC_KF33, KEYC_F9|KEYC_CTRL|KEYC_XTERM }, | ||||
| 	{ TTYC_KF34, KEYC_F10|KEYC_CTRL|KEYC_XTERM }, | ||||
| 	{ TTYC_KF35, KEYC_F11|KEYC_CTRL|KEYC_XTERM }, | ||||
| 	{ TTYC_KF36, KEYC_F12|KEYC_CTRL|KEYC_XTERM }, | ||||
| 	{ TTYC_KF25, KEYC_F1|KEYC_CTRL }, | ||||
| 	{ TTYC_KF26, KEYC_F2|KEYC_CTRL }, | ||||
| 	{ TTYC_KF27, KEYC_F3|KEYC_CTRL }, | ||||
| 	{ TTYC_KF28, KEYC_F4|KEYC_CTRL }, | ||||
| 	{ TTYC_KF29, KEYC_F5|KEYC_CTRL }, | ||||
| 	{ TTYC_KF30, KEYC_F6|KEYC_CTRL }, | ||||
| 	{ TTYC_KF31, KEYC_F7|KEYC_CTRL }, | ||||
| 	{ TTYC_KF32, KEYC_F8|KEYC_CTRL }, | ||||
| 	{ TTYC_KF33, KEYC_F9|KEYC_CTRL }, | ||||
| 	{ TTYC_KF34, KEYC_F10|KEYC_CTRL }, | ||||
| 	{ TTYC_KF35, KEYC_F11|KEYC_CTRL }, | ||||
| 	{ TTYC_KF36, KEYC_F12|KEYC_CTRL }, | ||||
|  | ||||
| 	{ TTYC_KF37, KEYC_F1|KEYC_SHIFT|KEYC_CTRL|KEYC_XTERM }, | ||||
| 	{ TTYC_KF38, KEYC_F2|KEYC_SHIFT|KEYC_CTRL|KEYC_XTERM }, | ||||
| 	{ TTYC_KF39, KEYC_F3|KEYC_SHIFT|KEYC_CTRL|KEYC_XTERM }, | ||||
| 	{ TTYC_KF40, KEYC_F4|KEYC_SHIFT|KEYC_CTRL|KEYC_XTERM }, | ||||
| 	{ TTYC_KF41, KEYC_F5|KEYC_SHIFT|KEYC_CTRL|KEYC_XTERM }, | ||||
| 	{ TTYC_KF42, KEYC_F6|KEYC_SHIFT|KEYC_CTRL|KEYC_XTERM }, | ||||
| 	{ TTYC_KF43, KEYC_F7|KEYC_SHIFT|KEYC_CTRL|KEYC_XTERM }, | ||||
| 	{ TTYC_KF44, KEYC_F8|KEYC_SHIFT|KEYC_CTRL|KEYC_XTERM }, | ||||
| 	{ TTYC_KF45, KEYC_F9|KEYC_SHIFT|KEYC_CTRL|KEYC_XTERM }, | ||||
| 	{ TTYC_KF46, KEYC_F10|KEYC_SHIFT|KEYC_CTRL|KEYC_XTERM }, | ||||
| 	{ TTYC_KF47, KEYC_F11|KEYC_SHIFT|KEYC_CTRL|KEYC_XTERM }, | ||||
| 	{ TTYC_KF48, KEYC_F12|KEYC_SHIFT|KEYC_CTRL|KEYC_XTERM }, | ||||
| 	{ TTYC_KF37, KEYC_F1|KEYC_SHIFT|KEYC_CTRL }, | ||||
| 	{ TTYC_KF38, KEYC_F2|KEYC_SHIFT|KEYC_CTRL }, | ||||
| 	{ TTYC_KF39, KEYC_F3|KEYC_SHIFT|KEYC_CTRL }, | ||||
| 	{ TTYC_KF40, KEYC_F4|KEYC_SHIFT|KEYC_CTRL }, | ||||
| 	{ TTYC_KF41, KEYC_F5|KEYC_SHIFT|KEYC_CTRL }, | ||||
| 	{ TTYC_KF42, KEYC_F6|KEYC_SHIFT|KEYC_CTRL }, | ||||
| 	{ TTYC_KF43, KEYC_F7|KEYC_SHIFT|KEYC_CTRL }, | ||||
| 	{ TTYC_KF44, KEYC_F8|KEYC_SHIFT|KEYC_CTRL }, | ||||
| 	{ TTYC_KF45, KEYC_F9|KEYC_SHIFT|KEYC_CTRL }, | ||||
| 	{ TTYC_KF46, KEYC_F10|KEYC_SHIFT|KEYC_CTRL }, | ||||
| 	{ TTYC_KF47, KEYC_F11|KEYC_SHIFT|KEYC_CTRL }, | ||||
| 	{ TTYC_KF48, KEYC_F12|KEYC_SHIFT|KEYC_CTRL }, | ||||
|  | ||||
| 	{ TTYC_KF49, KEYC_F1|KEYC_ESCAPE|KEYC_XTERM }, | ||||
| 	{ TTYC_KF50, KEYC_F2|KEYC_ESCAPE|KEYC_XTERM }, | ||||
| 	{ TTYC_KF51, KEYC_F3|KEYC_ESCAPE|KEYC_XTERM }, | ||||
| 	{ TTYC_KF52, KEYC_F4|KEYC_ESCAPE|KEYC_XTERM }, | ||||
| 	{ TTYC_KF53, KEYC_F5|KEYC_ESCAPE|KEYC_XTERM }, | ||||
| 	{ TTYC_KF54, KEYC_F6|KEYC_ESCAPE|KEYC_XTERM }, | ||||
| 	{ TTYC_KF55, KEYC_F7|KEYC_ESCAPE|KEYC_XTERM }, | ||||
| 	{ TTYC_KF56, KEYC_F8|KEYC_ESCAPE|KEYC_XTERM }, | ||||
| 	{ TTYC_KF57, KEYC_F9|KEYC_ESCAPE|KEYC_XTERM }, | ||||
| 	{ TTYC_KF58, KEYC_F10|KEYC_ESCAPE|KEYC_XTERM }, | ||||
| 	{ TTYC_KF59, KEYC_F11|KEYC_ESCAPE|KEYC_XTERM }, | ||||
| 	{ TTYC_KF60, KEYC_F12|KEYC_ESCAPE|KEYC_XTERM }, | ||||
| 	{ TTYC_KF49, KEYC_F1|KEYC_META|KEYC_IMPLIED_META }, | ||||
| 	{ TTYC_KF50, KEYC_F2|KEYC_META|KEYC_IMPLIED_META }, | ||||
| 	{ TTYC_KF51, KEYC_F3|KEYC_META|KEYC_IMPLIED_META }, | ||||
| 	{ TTYC_KF52, KEYC_F4|KEYC_META|KEYC_IMPLIED_META }, | ||||
| 	{ TTYC_KF53, KEYC_F5|KEYC_META|KEYC_IMPLIED_META }, | ||||
| 	{ TTYC_KF54, KEYC_F6|KEYC_META|KEYC_IMPLIED_META }, | ||||
| 	{ TTYC_KF55, KEYC_F7|KEYC_META|KEYC_IMPLIED_META }, | ||||
| 	{ TTYC_KF56, KEYC_F8|KEYC_META|KEYC_IMPLIED_META }, | ||||
| 	{ TTYC_KF57, KEYC_F9|KEYC_META|KEYC_IMPLIED_META }, | ||||
| 	{ TTYC_KF58, KEYC_F10|KEYC_META|KEYC_IMPLIED_META }, | ||||
| 	{ TTYC_KF59, KEYC_F11|KEYC_META|KEYC_IMPLIED_META }, | ||||
| 	{ TTYC_KF60, KEYC_F12|KEYC_META|KEYC_IMPLIED_META }, | ||||
|  | ||||
| 	{ TTYC_KF61, KEYC_F1|KEYC_ESCAPE|KEYC_SHIFT|KEYC_XTERM }, | ||||
| 	{ TTYC_KF62, KEYC_F2|KEYC_ESCAPE|KEYC_SHIFT|KEYC_XTERM }, | ||||
| 	{ TTYC_KF63, KEYC_F3|KEYC_ESCAPE|KEYC_SHIFT|KEYC_XTERM }, | ||||
| 	{ TTYC_KF61, KEYC_F1|KEYC_META|KEYC_IMPLIED_META|KEYC_SHIFT }, | ||||
| 	{ TTYC_KF62, KEYC_F2|KEYC_META|KEYC_IMPLIED_META|KEYC_SHIFT }, | ||||
| 	{ TTYC_KF63, KEYC_F3|KEYC_META|KEYC_IMPLIED_META|KEYC_SHIFT }, | ||||
|  | ||||
| 	{ TTYC_KICH1, KEYC_IC }, | ||||
| 	{ TTYC_KDCH1, KEYC_DC }, | ||||
| @@ -269,74 +356,74 @@ static const struct tty_default_key_code tty_default_code_keys[] = { | ||||
| 	{ TTYC_KCBT, KEYC_BTAB }, | ||||
|  | ||||
| 	/* Arrow keys from terminfo. */ | ||||
| 	{ TTYC_KCUU1, KEYC_UP }, | ||||
| 	{ TTYC_KCUD1, KEYC_DOWN }, | ||||
| 	{ TTYC_KCUB1, KEYC_LEFT }, | ||||
| 	{ TTYC_KCUF1, KEYC_RIGHT }, | ||||
| 	{ TTYC_KCUU1, KEYC_UP|KEYC_CURSOR }, | ||||
| 	{ TTYC_KCUD1, KEYC_DOWN|KEYC_CURSOR }, | ||||
| 	{ TTYC_KCUB1, KEYC_LEFT|KEYC_CURSOR }, | ||||
| 	{ TTYC_KCUF1, KEYC_RIGHT|KEYC_CURSOR }, | ||||
|  | ||||
| 	/* Key and modifier capabilities. */ | ||||
| 	{ TTYC_KDC2, KEYC_DC|KEYC_SHIFT|KEYC_XTERM }, | ||||
| 	{ TTYC_KDC3, KEYC_DC|KEYC_ESCAPE|KEYC_XTERM }, | ||||
| 	{ TTYC_KDC4, KEYC_DC|KEYC_SHIFT|KEYC_ESCAPE|KEYC_XTERM }, | ||||
| 	{ TTYC_KDC5, KEYC_DC|KEYC_CTRL|KEYC_XTERM }, | ||||
| 	{ TTYC_KDC6, KEYC_DC|KEYC_SHIFT|KEYC_CTRL|KEYC_XTERM }, | ||||
| 	{ TTYC_KDC7, KEYC_DC|KEYC_ESCAPE|KEYC_CTRL|KEYC_XTERM }, | ||||
| 	{ TTYC_KIND, KEYC_DOWN|KEYC_SHIFT|KEYC_XTERM }, | ||||
| 	{ TTYC_KDN2, KEYC_DOWN|KEYC_SHIFT|KEYC_XTERM }, | ||||
| 	{ TTYC_KDN3, KEYC_DOWN|KEYC_ESCAPE|KEYC_XTERM }, | ||||
| 	{ TTYC_KDN4, KEYC_DOWN|KEYC_SHIFT|KEYC_ESCAPE|KEYC_XTERM }, | ||||
| 	{ TTYC_KDN5, KEYC_DOWN|KEYC_CTRL|KEYC_XTERM }, | ||||
| 	{ TTYC_KDN6, KEYC_DOWN|KEYC_SHIFT|KEYC_CTRL|KEYC_XTERM }, | ||||
| 	{ TTYC_KDN7, KEYC_DOWN|KEYC_ESCAPE|KEYC_CTRL|KEYC_XTERM }, | ||||
| 	{ TTYC_KEND2, KEYC_END|KEYC_SHIFT|KEYC_XTERM }, | ||||
| 	{ TTYC_KEND3, KEYC_END|KEYC_ESCAPE|KEYC_XTERM }, | ||||
| 	{ TTYC_KEND4, KEYC_END|KEYC_SHIFT|KEYC_ESCAPE|KEYC_XTERM }, | ||||
| 	{ TTYC_KEND5, KEYC_END|KEYC_CTRL|KEYC_XTERM }, | ||||
| 	{ TTYC_KEND6, KEYC_END|KEYC_SHIFT|KEYC_CTRL|KEYC_XTERM }, | ||||
| 	{ TTYC_KEND7, KEYC_END|KEYC_ESCAPE|KEYC_CTRL|KEYC_XTERM }, | ||||
| 	{ TTYC_KHOM2, KEYC_HOME|KEYC_SHIFT|KEYC_XTERM }, | ||||
| 	{ TTYC_KHOM3, KEYC_HOME|KEYC_ESCAPE|KEYC_XTERM }, | ||||
| 	{ TTYC_KHOM4, KEYC_HOME|KEYC_SHIFT|KEYC_ESCAPE|KEYC_XTERM }, | ||||
| 	{ TTYC_KHOM5, KEYC_HOME|KEYC_CTRL|KEYC_XTERM }, | ||||
| 	{ TTYC_KHOM6, KEYC_HOME|KEYC_SHIFT|KEYC_CTRL|KEYC_XTERM }, | ||||
| 	{ TTYC_KHOM7, KEYC_HOME|KEYC_ESCAPE|KEYC_CTRL|KEYC_XTERM }, | ||||
| 	{ TTYC_KIC2, KEYC_IC|KEYC_SHIFT|KEYC_XTERM }, | ||||
| 	{ TTYC_KIC3, KEYC_IC|KEYC_ESCAPE|KEYC_XTERM }, | ||||
| 	{ TTYC_KIC4, KEYC_IC|KEYC_SHIFT|KEYC_ESCAPE|KEYC_XTERM }, | ||||
| 	{ TTYC_KIC5, KEYC_IC|KEYC_CTRL|KEYC_XTERM }, | ||||
| 	{ TTYC_KIC6, KEYC_IC|KEYC_SHIFT|KEYC_CTRL|KEYC_XTERM }, | ||||
| 	{ TTYC_KIC7, KEYC_IC|KEYC_ESCAPE|KEYC_CTRL|KEYC_XTERM }, | ||||
| 	{ TTYC_KLFT2, KEYC_LEFT|KEYC_SHIFT|KEYC_XTERM }, | ||||
| 	{ TTYC_KLFT3, KEYC_LEFT|KEYC_ESCAPE|KEYC_XTERM }, | ||||
| 	{ TTYC_KLFT4, KEYC_LEFT|KEYC_SHIFT|KEYC_ESCAPE|KEYC_XTERM }, | ||||
| 	{ TTYC_KLFT5, KEYC_LEFT|KEYC_CTRL|KEYC_XTERM }, | ||||
| 	{ TTYC_KLFT6, KEYC_LEFT|KEYC_SHIFT|KEYC_CTRL|KEYC_XTERM }, | ||||
| 	{ TTYC_KLFT7, KEYC_LEFT|KEYC_ESCAPE|KEYC_CTRL|KEYC_XTERM }, | ||||
| 	{ TTYC_KNXT2, KEYC_NPAGE|KEYC_SHIFT|KEYC_XTERM }, | ||||
| 	{ TTYC_KNXT3, KEYC_NPAGE|KEYC_ESCAPE|KEYC_XTERM }, | ||||
| 	{ TTYC_KNXT4, KEYC_NPAGE|KEYC_SHIFT|KEYC_ESCAPE|KEYC_XTERM }, | ||||
| 	{ TTYC_KNXT5, KEYC_NPAGE|KEYC_CTRL|KEYC_XTERM }, | ||||
| 	{ TTYC_KNXT6, KEYC_NPAGE|KEYC_SHIFT|KEYC_CTRL|KEYC_XTERM }, | ||||
| 	{ TTYC_KNXT7, KEYC_NPAGE|KEYC_ESCAPE|KEYC_CTRL|KEYC_XTERM }, | ||||
| 	{ TTYC_KPRV2, KEYC_PPAGE|KEYC_SHIFT|KEYC_XTERM }, | ||||
| 	{ TTYC_KPRV3, KEYC_PPAGE|KEYC_ESCAPE|KEYC_XTERM }, | ||||
| 	{ TTYC_KPRV4, KEYC_PPAGE|KEYC_SHIFT|KEYC_ESCAPE|KEYC_XTERM }, | ||||
| 	{ TTYC_KPRV5, KEYC_PPAGE|KEYC_CTRL|KEYC_XTERM }, | ||||
| 	{ TTYC_KPRV6, KEYC_PPAGE|KEYC_SHIFT|KEYC_CTRL|KEYC_XTERM }, | ||||
| 	{ TTYC_KPRV7, KEYC_PPAGE|KEYC_ESCAPE|KEYC_CTRL|KEYC_XTERM }, | ||||
| 	{ TTYC_KRIT2, KEYC_RIGHT|KEYC_SHIFT|KEYC_XTERM }, | ||||
| 	{ TTYC_KRIT3, KEYC_RIGHT|KEYC_ESCAPE|KEYC_XTERM }, | ||||
| 	{ TTYC_KRIT4, KEYC_RIGHT|KEYC_SHIFT|KEYC_ESCAPE|KEYC_XTERM }, | ||||
| 	{ TTYC_KRIT5, KEYC_RIGHT|KEYC_CTRL|KEYC_XTERM }, | ||||
| 	{ TTYC_KRIT6, KEYC_RIGHT|KEYC_SHIFT|KEYC_CTRL|KEYC_XTERM }, | ||||
| 	{ TTYC_KRIT7, KEYC_RIGHT|KEYC_ESCAPE|KEYC_CTRL|KEYC_XTERM }, | ||||
| 	{ TTYC_KRI, KEYC_UP|KEYC_SHIFT|KEYC_XTERM }, | ||||
| 	{ TTYC_KUP2, KEYC_UP|KEYC_SHIFT|KEYC_XTERM }, | ||||
| 	{ TTYC_KUP3, KEYC_UP|KEYC_ESCAPE|KEYC_XTERM }, | ||||
| 	{ TTYC_KUP4, KEYC_UP|KEYC_SHIFT|KEYC_ESCAPE|KEYC_XTERM }, | ||||
| 	{ TTYC_KUP5, KEYC_UP|KEYC_CTRL|KEYC_XTERM }, | ||||
| 	{ TTYC_KUP6, KEYC_UP|KEYC_SHIFT|KEYC_CTRL|KEYC_XTERM }, | ||||
| 	{ TTYC_KUP7, KEYC_UP|KEYC_ESCAPE|KEYC_CTRL|KEYC_XTERM }, | ||||
| 	{ TTYC_KDC2, KEYC_DC|KEYC_SHIFT }, | ||||
| 	{ TTYC_KDC3, KEYC_DC|KEYC_META|KEYC_IMPLIED_META }, | ||||
| 	{ TTYC_KDC4, KEYC_DC|KEYC_SHIFT|KEYC_META|KEYC_IMPLIED_META }, | ||||
| 	{ TTYC_KDC5, KEYC_DC|KEYC_CTRL }, | ||||
| 	{ TTYC_KDC6, KEYC_DC|KEYC_SHIFT|KEYC_CTRL }, | ||||
| 	{ TTYC_KDC7, KEYC_DC|KEYC_META|KEYC_IMPLIED_META|KEYC_CTRL }, | ||||
| 	{ TTYC_KIND, KEYC_DOWN|KEYC_SHIFT }, | ||||
| 	{ TTYC_KDN2, KEYC_DOWN|KEYC_SHIFT }, | ||||
| 	{ TTYC_KDN3, KEYC_DOWN|KEYC_META|KEYC_IMPLIED_META }, | ||||
| 	{ TTYC_KDN4, KEYC_DOWN|KEYC_SHIFT|KEYC_META|KEYC_IMPLIED_META }, | ||||
| 	{ TTYC_KDN5, KEYC_DOWN|KEYC_CTRL }, | ||||
| 	{ TTYC_KDN6, KEYC_DOWN|KEYC_SHIFT|KEYC_CTRL }, | ||||
| 	{ TTYC_KDN7, KEYC_DOWN|KEYC_META|KEYC_IMPLIED_META|KEYC_CTRL }, | ||||
| 	{ TTYC_KEND2, KEYC_END|KEYC_SHIFT }, | ||||
| 	{ TTYC_KEND3, KEYC_END|KEYC_META|KEYC_IMPLIED_META }, | ||||
| 	{ TTYC_KEND4, KEYC_END|KEYC_SHIFT|KEYC_META|KEYC_IMPLIED_META }, | ||||
| 	{ TTYC_KEND5, KEYC_END|KEYC_CTRL }, | ||||
| 	{ TTYC_KEND6, KEYC_END|KEYC_SHIFT|KEYC_CTRL }, | ||||
| 	{ TTYC_KEND7, KEYC_END|KEYC_META|KEYC_IMPLIED_META|KEYC_CTRL }, | ||||
| 	{ TTYC_KHOM2, KEYC_HOME|KEYC_SHIFT }, | ||||
| 	{ TTYC_KHOM3, KEYC_HOME|KEYC_META|KEYC_IMPLIED_META }, | ||||
| 	{ TTYC_KHOM4, KEYC_HOME|KEYC_SHIFT|KEYC_META|KEYC_IMPLIED_META }, | ||||
| 	{ TTYC_KHOM5, KEYC_HOME|KEYC_CTRL }, | ||||
| 	{ TTYC_KHOM6, KEYC_HOME|KEYC_SHIFT|KEYC_CTRL }, | ||||
| 	{ TTYC_KHOM7, KEYC_HOME|KEYC_META|KEYC_IMPLIED_META|KEYC_CTRL }, | ||||
| 	{ TTYC_KIC2, KEYC_IC|KEYC_SHIFT }, | ||||
| 	{ TTYC_KIC3, KEYC_IC|KEYC_META|KEYC_IMPLIED_META }, | ||||
| 	{ TTYC_KIC4, KEYC_IC|KEYC_SHIFT|KEYC_META|KEYC_IMPLIED_META }, | ||||
| 	{ TTYC_KIC5, KEYC_IC|KEYC_CTRL }, | ||||
| 	{ TTYC_KIC6, KEYC_IC|KEYC_SHIFT|KEYC_CTRL }, | ||||
| 	{ TTYC_KIC7, KEYC_IC|KEYC_META|KEYC_IMPLIED_META|KEYC_CTRL }, | ||||
| 	{ TTYC_KLFT2, KEYC_LEFT|KEYC_SHIFT }, | ||||
| 	{ TTYC_KLFT3, KEYC_LEFT|KEYC_META|KEYC_IMPLIED_META }, | ||||
| 	{ TTYC_KLFT4, KEYC_LEFT|KEYC_SHIFT|KEYC_META|KEYC_IMPLIED_META }, | ||||
| 	{ TTYC_KLFT5, KEYC_LEFT|KEYC_CTRL }, | ||||
| 	{ TTYC_KLFT6, KEYC_LEFT|KEYC_SHIFT|KEYC_CTRL }, | ||||
| 	{ TTYC_KLFT7, KEYC_LEFT|KEYC_META|KEYC_IMPLIED_META|KEYC_CTRL }, | ||||
| 	{ TTYC_KNXT2, KEYC_NPAGE|KEYC_SHIFT }, | ||||
| 	{ TTYC_KNXT3, KEYC_NPAGE|KEYC_META|KEYC_IMPLIED_META }, | ||||
| 	{ TTYC_KNXT4, KEYC_NPAGE|KEYC_SHIFT|KEYC_META|KEYC_IMPLIED_META }, | ||||
| 	{ TTYC_KNXT5, KEYC_NPAGE|KEYC_CTRL }, | ||||
| 	{ TTYC_KNXT6, KEYC_NPAGE|KEYC_SHIFT|KEYC_CTRL }, | ||||
| 	{ TTYC_KNXT7, KEYC_NPAGE|KEYC_META|KEYC_IMPLIED_META|KEYC_CTRL }, | ||||
| 	{ TTYC_KPRV2, KEYC_PPAGE|KEYC_SHIFT }, | ||||
| 	{ TTYC_KPRV3, KEYC_PPAGE|KEYC_META|KEYC_IMPLIED_META }, | ||||
| 	{ TTYC_KPRV4, KEYC_PPAGE|KEYC_SHIFT|KEYC_META|KEYC_IMPLIED_META }, | ||||
| 	{ TTYC_KPRV5, KEYC_PPAGE|KEYC_CTRL }, | ||||
| 	{ TTYC_KPRV6, KEYC_PPAGE|KEYC_SHIFT|KEYC_CTRL }, | ||||
| 	{ TTYC_KPRV7, KEYC_PPAGE|KEYC_META|KEYC_IMPLIED_META|KEYC_CTRL }, | ||||
| 	{ TTYC_KRIT2, KEYC_RIGHT|KEYC_SHIFT }, | ||||
| 	{ TTYC_KRIT3, KEYC_RIGHT|KEYC_META|KEYC_IMPLIED_META }, | ||||
| 	{ TTYC_KRIT4, KEYC_RIGHT|KEYC_SHIFT|KEYC_META|KEYC_IMPLIED_META }, | ||||
| 	{ TTYC_KRIT5, KEYC_RIGHT|KEYC_CTRL }, | ||||
| 	{ TTYC_KRIT6, KEYC_RIGHT|KEYC_SHIFT|KEYC_CTRL }, | ||||
| 	{ TTYC_KRIT7, KEYC_RIGHT|KEYC_META|KEYC_IMPLIED_META|KEYC_CTRL }, | ||||
| 	{ TTYC_KRI, KEYC_UP|KEYC_SHIFT }, | ||||
| 	{ TTYC_KUP2, KEYC_UP|KEYC_SHIFT }, | ||||
| 	{ TTYC_KUP3, KEYC_UP|KEYC_META|KEYC_IMPLIED_META }, | ||||
| 	{ TTYC_KUP4, KEYC_UP|KEYC_SHIFT|KEYC_META|KEYC_IMPLIED_META }, | ||||
| 	{ TTYC_KUP5, KEYC_UP|KEYC_CTRL }, | ||||
| 	{ TTYC_KUP6, KEYC_UP|KEYC_SHIFT|KEYC_CTRL }, | ||||
| 	{ TTYC_KUP7, KEYC_UP|KEYC_META|KEYC_IMPLIED_META|KEYC_CTRL }, | ||||
| }; | ||||
|  | ||||
| /* Add key to tree. */ | ||||
| @@ -345,9 +432,9 @@ tty_keys_add(struct tty *tty, const char *s, key_code key) | ||||
| { | ||||
| 	struct tty_key	*tk; | ||||
| 	size_t		 size; | ||||
| 	const char     	*keystr; | ||||
| 	const char	*keystr; | ||||
|  | ||||
| 	keystr = key_string_lookup_key(key); | ||||
| 	keystr = key_string_lookup_key(key, 1); | ||||
| 	if ((tk = tty_keys_find(tty, s, strlen(s), &size)) == NULL) { | ||||
| 		log_debug("new key %s: 0x%llx (%s)", s, key, keystr); | ||||
| 		tty_keys_add1(&tty->key_tree, s, key); | ||||
| @@ -400,17 +487,30 @@ void | ||||
| tty_keys_build(struct tty *tty) | ||||
| { | ||||
| 	const struct tty_default_key_raw	*tdkr; | ||||
| 	const struct tty_default_key_xterm	*tdkx; | ||||
| 	const struct tty_default_key_code	*tdkc; | ||||
| 	u_int		 			 i; | ||||
| 	u_int					 i, j; | ||||
| 	const char				*s; | ||||
| 	struct options_entry			*o; | ||||
| 	struct options_array_item		*a; | ||||
| 	union options_value			*ov; | ||||
| 	char					 copy[16]; | ||||
| 	key_code				 key; | ||||
|  | ||||
| 	if (tty->key_tree != NULL) | ||||
| 		tty_keys_free(tty); | ||||
| 	tty->key_tree = NULL; | ||||
|  | ||||
| 	for (i = 0; i < nitems(tty_default_xterm_keys); i++) { | ||||
| 		tdkx = &tty_default_xterm_keys[i]; | ||||
| 		for (j = 2; j < nitems(tty_default_xterm_modifiers); j++) { | ||||
| 			strlcpy(copy, tdkx->template, sizeof copy); | ||||
| 			copy[strcspn(copy, "_")] = '0' + j; | ||||
|  | ||||
| 			key = tdkx->key|tty_default_xterm_modifiers[j]; | ||||
| 			tty_keys_add(tty, copy, key); | ||||
| 		} | ||||
| 	} | ||||
| 	for (i = 0; i < nitems(tty_default_raw_keys); i++) { | ||||
| 		tdkr = &tty_default_raw_keys[i]; | ||||
|  | ||||
| @@ -511,9 +611,8 @@ tty_keys_next1(struct tty *tty, const char *buf, size_t len, key_code *key, | ||||
| 	struct tty_key		*tk, *tk1; | ||||
| 	struct utf8_data	 ud; | ||||
| 	enum utf8_state		 more; | ||||
| 	utf8_char		 uc; | ||||
| 	u_int			 i; | ||||
| 	wchar_t			 wc; | ||||
| 	int			 n; | ||||
|  | ||||
| 	log_debug("%s: next key is %zu (%.*s) (expired=%d)", c->name, len, | ||||
| 	    (int)len, buf, expired); | ||||
| @@ -531,13 +630,6 @@ tty_keys_next1(struct tty *tty, const char *buf, size_t len, key_code *key, | ||||
| 		return (0); | ||||
| 	} | ||||
|  | ||||
| 	/* Is this an an xterm(1) key? */ | ||||
| 	n = xterm_keys_find(buf, len, size, key); | ||||
| 	if (n == 0) | ||||
| 		return (0); | ||||
| 	if (n == 1 && !expired) | ||||
| 		return (1); | ||||
|  | ||||
| 	/* Is this valid UTF-8? */ | ||||
| 	more = utf8_open(&ud, (u_char)*buf); | ||||
| 	if (more == UTF8_MORE) { | ||||
| @@ -552,12 +644,12 @@ tty_keys_next1(struct tty *tty, const char *buf, size_t len, key_code *key, | ||||
| 		if (more != UTF8_DONE) | ||||
| 			return (-1); | ||||
|  | ||||
| 		if (utf8_combine(&ud, &wc) != UTF8_DONE) | ||||
| 		if (utf8_from_data(&ud, &uc) != UTF8_DONE) | ||||
| 			return (-1); | ||||
| 		*key = wc; | ||||
| 		*key = uc; | ||||
|  | ||||
| 		log_debug("%s: UTF-8 key %.*s %#llx", c->name, (int)ud.size, | ||||
| 		    buf, *key); | ||||
| 		    ud.data, *key); | ||||
| 		return (0); | ||||
| 	} | ||||
|  | ||||
| @@ -578,8 +670,6 @@ tty_keys_next(struct tty *tty) | ||||
| 	struct mouse_event	 m = { 0 }; | ||||
| 	struct key_event	*event; | ||||
|  | ||||
| 	gettimeofday(&tv, NULL); | ||||
|  | ||||
| 	/* Get key buffer. */ | ||||
| 	buf = EVBUFFER_DATA(tty->in); | ||||
| 	len = EVBUFFER_LENGTH(tty->in); | ||||
| @@ -609,8 +699,8 @@ tty_keys_next(struct tty *tty) | ||||
| 		goto partial_key; | ||||
| 	} | ||||
|  | ||||
| 	/* Is this a device status report response? */ | ||||
| 	switch (tty_keys_device_status_report(tty, buf, len, &size)) { | ||||
| 	/* Is this an extended device attributes response? */ | ||||
| 	switch (tty_keys_extended_device_attributes(tty, buf, len, &size)) { | ||||
| 	case 0:		/* yes */ | ||||
| 		key = KEYC_UNKNOWN; | ||||
| 		goto complete_key; | ||||
| @@ -634,6 +724,16 @@ tty_keys_next(struct tty *tty) | ||||
| 		goto partial_key; | ||||
| 	} | ||||
|  | ||||
| 	/* Is this an extended key press? */ | ||||
| 	switch (tty_keys_extended_key(tty, buf, len, &size, &key)) { | ||||
| 	case 0:		/* yes */ | ||||
| 		goto complete_key; | ||||
| 	case -1:	/* no, or not valid */ | ||||
| 		break; | ||||
| 	case 1:		/* partial */ | ||||
| 		goto partial_key; | ||||
| 	} | ||||
|  | ||||
| first_key: | ||||
| 	/* Try to lookup complete key. */ | ||||
| 	n = tty_keys_next1(tty, buf, len, &key, &size, expired); | ||||
| @@ -650,7 +750,7 @@ first_key: | ||||
| 		/* Look for a key without the escape. */ | ||||
| 		n = tty_keys_next1(tty, buf + 1, len - 1, &key, &size, expired); | ||||
| 		if (n == 0) {	/* found */ | ||||
| 			if (key & KEYC_XTERM) { | ||||
| 			if (key & KEYC_IMPLIED_META) { | ||||
| 				/* | ||||
| 				 * We want the escape key as well as the xterm | ||||
| 				 * key, because the xterm sequence implicitly | ||||
| @@ -662,7 +762,7 @@ first_key: | ||||
| 				size = 1; | ||||
| 				goto complete_key; | ||||
| 			} | ||||
| 			key |= KEYC_ESCAPE; | ||||
| 			key |= KEYC_META; | ||||
| 			size++; | ||||
| 			goto complete_key; | ||||
| 		} | ||||
| @@ -675,7 +775,7 @@ first_key: | ||||
| 	 * escape). So pass it through even if the timer has not expired. | ||||
| 	 */ | ||||
| 	if (*buf == '\033' && len >= 2) { | ||||
| 		key = (u_char)buf[1] | KEYC_ESCAPE; | ||||
| 		key = (u_char)buf[1] | KEYC_META; | ||||
| 		size = 2; | ||||
| 	} else { | ||||
| 		key = (u_char)buf[0]; | ||||
| @@ -720,7 +820,7 @@ complete_key: | ||||
| 	 */ | ||||
| 	bspace = tty->tio.c_cc[VERASE]; | ||||
| 	if (bspace != _POSIX_VDISABLE && (key & KEYC_MASK_KEY) == bspace) | ||||
| 		key = (key & KEYC_MASK_MOD) | KEYC_BSPACE; | ||||
| 		key = (key & KEYC_MASK_MODIFIERS)|KEYC_BSPACE; | ||||
|  | ||||
| 	/* Remove data from buffer. */ | ||||
| 	evbuffer_drain(tty->in, size); | ||||
| @@ -732,11 +832,13 @@ complete_key: | ||||
|  | ||||
| 	/* Check for focus events. */ | ||||
| 	if (key == KEYC_FOCUS_OUT) { | ||||
| 		tty->client->flags &= ~CLIENT_FOCUSED; | ||||
| 		return (1); | ||||
| 		c->flags &= ~CLIENT_FOCUSED; | ||||
| 		window_update_focus(c->session->curw->window); | ||||
| 		notify_client("client-focus-out", c); | ||||
| 	} else if (key == KEYC_FOCUS_IN) { | ||||
| 		tty->client->flags |= CLIENT_FOCUSED; | ||||
| 		return (1); | ||||
| 		c->flags |= CLIENT_FOCUSED; | ||||
| 		notify_client("client-focus-in", c); | ||||
| 		window_update_focus(c->session->curw->window); | ||||
| 	} | ||||
|  | ||||
| 	/* Fire the key. */ | ||||
| @@ -771,6 +873,134 @@ tty_keys_callback(__unused int fd, __unused short events, void *data) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| /* | ||||
|  * Handle extended key input. This has two forms: \033[27;m;k~ and \033[k;mu, | ||||
|  * where k is key as a number and m is a modifier. Returns 0 for success, -1 | ||||
|  * for failure, 1 for partial; | ||||
|  */ | ||||
| static int | ||||
| tty_keys_extended_key(struct tty *tty, const char *buf, size_t len, | ||||
|     size_t *size, key_code *key) | ||||
| { | ||||
| 	struct client	*c = tty->client; | ||||
| 	size_t		 end; | ||||
| 	u_int		 number, modifiers; | ||||
| 	char		 tmp[64]; | ||||
| 	cc_t		 bspace; | ||||
| 	key_code	 nkey; | ||||
| 	key_code	 onlykey; | ||||
|  | ||||
| 	*size = 0; | ||||
|  | ||||
| 	/* First two bytes are always \033[. */ | ||||
| 	if (buf[0] != '\033') | ||||
| 		return (-1); | ||||
| 	if (len == 1) | ||||
| 		return (1); | ||||
| 	if (buf[1] != '[') | ||||
| 		return (-1); | ||||
| 	if (len == 2) | ||||
| 		return (1); | ||||
|  | ||||
| 	/* | ||||
| 	 * Look for a terminator. Stop at either '~' or anything that isn't a | ||||
| 	 * number or ';'. | ||||
| 	 */ | ||||
| 	for (end = 2; end < len && end != sizeof tmp; end++) { | ||||
| 		if (buf[end] == '~') | ||||
| 			break; | ||||
| 		if (!isdigit((u_char)buf[end]) && buf[end] != ';') | ||||
| 			break; | ||||
| 	} | ||||
| 	if (end == len) | ||||
| 		return (1); | ||||
| 	if (end == sizeof tmp || (buf[end] != '~' && buf[end] != 'u')) | ||||
| 		return (-1); | ||||
|  | ||||
| 	/* Copy to the buffer. */ | ||||
| 	memcpy(tmp, buf + 2, end); | ||||
| 	tmp[end] = '\0'; | ||||
|  | ||||
| 	/* Try to parse either form of key. */ | ||||
| 	if (buf[end] == '~') { | ||||
| 		if (sscanf(tmp, "27;%u;%u", &modifiers, &number) != 2) | ||||
| 			return (-1); | ||||
| 	} else { | ||||
| 		if (sscanf(tmp ,"%u;%u", &number, &modifiers) != 2) | ||||
| 			return (-1); | ||||
| 	} | ||||
| 	*size = end + 1; | ||||
|  | ||||
| 	/* Store the key. */ | ||||
| 	bspace = tty->tio.c_cc[VERASE]; | ||||
| 	if (bspace != _POSIX_VDISABLE && number == bspace) | ||||
| 		nkey = KEYC_BSPACE; | ||||
| 	else | ||||
| 		nkey = number; | ||||
|  | ||||
| 	/* Update the modifiers. */ | ||||
| 	switch (modifiers) { | ||||
| 	case 2: | ||||
| 		nkey |= KEYC_SHIFT; | ||||
| 		break; | ||||
| 	case 3: | ||||
| 		nkey |= (KEYC_META|KEYC_IMPLIED_META); | ||||
| 		break; | ||||
| 	case 4: | ||||
| 		nkey |= (KEYC_SHIFT|KEYC_META|KEYC_IMPLIED_META); | ||||
| 		break; | ||||
| 	case 5: | ||||
| 		nkey |= KEYC_CTRL; | ||||
| 		break; | ||||
| 	case 6: | ||||
| 		nkey |= (KEYC_SHIFT|KEYC_CTRL); | ||||
| 		break; | ||||
| 	case 7: | ||||
| 		nkey |= (KEYC_META|KEYC_CTRL); | ||||
| 		break; | ||||
| 	case 8: | ||||
| 		nkey |= (KEYC_SHIFT|KEYC_META|KEYC_IMPLIED_META|KEYC_CTRL); | ||||
| 		break; | ||||
| 	case 9: | ||||
| 		nkey |= (KEYC_META|KEYC_IMPLIED_META); | ||||
| 		break; | ||||
| 	default: | ||||
| 		*key = KEYC_NONE; | ||||
| 		break; | ||||
| 	} | ||||
|  | ||||
| 	/* | ||||
| 	 * Don't allow both KEYC_CTRL and as an implied modifier. Also convert | ||||
| 	 * C-X into C-x and so on. | ||||
| 	 */ | ||||
| 	if (nkey & KEYC_CTRL) { | ||||
| 		onlykey = (nkey & KEYC_MASK_KEY); | ||||
| 		if (onlykey < 32 && | ||||
| 		    onlykey != 9 && | ||||
| 		    onlykey != 13 && | ||||
| 		    onlykey != 27) | ||||
| 			/* nothing */; | ||||
| 		else if (onlykey >= 97 && onlykey <= 122) | ||||
| 			onlykey -= 96; | ||||
| 		else if (onlykey >= 64 && onlykey <= 95) | ||||
| 			onlykey -= 64; | ||||
| 		else if (onlykey == 32) | ||||
| 			onlykey = 0; | ||||
| 		else if (onlykey == 63) | ||||
| 			onlykey = 127; | ||||
| 		else | ||||
| 			onlykey |= KEYC_CTRL; | ||||
| 		nkey = onlykey|((nkey & KEYC_MASK_MODIFIERS) & ~KEYC_CTRL); | ||||
| 	} | ||||
|  | ||||
| 	if (log_get_level() != 0) { | ||||
| 		log_debug("%s: extended key %.*s is %llx (%s)", c->name, | ||||
| 		    (int)*size, buf, nkey, key_string_lookup_key(nkey, 1)); | ||||
| 	} | ||||
| 	*key = nkey; | ||||
| 	return (0); | ||||
| } | ||||
|  | ||||
| /* | ||||
|  * Handle mouse key input. Returns 0 for success, -1 for failure, 1 for partial | ||||
|  * (probably a mouse sequence but need more data). | ||||
| @@ -933,7 +1163,7 @@ tty_keys_clipboard(__unused struct tty *tty, const char *buf, size_t len, | ||||
|  | ||||
| 	*size = 0; | ||||
|  | ||||
| 	/* First three bytes are always \033]52;. */ | ||||
| 	/* First five bytes are always \033]52;. */ | ||||
| 	if (buf[0] != '\033') | ||||
| 		return (-1); | ||||
| 	if (len == 1) | ||||
| @@ -1006,9 +1236,16 @@ tty_keys_clipboard(__unused struct tty *tty, const char *buf, size_t len, | ||||
| 	return (0); | ||||
| } | ||||
|  | ||||
| //XXX primary DA | ||||
| //	for (i = 1; i < n; i++) { | ||||
| //		log_debug("%s: DA feature: %d", c->name, p[i]); | ||||
| //		if (p[i] == 4) | ||||
| //			flags |= TERM_SIXEL; | ||||
| //	} | ||||
|  | ||||
| /* | ||||
|  * Handle device attributes input. Returns 0 for success, -1 for failure, 1 for | ||||
|  * partial. | ||||
|  * Handle secondary device attributes input. Returns 0 for success, -1 for | ||||
|  * failure, 1 for partial. | ||||
|  */ | ||||
| static int | ||||
| tty_keys_device_attributes(struct tty *tty, const char *buf, size_t len, | ||||
| @@ -1017,13 +1254,15 @@ tty_keys_device_attributes(struct tty *tty, const char *buf, size_t len, | ||||
| 	struct client	*c = tty->client; | ||||
| 	u_int		 i, n = 0; | ||||
| 	char		 tmp[64], *endptr, p[32] = { 0 }, *cp, *next; | ||||
| 	int		 flags = 0; | ||||
|  | ||||
| 	*size = 0; | ||||
| 	if (tty->flags & TTY_HAVEDA) | ||||
| 		return (-1); | ||||
|  | ||||
| 	/* First three bytes are always \033[?. */ | ||||
| 	/* | ||||
| 	 * First three bytes are always \033[>. Some older Terminal.app | ||||
| 	 * versions respond as for DA (\033[?) so accept and ignore that. | ||||
| 	 */ | ||||
| 	if (buf[0] != '\033') | ||||
| 		return (-1); | ||||
| 	if (len == 1) | ||||
| @@ -1032,15 +1271,17 @@ tty_keys_device_attributes(struct tty *tty, const char *buf, size_t len, | ||||
| 		return (-1); | ||||
| 	if (len == 2) | ||||
| 		return (1); | ||||
| 	if (buf[2] != '?') | ||||
| 	if (buf[2] != '>' && buf[2] != '?') | ||||
| 		return (-1); | ||||
| 	if (len == 3) | ||||
| 		return (1); | ||||
|  | ||||
| 	/* Copy the rest up to a 'c'. */ | ||||
| 	for (i = 0; i < (sizeof tmp) - 1 && buf[3 + i] != 'c'; i++) { | ||||
| 	for (i = 0; i < (sizeof tmp) - 1; i++) { | ||||
| 		if (3 + i == len) | ||||
| 			return (1); | ||||
| 		if (buf[3 + i] == 'c') | ||||
| 			break; | ||||
| 		tmp[i] = buf[3 + i]; | ||||
| 	} | ||||
| 	if (i == (sizeof tmp) - 1) | ||||
| @@ -1048,7 +1289,11 @@ tty_keys_device_attributes(struct tty *tty, const char *buf, size_t len, | ||||
| 	tmp[i] = '\0'; | ||||
| 	*size = 4 + i; | ||||
|  | ||||
| 	/* Convert version numbers. */ | ||||
| 	/* Ignore DA response. */ | ||||
| 	if (buf[2] == '?') | ||||
| 		return (0); | ||||
|  | ||||
| 	/* Convert all arguments to numbers. */ | ||||
| 	cp = tmp; | ||||
| 	while ((next = strsep(&cp, ";")) != NULL) { | ||||
| 		p[n] = strtoul(next, &endptr, 10); | ||||
| @@ -1057,75 +1302,92 @@ tty_keys_device_attributes(struct tty *tty, const char *buf, size_t len, | ||||
| 		n++; | ||||
| 	} | ||||
|  | ||||
| 	/* Set terminal flags. */ | ||||
| 	/* Add terminal features. */ | ||||
| 	switch (p[0]) { | ||||
| 	case 64: /* VT420 */ | ||||
| 		flags |= (TERM_DECFRA|TERM_DECSLRM); | ||||
| 	case 41: /* VT420 */ | ||||
| 		tty_add_features(&c->term_features, "margins,rectfill", ","); | ||||
| 		break; | ||||
| 	case 'M': /* mintty */ | ||||
| 		tty_default_features(&c->term_features, "mintty", 0); | ||||
| 		break; | ||||
| 	case 'T': /* tmux */ | ||||
| 		tty_default_features(&c->term_features, "tmux", 0); | ||||
| 		break; | ||||
| 	case 'U': /* rxvt-unicode */ | ||||
| 		tty_default_features(&c->term_features, "rxvt-unicode", 0); | ||||
| 		break; | ||||
| 	} | ||||
| 	for (i = 1; i < n; i++) { | ||||
| 		log_debug("%s: DA feature: %d", c->name, p[i]); | ||||
| 		if (p[i] == 4) | ||||
| 			flags |= TERM_SIXEL; | ||||
| 	} | ||||
| 	log_debug("%s: received secondary DA %.*s", c->name, (int)*size, buf); | ||||
|  | ||||
| 	tty_set_flags(tty, flags); | ||||
| 	tty_update_features(tty); | ||||
| 	tty->flags |= TTY_HAVEDA; | ||||
|  | ||||
| 	return (0); | ||||
| } | ||||
|  | ||||
| /* | ||||
|  * Handle device status report input. Returns 0 for success, -1 for failure, 1 | ||||
|  * for partial. | ||||
|  * Handle extended device attributes input. Returns 0 for success, -1 for | ||||
|  * failure, 1 for partial. | ||||
|  */ | ||||
| static int | ||||
| tty_keys_device_status_report(struct tty *tty, const char *buf, size_t len, | ||||
|     size_t *size) | ||||
| tty_keys_extended_device_attributes(struct tty *tty, const char *buf, | ||||
|     size_t len, size_t *size) | ||||
| { | ||||
| 	struct client	*c = tty->client; | ||||
| 	u_int		 i; | ||||
| 	char		 tmp[64]; | ||||
| 	int		 flags = 0; | ||||
| 	char		 tmp[128]; | ||||
|  | ||||
| 	*size = 0; | ||||
| 	if (tty->flags & TTY_HAVEDSR) | ||||
| 	if (tty->flags & TTY_HAVEXDA) | ||||
| 		return (-1); | ||||
|  | ||||
| 	/* First three bytes are always \033[. */ | ||||
| 	/* First four bytes are always \033P>|. */ | ||||
| 	if (buf[0] != '\033') | ||||
| 		return (-1); | ||||
| 	if (len == 1) | ||||
| 		return (1); | ||||
| 	if (buf[1] != '[') | ||||
| 	if (buf[1] != 'P') | ||||
| 		return (-1); | ||||
| 	if (len == 2) | ||||
| 		return (1); | ||||
| 	if (buf[2] != 'I' && buf[2] != 'T') | ||||
| 	if (buf[2] != '>') | ||||
| 		return (-1); | ||||
| 	if (len == 3) | ||||
| 		return (1); | ||||
| 	if (buf[3] != '|') | ||||
| 		return (-1); | ||||
| 	if (len == 4) | ||||
| 		return (1); | ||||
|  | ||||
| 	/* Copy the rest up to a 'n'. */ | ||||
| 	for (i = 0; i < (sizeof tmp) - 1 && buf[2 + i] != 'n'; i++) { | ||||
| 		if (2 + i == len) | ||||
| 	/* Copy the rest up to a '\033\\'. */ | ||||
| 	for (i = 0; i < (sizeof tmp) - 1; i++) { | ||||
| 		if (4 + i == len) | ||||
| 			return (1); | ||||
| 		tmp[i] = buf[2 + i]; | ||||
| 		if (buf[4 + i - 1] == '\033' && buf[4 + i] == '\\') | ||||
| 			break; | ||||
| 		tmp[i] = buf[4 + i]; | ||||
| 	} | ||||
| 	if (i == (sizeof tmp) - 1) | ||||
| 		return (-1); | ||||
| 	tmp[i] = '\0'; | ||||
| 	*size = 3 + i; | ||||
| 	tmp[i - 1] = '\0'; | ||||
| 	*size = 5 + i; | ||||
|  | ||||
| 	/* Set terminal flags. */ | ||||
| 	if (strncmp(tmp, "ITERM2 ", 7) == 0) | ||||
| 		flags |= (TERM_DECSLRM|TERM_256COLOURS|TERM_RGBCOLOURS); | ||||
| 	if (strncmp(tmp, "TMUX ", 5) == 0) | ||||
| 		flags |= (TERM_256COLOURS|TERM_RGBCOLOURS); | ||||
| 	log_debug("%s: received DSR %.*s", c->name, (int)*size, buf); | ||||
| 	/* Add terminal features. */ | ||||
| 	if (strncmp(tmp, "iTerm2 ", 7) == 0) | ||||
| 		tty_default_features(&c->term_features, "iTerm2", 0); | ||||
| 	else if (strncmp(tmp, "tmux ", 5) == 0) | ||||
| 		tty_default_features(&c->term_features, "tmux", 0); | ||||
| 	else if (strncmp(tmp, "XTerm(", 6) == 0) | ||||
| 		tty_default_features(&c->term_features, "XTerm", 0); | ||||
| 	else if (strncmp(tmp, "mintty ", 7) == 0) | ||||
| 		tty_default_features(&c->term_features, "mintty", 0); | ||||
| 	log_debug("%s: received extended DA %.*s", c->name, (int)*size, buf); | ||||
|  | ||||
| 	tty_set_flags(tty, flags); | ||||
| 	tty->flags |= TTY_HAVEDSR; | ||||
| 	free(c->term_type); | ||||
| 	c->term_type = xstrdup(tmp); | ||||
|  | ||||
| 	tty_update_features(tty); | ||||
| 	tty->flags |= TTY_HAVEXDA; | ||||
|  | ||||
| 	return (0); | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Nicholas Marriott
					Nicholas Marriott