mirror of
				https://github.com/tmux/tmux.git
				synced 2025-11-04 09:44:18 +00:00 
			
		
		
		
	Fixes for extended keys: 1) allow C-x and C-X to be bound separately
since some terminals report them differently 2) use the "backspace" option to translate backspace 3) map ctrl which are have the ctrl implied (such as C-x) properly when the terminal reports both the key and the modifier. Note that any key bindings for C-X where C-x is meant must now be changed.
This commit is contained in:
		
							
								
								
									
										18
									
								
								key-string.c
									
									
									
									
									
								
							
							
						
						
									
										18
									
								
								key-string.c
									
									
									
									
									
								
							@@ -45,9 +45,9 @@ static const struct {
 | 
				
			|||||||
	{ "F11",	KEYC_F11|KEYC_IMPLIED_META },
 | 
						{ "F11",	KEYC_F11|KEYC_IMPLIED_META },
 | 
				
			||||||
	{ "F12",	KEYC_F12|KEYC_IMPLIED_META },
 | 
						{ "F12",	KEYC_F12|KEYC_IMPLIED_META },
 | 
				
			||||||
	{ "IC",		KEYC_IC|KEYC_IMPLIED_META },
 | 
						{ "IC",		KEYC_IC|KEYC_IMPLIED_META },
 | 
				
			||||||
	{ "Insert",     KEYC_IC|KEYC_IMPLIED_META },
 | 
						{ "Insert",	KEYC_IC|KEYC_IMPLIED_META },
 | 
				
			||||||
	{ "DC",		KEYC_DC|KEYC_IMPLIED_META },
 | 
						{ "DC",		KEYC_DC|KEYC_IMPLIED_META },
 | 
				
			||||||
	{ "Delete",     KEYC_DC|KEYC_IMPLIED_META },
 | 
						{ "Delete",	KEYC_DC|KEYC_IMPLIED_META },
 | 
				
			||||||
	{ "Home",	KEYC_HOME|KEYC_IMPLIED_META },
 | 
						{ "Home",	KEYC_HOME|KEYC_IMPLIED_META },
 | 
				
			||||||
	{ "End",	KEYC_END|KEYC_IMPLIED_META },
 | 
						{ "End",	KEYC_END|KEYC_IMPLIED_META },
 | 
				
			||||||
	{ "NPage",	KEYC_NPAGE|KEYC_IMPLIED_META },
 | 
						{ "NPage",	KEYC_NPAGE|KEYC_IMPLIED_META },
 | 
				
			||||||
@@ -70,7 +70,7 @@ static const struct {
 | 
				
			|||||||
	{ "Right",	KEYC_RIGHT|KEYC_CURSOR|KEYC_IMPLIED_META },
 | 
						{ "Right",	KEYC_RIGHT|KEYC_CURSOR|KEYC_IMPLIED_META },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Numeric keypad. */
 | 
						/* Numeric keypad. */
 | 
				
			||||||
	{ "KP/", 	KEYC_KP_SLASH|KEYC_KEYPAD },
 | 
						{ "KP/",	KEYC_KP_SLASH|KEYC_KEYPAD },
 | 
				
			||||||
	{ "KP*",	KEYC_KP_STAR|KEYC_KEYPAD },
 | 
						{ "KP*",	KEYC_KP_STAR|KEYC_KEYPAD },
 | 
				
			||||||
	{ "KP-",	KEYC_KP_MINUS|KEYC_KEYPAD },
 | 
						{ "KP-",	KEYC_KP_MINUS|KEYC_KEYPAD },
 | 
				
			||||||
	{ "KP7",	KEYC_KP_SEVEN|KEYC_KEYPAD },
 | 
						{ "KP7",	KEYC_KP_SEVEN|KEYC_KEYPAD },
 | 
				
			||||||
@@ -164,7 +164,7 @@ key_string_get_modifiers(const char **string)
 | 
				
			|||||||
key_code
 | 
					key_code
 | 
				
			||||||
key_string_lookup_string(const char *string)
 | 
					key_string_lookup_string(const char *string)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	static const char	*other = "!#()+,-.0123456789:;<=>'\r\t";
 | 
						static const char	*other = "!#()+,-.0123456789:;<=>'\r\t\177";
 | 
				
			||||||
	key_code		 key, modifiers;
 | 
						key_code		 key, modifiers;
 | 
				
			||||||
	u_int			 u, i;
 | 
						u_int			 u, i;
 | 
				
			||||||
	struct utf8_data	 ud, *udp;
 | 
						struct utf8_data	 ud, *udp;
 | 
				
			||||||
@@ -181,8 +181,8 @@ key_string_lookup_string(const char *string)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	/* Is this a hexadecimal value? */
 | 
						/* Is this a hexadecimal value? */
 | 
				
			||||||
	if (string[0] == '0' && string[1] == 'x') {
 | 
						if (string[0] == '0' && string[1] == 'x') {
 | 
				
			||||||
	        if (sscanf(string + 2, "%x", &u) != 1)
 | 
							if (sscanf(string + 2, "%x", &u) != 1)
 | 
				
			||||||
	                return (KEYC_UNKNOWN);
 | 
								return (KEYC_UNKNOWN);
 | 
				
			||||||
		mlen = wctomb(m, u);
 | 
							mlen = wctomb(m, u);
 | 
				
			||||||
		if (mlen <= 0 || mlen > MB_LEN_MAX)
 | 
							if (mlen <= 0 || mlen > MB_LEN_MAX)
 | 
				
			||||||
			return (KEYC_UNKNOWN);
 | 
								return (KEYC_UNKNOWN);
 | 
				
			||||||
@@ -238,11 +238,11 @@ key_string_lookup_string(const char *string)
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Convert the standard control keys. */
 | 
						/* Convert the standard control keys. */
 | 
				
			||||||
	if (key < KEYC_BASE && (modifiers & KEYC_CTRL) && !strchr(other, key)) {
 | 
						if (key < KEYC_BASE && (modifiers & KEYC_CTRL) &&
 | 
				
			||||||
 | 
						    strchr(other, key) == NULL &&
 | 
				
			||||||
 | 
						    (key < 64 || key > 95)) {
 | 
				
			||||||
		if (key >= 97 && key <= 122)
 | 
							if (key >= 97 && key <= 122)
 | 
				
			||||||
			key -= 96;
 | 
								key -= 96;
 | 
				
			||||||
		else if (key >= 64 && key <= 95)
 | 
					 | 
				
			||||||
			key -= 64;
 | 
					 | 
				
			||||||
		else if (key == 32)
 | 
							else if (key == 32)
 | 
				
			||||||
			key = 0;
 | 
								key = 0;
 | 
				
			||||||
		else if (key == 63)
 | 
							else if (key == 63)
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										53
									
								
								tty-keys.c
									
									
									
									
									
								
							
							
						
						
									
										53
									
								
								tty-keys.c
									
									
									
									
									
								
							@@ -61,7 +61,7 @@ static int	tty_keys_extended_device_attributes(struct tty *, const char *,
 | 
				
			|||||||
/* Default raw keys. */
 | 
					/* Default raw keys. */
 | 
				
			||||||
struct tty_default_key_raw {
 | 
					struct tty_default_key_raw {
 | 
				
			||||||
	const char	       *string;
 | 
						const char	       *string;
 | 
				
			||||||
	key_code	 	key;
 | 
						key_code		key;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
static const struct tty_default_key_raw tty_default_raw_keys[] = {
 | 
					static const struct tty_default_key_raw tty_default_raw_keys[] = {
 | 
				
			||||||
	/* Application escape. */
 | 
						/* Application escape. */
 | 
				
			||||||
@@ -262,7 +262,7 @@ static const key_code tty_default_xterm_modifiers[] = {
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
struct tty_default_key_code {
 | 
					struct tty_default_key_code {
 | 
				
			||||||
	enum tty_code_code	code;
 | 
						enum tty_code_code	code;
 | 
				
			||||||
	key_code	 	key;
 | 
						key_code		key;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
static const struct tty_default_key_code tty_default_code_keys[] = {
 | 
					static const struct tty_default_key_code tty_default_code_keys[] = {
 | 
				
			||||||
	/* Function keys. */
 | 
						/* Function keys. */
 | 
				
			||||||
@@ -420,7 +420,7 @@ tty_keys_add(struct tty *tty, const char *s, key_code key)
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
	struct tty_key	*tk;
 | 
						struct tty_key	*tk;
 | 
				
			||||||
	size_t		 size;
 | 
						size_t		 size;
 | 
				
			||||||
	const char     	*keystr;
 | 
						const char	*keystr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	keystr = key_string_lookup_key(key, 1);
 | 
						keystr = key_string_lookup_key(key, 1);
 | 
				
			||||||
	if ((tk = tty_keys_find(tty, s, strlen(s), &size)) == NULL) {
 | 
						if ((tk = tty_keys_find(tty, s, strlen(s), &size)) == NULL) {
 | 
				
			||||||
@@ -477,7 +477,7 @@ tty_keys_build(struct tty *tty)
 | 
				
			|||||||
	const struct tty_default_key_raw	*tdkr;
 | 
						const struct tty_default_key_raw	*tdkr;
 | 
				
			||||||
	const struct tty_default_key_xterm	*tdkx;
 | 
						const struct tty_default_key_xterm	*tdkx;
 | 
				
			||||||
	const struct tty_default_key_code	*tdkc;
 | 
						const struct tty_default_key_code	*tdkc;
 | 
				
			||||||
	u_int		 			 i, j;
 | 
						u_int					 i, j;
 | 
				
			||||||
	const char				*s;
 | 
						const char				*s;
 | 
				
			||||||
	struct options_entry			*o;
 | 
						struct options_entry			*o;
 | 
				
			||||||
	struct options_array_item		*a;
 | 
						struct options_array_item		*a;
 | 
				
			||||||
@@ -869,6 +869,8 @@ tty_keys_extended_key(struct tty *tty, const char *buf, size_t len,
 | 
				
			|||||||
	size_t		 end;
 | 
						size_t		 end;
 | 
				
			||||||
	u_int		 number, modifiers;
 | 
						u_int		 number, modifiers;
 | 
				
			||||||
	char		 tmp[64];
 | 
						char		 tmp[64];
 | 
				
			||||||
 | 
						cc_t		 bspace;
 | 
				
			||||||
 | 
						key_code	 nkey;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	*size = 0;
 | 
						*size = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -911,38 +913,61 @@ tty_keys_extended_key(struct tty *tty, const char *buf, size_t len,
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	*size = end + 1;
 | 
						*size = end + 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Store the key and modifiers. */
 | 
						/* Store the key. */
 | 
				
			||||||
	*key = number;
 | 
						bspace = tty->tio.c_cc[VERASE];
 | 
				
			||||||
 | 
						if (bspace != _POSIX_VDISABLE && number == bspace)
 | 
				
			||||||
 | 
							nkey = KEYC_BSPACE;
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							nkey = number;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Update the modifiers. */
 | 
				
			||||||
	switch (modifiers) {
 | 
						switch (modifiers) {
 | 
				
			||||||
	case 2:
 | 
						case 2:
 | 
				
			||||||
		(*key) |= KEYC_SHIFT;
 | 
							nkey |= KEYC_SHIFT;
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	case 3:
 | 
						case 3:
 | 
				
			||||||
		(*key) |= (KEYC_META|KEYC_IMPLIED_META);
 | 
							nkey |= (KEYC_META|KEYC_IMPLIED_META);
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	case 4:
 | 
						case 4:
 | 
				
			||||||
		(*key) |= (KEYC_SHIFT|KEYC_META|KEYC_IMPLIED_META);
 | 
							nkey |= (KEYC_SHIFT|KEYC_META|KEYC_IMPLIED_META);
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	case 5:
 | 
						case 5:
 | 
				
			||||||
		(*key) |= KEYC_CTRL;
 | 
							nkey |= KEYC_CTRL;
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	case 6:
 | 
						case 6:
 | 
				
			||||||
		(*key) |= (KEYC_SHIFT|KEYC_CTRL);
 | 
							nkey |= (KEYC_SHIFT|KEYC_CTRL);
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	case 7:
 | 
						case 7:
 | 
				
			||||||
		(*key) |= (KEYC_META|KEYC_CTRL);
 | 
							nkey |= (KEYC_META|KEYC_CTRL);
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	case 8:
 | 
						case 8:
 | 
				
			||||||
		(*key) |= (KEYC_SHIFT|KEYC_META|KEYC_IMPLIED_META|KEYC_CTRL);
 | 
							nkey |= (KEYC_SHIFT|KEYC_META|KEYC_IMPLIED_META|KEYC_CTRL);
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		*key = KEYC_NONE;
 | 
							*key = KEYC_NONE;
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Don't allow both KEYC_CTRL and implied. */
 | 
				
			||||||
 | 
						if ((nkey & KEYC_CTRL) && (nkey & KEYC_MASK_KEY) < 32)
 | 
				
			||||||
 | 
							nkey &= ~KEYC_CTRL;
 | 
				
			||||||
 | 
						if ((nkey & KEYC_MASK_MODIFIERS) == KEYC_CTRL) {
 | 
				
			||||||
 | 
							nkey &= KEYC_MASK_KEY;
 | 
				
			||||||
 | 
							if (nkey >= 97 && nkey <= 122)
 | 
				
			||||||
 | 
								nkey -= 96;
 | 
				
			||||||
 | 
							else if (nkey == 32)
 | 
				
			||||||
 | 
								nkey = 0;
 | 
				
			||||||
 | 
							else if (nkey == 63)
 | 
				
			||||||
 | 
								nkey = 127;
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
								nkey |= KEYC_CTRL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (log_get_level() != 0) {
 | 
						if (log_get_level() != 0) {
 | 
				
			||||||
		log_debug("%s: extended key %.*s is %llx (%s)", c->name,
 | 
							log_debug("%s: extended key %.*s is %llx (%s)", c->name,
 | 
				
			||||||
		    (int)*size, buf, *key, key_string_lookup_key(*key, 1));
 | 
							    (int)*size, buf, nkey, key_string_lookup_key(nkey, 1));
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						*key = nkey;
 | 
				
			||||||
	return (0);
 | 
						return (0);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user