mirror of
				https://github.com/tmux/tmux.git
				synced 2025-10-26 12:27:15 +00:00 
			
		
		
		
	Merge branch 'obsd-master'
This commit is contained in:
		
							
								
								
									
										20
									
								
								format.c
									
									
									
									
									
								
							
							
						
						
									
										20
									
								
								format.c
									
									
									
									
									
								
							| @@ -1962,6 +1962,23 @@ format_cb_pane_unseen_changes(struct format_tree *ft) | |||||||
| 	return (NULL); | 	return (NULL); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | /* Callback for pane_key_mode. */ | ||||||
|  | static void * | ||||||
|  | format_cb_pane_key_mode(struct format_tree *ft) | ||||||
|  | { | ||||||
|  | 	if (ft->wp != NULL && ft->wp->screen != NULL) { | ||||||
|  | 		switch (ft->wp->screen->mode & EXTENDED_KEY_MODES) { | ||||||
|  | 		case MODE_KEYS_EXTENDED: | ||||||
|  | 			return (xstrdup("Ext 1")); | ||||||
|  | 		case MODE_KEYS_EXTENDED_2: | ||||||
|  | 			return (xstrdup("Ext 2")); | ||||||
|  | 		default: | ||||||
|  | 			return (xstrdup("VT10x")); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return (NULL); | ||||||
|  | } | ||||||
|  |  | ||||||
| /* Callback for pane_last. */ | /* Callback for pane_last. */ | ||||||
| static void * | static void * | ||||||
| format_cb_pane_last(struct format_tree *ft) | format_cb_pane_last(struct format_tree *ft) | ||||||
| @@ -2997,6 +3014,9 @@ static const struct format_table_entry format_table[] = { | |||||||
| 	{ "pane_input_off", FORMAT_TABLE_STRING, | 	{ "pane_input_off", FORMAT_TABLE_STRING, | ||||||
| 	  format_cb_pane_input_off | 	  format_cb_pane_input_off | ||||||
| 	}, | 	}, | ||||||
|  | 	{ "pane_key_mode", FORMAT_TABLE_STRING, | ||||||
|  | 	  format_cb_pane_key_mode | ||||||
|  | 	}, | ||||||
| 	{ "pane_last", FORMAT_TABLE_STRING, | 	{ "pane_last", FORMAT_TABLE_STRING, | ||||||
| 	  format_cb_pane_last | 	  format_cb_pane_last | ||||||
| 	}, | 	}, | ||||||
|   | |||||||
							
								
								
									
										373
									
								
								input-keys.c
									
									
									
									
									
								
							
							
						
						
									
										373
									
								
								input-keys.c
									
									
									
									
									
								
							| @@ -307,20 +307,6 @@ static struct input_key_entry input_key_defaults[] = { | |||||||
| 	{ .key = KEYC_DC|KEYC_BUILD_MODIFIERS, | 	{ .key = KEYC_DC|KEYC_BUILD_MODIFIERS, | ||||||
| 	  .data = "\033[3;_~" | 	  .data = "\033[3;_~" | ||||||
| 	}, | 	}, | ||||||
|  |  | ||||||
| 	/* Tab and modifiers. */ |  | ||||||
| 	{ .key = '\011'|KEYC_CTRL, |  | ||||||
| 	  .data = "\011" |  | ||||||
| 	}, |  | ||||||
| 	{ .key = '\011'|KEYC_CTRL|KEYC_EXTENDED, |  | ||||||
| 	  .data = "\033[9;5u" |  | ||||||
| 	}, |  | ||||||
| 	{ .key = '\011'|KEYC_CTRL|KEYC_SHIFT, |  | ||||||
| 	  .data = "\033[Z" |  | ||||||
| 	}, |  | ||||||
| 	{ .key = '\011'|KEYC_CTRL|KEYC_SHIFT|KEYC_EXTENDED, |  | ||||||
| 	  .data = "\033[1;5Z" |  | ||||||
| 	} |  | ||||||
| }; | }; | ||||||
| static const key_code input_key_modifiers[] = { | static const key_code input_key_modifiers[] = { | ||||||
| 	0, | 	0, | ||||||
| @@ -426,126 +412,18 @@ input_key_write(const char *from, struct bufferevent *bev, const char *data, | |||||||
| 	bufferevent_write(bev, data, size); | 	bufferevent_write(bev, data, size); | ||||||
| } | } | ||||||
|  |  | ||||||
| /* Translate a key code into an output key sequence. */ | /* | ||||||
| int |  * Encode and write an extended key escape sequence in one of the two | ||||||
| input_key(struct screen *s, struct bufferevent *bev, key_code key) |  * possible formats, depending on the configured output mode. | ||||||
|  |  */ | ||||||
|  | static int | ||||||
|  | input_key_extended(struct bufferevent *bev, key_code key) | ||||||
| { | { | ||||||
| 	struct input_key_entry	*ike = NULL; | 	char		 tmp[64], modifier; | ||||||
| 	key_code		 justkey, newkey, outkey, modifiers; | 	struct utf8_data ud; | ||||||
| 	struct utf8_data	 ud; | 	wchar_t		 wc; | ||||||
| 	char			 tmp[64], modifier; |  | ||||||
|  |  | ||||||
| 	/* Mouse keys need a pane. */ | 	switch (key & KEYC_MASK_MODIFIERS) { | ||||||
| 	if (KEYC_IS_MOUSE(key)) |  | ||||||
| 		return (0); |  | ||||||
|  |  | ||||||
| 	/* Literal keys go as themselves (can't be more than eight bits). */ |  | ||||||
| 	if (key & KEYC_LITERAL) { |  | ||||||
| 		ud.data[0] = (u_char)key; |  | ||||||
| 		input_key_write(__func__, bev, &ud.data[0], 1); |  | ||||||
| 		return (0); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	/* Is this backspace? */ |  | ||||||
| 	if ((key & KEYC_MASK_KEY) == KEYC_BSPACE) { |  | ||||||
| 		newkey = options_get_number(global_options, "backspace"); |  | ||||||
| 		if (newkey >= 0x7f) |  | ||||||
| 			newkey = '\177'; |  | ||||||
| 		key = newkey|(key & (KEYC_MASK_MODIFIERS|KEYC_MASK_FLAGS)); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	/* |  | ||||||
| 	 * If this is a normal 7-bit key, just send it, with a leading escape |  | ||||||
| 	 * if necessary. If it is a UTF-8 key, split it and send it. |  | ||||||
| 	 */ |  | ||||||
| 	justkey = (key & ~(KEYC_META|KEYC_IMPLIED_META)); |  | ||||||
| 	if (justkey <= 0x7f) { |  | ||||||
| 		if (key & KEYC_META) |  | ||||||
| 			input_key_write(__func__, bev, "\033", 1); |  | ||||||
| 		ud.data[0] = justkey; |  | ||||||
| 		input_key_write(__func__, bev, &ud.data[0], 1); |  | ||||||
| 		return (0); |  | ||||||
| 	} |  | ||||||
| 	if (KEYC_IS_UNICODE(justkey)) { |  | ||||||
| 		if (key & KEYC_META) |  | ||||||
| 			input_key_write(__func__, bev, "\033", 1); |  | ||||||
| 		utf8_to_data(justkey, &ud); |  | ||||||
| 		input_key_write(__func__, bev, ud.data, ud.size); |  | ||||||
| 		return (0); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	/* |  | ||||||
| 	 * Look up in the tree. If not in application keypad or cursor mode, |  | ||||||
| 	 * remove the flags from the key. |  | ||||||
| 	 */ |  | ||||||
| 	if (~s->mode & MODE_KKEYPAD) |  | ||||||
| 		key &= ~KEYC_KEYPAD; |  | ||||||
| 	if (~s->mode & MODE_KCURSOR) |  | ||||||
| 		key &= ~KEYC_CURSOR; |  | ||||||
| 	if (s->mode & MODE_KEXTENDED) |  | ||||||
| 		ike = input_key_get(key|KEYC_EXTENDED); |  | ||||||
| 	if (ike == NULL) |  | ||||||
| 		ike = input_key_get(key); |  | ||||||
| 	if (ike == NULL && (key & KEYC_META) && (~key & KEYC_IMPLIED_META)) |  | ||||||
| 		ike = input_key_get(key & ~KEYC_META); |  | ||||||
| 	if (ike == NULL && (key & KEYC_CURSOR)) |  | ||||||
| 		ike = input_key_get(key & ~KEYC_CURSOR); |  | ||||||
| 	if (ike == NULL && (key & KEYC_KEYPAD)) |  | ||||||
| 		ike = input_key_get(key & ~KEYC_KEYPAD); |  | ||||||
| 	if (ike == NULL && (key & KEYC_EXTENDED)) |  | ||||||
| 		ike = input_key_get(key & ~KEYC_EXTENDED); |  | ||||||
| 	if (ike != NULL) { |  | ||||||
| 		log_debug("found key 0x%llx: \"%s\"", key, ike->data); |  | ||||||
| 		if ((key == KEYC_PASTE_START || key == KEYC_PASTE_END) && |  | ||||||
| 		    (~s->mode & MODE_BRACKETPASTE)) |  | ||||||
| 			return (0); |  | ||||||
| 		if ((key & KEYC_META) && (~key & KEYC_IMPLIED_META)) |  | ||||||
| 			input_key_write(__func__, bev, "\033", 1); |  | ||||||
| 		input_key_write(__func__, bev, ike->data, strlen(ike->data)); |  | ||||||
| 		return (0); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	/* No builtin key sequence; construct an extended key sequence. */ |  | ||||||
| 	if (~s->mode & MODE_KEXTENDED) { |  | ||||||
| 		if ((key & KEYC_MASK_MODIFIERS) != KEYC_CTRL) |  | ||||||
| 			goto missing; |  | ||||||
| 		justkey = (key & KEYC_MASK_KEY); |  | ||||||
| 		switch (justkey) { |  | ||||||
| 		case ' ': |  | ||||||
| 		case '2': |  | ||||||
| 			key = 0|(key & ~KEYC_MASK_KEY); |  | ||||||
| 			break; |  | ||||||
| 		case '|': |  | ||||||
| 			key = 28|(key & ~KEYC_MASK_KEY); |  | ||||||
| 			break; |  | ||||||
| 		case '6': |  | ||||||
| 			key = 30|(key & ~KEYC_MASK_KEY); |  | ||||||
| 			break; |  | ||||||
| 		case '-': |  | ||||||
| 		case '/': |  | ||||||
| 			key = 31|(key & ~KEYC_MASK_KEY); |  | ||||||
| 			break; |  | ||||||
| 		case '?': |  | ||||||
| 			key = 127|(key & ~KEYC_MASK_KEY); |  | ||||||
| 			break; |  | ||||||
| 		default: |  | ||||||
| 			if (justkey >= 'A' && justkey <= '_') |  | ||||||
| 				key = (justkey - 'A')|(key & ~KEYC_MASK_KEY); |  | ||||||
| 			else if (justkey >= 'a' && justkey <= '~') |  | ||||||
| 				key = (justkey - 96)|(key & ~KEYC_MASK_KEY); |  | ||||||
| 			else |  | ||||||
| 				return (0); |  | ||||||
| 			break; |  | ||||||
| 		} |  | ||||||
| 		return (input_key(s, bev, key & ~KEYC_CTRL)); |  | ||||||
| 	} |  | ||||||
| 	outkey = (key & KEYC_MASK_KEY); |  | ||||||
| 	modifiers = (key & KEYC_MASK_MODIFIERS); |  | ||||||
| 	if (outkey < 32 && outkey != 9 && outkey != 13 && outkey != 27) { |  | ||||||
| 		outkey = 64 + outkey; |  | ||||||
| 		modifiers |= KEYC_CTRL; |  | ||||||
| 	} |  | ||||||
| 	switch (modifiers) { |  | ||||||
| 	case KEYC_SHIFT: | 	case KEYC_SHIFT: | ||||||
| 		modifier = '2'; | 		modifier = '2'; | ||||||
| 		break; | 		break; | ||||||
| @@ -568,17 +446,240 @@ input_key(struct screen *s, struct bufferevent *bev, key_code key) | |||||||
| 		modifier = '8'; | 		modifier = '8'; | ||||||
| 		break; | 		break; | ||||||
| 	default: | 	default: | ||||||
| 		goto missing; | 		return (-1); | ||||||
| 	} | 	} | ||||||
| 	xsnprintf(tmp, sizeof tmp, "\033[%llu;%cu", outkey, modifier); |  | ||||||
|  | 	if (KEYC_IS_UNICODE(key)) { | ||||||
|  | 		utf8_to_data(key & KEYC_MASK_KEY, &ud); | ||||||
|  | 		if (utf8_towc(&ud, &wc) == UTF8_DONE) | ||||||
|  | 			key = wc; | ||||||
|  | 		else | ||||||
|  | 			return (-1); | ||||||
|  | 	} else | ||||||
|  | 		key &= KEYC_MASK_KEY; | ||||||
|  |  | ||||||
|  | 	if (options_get_number(global_options, "extended-keys-format") == 1) | ||||||
|  | 		xsnprintf(tmp, sizeof tmp, "\033[27;%c;%llu~", modifier, key); | ||||||
|  | 	else | ||||||
|  | 		xsnprintf(tmp, sizeof tmp, "\033[%llu;%cu", key, modifier); | ||||||
|  |  | ||||||
| 	input_key_write(__func__, bev, tmp, strlen(tmp)); | 	input_key_write(__func__, bev, tmp, strlen(tmp)); | ||||||
| 	return (0); | 	return (0); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * Outputs the key in the "standard" mode. This is by far the most | ||||||
|  |  * complicated output mode, with a lot of remapping in order to | ||||||
|  |  * emulate quirks of terminals that today can be only found in museums. | ||||||
|  |  */ | ||||||
|  | static int | ||||||
|  | input_key_vt10x(struct bufferevent *bev, key_code key) | ||||||
|  | { | ||||||
|  | 	struct utf8_data	 ud; | ||||||
|  | 	key_code		 onlykey; | ||||||
|  | 	char			*p; | ||||||
|  | 	static const char	*standard_map[2] = { | ||||||
|  | 		"1!9(0)=+;:'\",<.>/-8? 2", | ||||||
|  | 		"119900=+;;'',,..\x1f\x1f\x7f\x7f\0\0", | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	log_debug("%s: key in %llx", __func__, key); | ||||||
|  |  | ||||||
|  | 	if (key & KEYC_META) | ||||||
|  | 		input_key_write(__func__, bev, "\033", 1); | ||||||
|  |  | ||||||
|  | 	/* | ||||||
|  | 	 * There's no way to report modifiers for unicode keys in standard mode | ||||||
|  | 	 * so lose the modifiers. | ||||||
|  | 	 */ | ||||||
|  | 	if (KEYC_IS_UNICODE(key)) { | ||||||
|  | 		utf8_to_data(key, &ud); | ||||||
|  |                 input_key_write(__func__, bev, ud.data, ud.size); | ||||||
|  | 		return (0); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	onlykey = key & KEYC_MASK_KEY; | ||||||
|  |  | ||||||
|  | 	/* Prevent TAB and RET from being swallowed by C0 remapping logic. */ | ||||||
|  | 	if (onlykey == '\r' || onlykey == '\t') | ||||||
|  | 		key &= ~KEYC_CTRL; | ||||||
|  |  | ||||||
|  | 	/* | ||||||
|  | 	 * Convert keys with Ctrl modifier into corresponding C0 control codes, | ||||||
|  | 	 * with the exception of *some* keys, which are remapped into printable | ||||||
|  | 	 * ASCII characters. | ||||||
|  | 	 * | ||||||
|  | 	 * There is no special handling for Shift modifier, which is pretty | ||||||
|  | 	 * much redundant anyway, as no terminal will send <base key>|SHIFT, | ||||||
|  | 	 * but only <shifted key>|SHIFT. | ||||||
|  | 	 */ | ||||||
|  | 	if (key & KEYC_CTRL) { | ||||||
|  | 		p = strchr(standard_map[0], onlykey); | ||||||
|  | 		if (p != NULL) | ||||||
|  | 			key = standard_map[1][p - standard_map[0]]; | ||||||
|  | 		else if (onlykey >= '3' && onlykey <= '7') | ||||||
|  | 			key = onlykey - '\030'; | ||||||
|  | 		else if (onlykey >= '@' && onlykey <= '~') | ||||||
|  | 			key = onlykey & 0x1f; | ||||||
|  | 		else | ||||||
|  | 			return (-1); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	log_debug("%s: key out %llx", __func__, key); | ||||||
|  |  | ||||||
|  | 	ud.data[0] = key & 0x7f; | ||||||
|  | 	input_key_write(__func__, bev, &ud.data[0], 1); | ||||||
|  | 	return (0); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* Pick keys that are reported as vt10x keys in modifyOtherKeys=1 mode. */ | ||||||
|  | static int | ||||||
|  | input_key_mode1(struct bufferevent *bev, key_code key) | ||||||
|  | { | ||||||
|  | 	key_code	 onlykey; | ||||||
|  |  | ||||||
|  | 	log_debug("%s: key in %llx", __func__, key); | ||||||
|  |  | ||||||
|  | 	/* | ||||||
|  | 	 * As per | ||||||
|  | 	 * https://invisible-island.net/xterm/modified-keys-us-pc105.html. | ||||||
|  | 	 */ | ||||||
|  | 	onlykey = key & KEYC_MASK_KEY; | ||||||
|  | 	if ((key & (KEYC_META | KEYC_CTRL)) == KEYC_CTRL && | ||||||
|  | 	    (onlykey == ' ' || | ||||||
|  | 	     onlykey == '/' || | ||||||
|  | 	     onlykey == '@' || | ||||||
|  | 	     onlykey == '^' || | ||||||
|  | 	     (onlykey >= '2' && onlykey <= '8') || | ||||||
|  | 	     (onlykey >= '@' && onlykey <= '~'))) | ||||||
|  | 		return (input_key_vt10x(bev, key)); | ||||||
|  |  | ||||||
|  | 	/* | ||||||
|  | 	 * A regular key + Meta. In the absence of a standard to back this, we | ||||||
|  | 	 * mimic what iTerm 2 does. | ||||||
|  | 	 */ | ||||||
|  | 	if ((key & (KEYC_CTRL | KEYC_META)) == KEYC_META) | ||||||
|  | 		return (input_key_vt10x(bev, key)); | ||||||
|  |  | ||||||
| missing: |  | ||||||
| 	log_debug("key 0x%llx missing", key); |  | ||||||
| 	return (-1); | 	return (-1); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | /* Translate a key code into an output key sequence. */ | ||||||
|  | int | ||||||
|  | input_key(struct screen *s, struct bufferevent *bev, key_code key) | ||||||
|  | { | ||||||
|  | 	struct input_key_entry	*ike = NULL; | ||||||
|  | 	key_code		 newkey; | ||||||
|  | 	struct utf8_data	 ud; | ||||||
|  |  | ||||||
|  | 	/* Mouse keys need a pane. */ | ||||||
|  | 	if (KEYC_IS_MOUSE(key)) | ||||||
|  | 		return (0); | ||||||
|  |  | ||||||
|  | 	/* Literal keys go as themselves (can't be more than eight bits). */ | ||||||
|  | 	if (key & KEYC_LITERAL) { | ||||||
|  | 		ud.data[0] = (u_char)key; | ||||||
|  | 		input_key_write(__func__, bev, &ud.data[0], 1); | ||||||
|  | 		return (0); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	/* Is this backspace? */ | ||||||
|  | 	if ((key & KEYC_MASK_KEY) == KEYC_BSPACE) { | ||||||
|  | 		newkey = options_get_number(global_options, "backspace"); | ||||||
|  | 		if (newkey >= 0x7f) | ||||||
|  | 			newkey = '\177'; | ||||||
|  | 		key = newkey|(key & (KEYC_MASK_MODIFIERS|KEYC_MASK_FLAGS)); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	/* Is this backtab? */ | ||||||
|  | 	if ((key & KEYC_MASK_KEY) == KEYC_BTAB) { | ||||||
|  | 		if (s->mode & EXTENDED_KEY_MODES) { | ||||||
|  | 			/* When in xterm extended mode, remap into S-Tab. */ | ||||||
|  | 			key = '\011' | (key & ~KEYC_MASK_KEY) | KEYC_SHIFT; | ||||||
|  | 		} else { | ||||||
|  | 			/* Otherwise clear modifiers. */ | ||||||
|  | 			key &= ~KEYC_MASK_MODIFIERS; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	/* | ||||||
|  | 	 * A trivial case, that is a 7-bit key, excluding C0 control characters | ||||||
|  | 	 * that can't be entered from the keyboard, and no modifiers; or a UTF-8 | ||||||
|  | 	 * key and no modifiers. | ||||||
|  | 	 */ | ||||||
|  | 	if (!(key & ~KEYC_MASK_KEY)) { | ||||||
|  | 		if (key == C0_BS || key == C0_HT || | ||||||
|  | 		    key == C0_CR || key == C0_ESC || | ||||||
|  | 		    (key >= 0x20 && key <= 0x7f)) { | ||||||
|  | 			ud.data[0] = key; | ||||||
|  | 			input_key_write(__func__, bev, &ud.data[0], 1); | ||||||
|  | 			return (0); | ||||||
|  | 		} | ||||||
|  | 		if (KEYC_IS_UNICODE(key)) { | ||||||
|  | 			utf8_to_data(key, &ud); | ||||||
|  | 			input_key_write(__func__, bev, ud.data, ud.size); | ||||||
|  | 			return (0); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	/* | ||||||
|  | 	 * Look up the standard VT10x keys in the tree. If not in application | ||||||
|  | 	 * keypad or cursor mode, remove the respective flags from the key. | ||||||
|  | 	 */ | ||||||
|  | 	if (~s->mode & MODE_KKEYPAD) | ||||||
|  | 		key &= ~KEYC_KEYPAD; | ||||||
|  | 	if (~s->mode & MODE_KCURSOR) | ||||||
|  | 		key &= ~KEYC_CURSOR; | ||||||
|  | 	if (ike == NULL) | ||||||
|  | 		ike = input_key_get(key); | ||||||
|  | 	if (ike == NULL && (key & KEYC_META) && (~key & KEYC_IMPLIED_META)) | ||||||
|  | 		ike = input_key_get(key & ~KEYC_META); | ||||||
|  | 	if (ike == NULL && (key & KEYC_CURSOR)) | ||||||
|  | 		ike = input_key_get(key & ~KEYC_CURSOR); | ||||||
|  | 	if (ike == NULL && (key & KEYC_KEYPAD)) | ||||||
|  | 		ike = input_key_get(key & ~KEYC_KEYPAD); | ||||||
|  | 	if (ike != NULL) { | ||||||
|  | 		log_debug("%s: found key 0x%llx: \"%s\"", __func__, key, | ||||||
|  | 		    ike->data); | ||||||
|  | 		if ((key == KEYC_PASTE_START || key == KEYC_PASTE_END) && | ||||||
|  | 		    (~s->mode & MODE_BRACKETPASTE)) | ||||||
|  | 			return (0); | ||||||
|  | 		if ((key & KEYC_META) && (~key & KEYC_IMPLIED_META)) | ||||||
|  | 			input_key_write(__func__, bev, "\033", 1); | ||||||
|  | 		input_key_write(__func__, bev, ike->data, strlen(ike->data)); | ||||||
|  | 		return (0); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	/* | ||||||
|  | 	 * No builtin key sequence; construct an extended key sequence | ||||||
|  | 	 * depending on the client mode. | ||||||
|  | 	 * | ||||||
|  | 	 * If something invalid reaches here, an invalid output may be | ||||||
|  | 	 * produced. For example Ctrl-Shift-2 is invalid (as there's | ||||||
|  | 	 * no way to enter it). The correct form is Ctrl-Shift-@, at | ||||||
|  | 	 * least in US English keyboard layout. | ||||||
|  | 	 */ | ||||||
|  | 	switch (s->mode & EXTENDED_KEY_MODES) { | ||||||
|  | 	case MODE_KEYS_EXTENDED_2: | ||||||
|  | 		/* | ||||||
|  | 		 * The simplest mode to handle - *all* modified keys are | ||||||
|  | 		 * reported in the extended form. | ||||||
|  | 		 */ | ||||||
|  | 		return (input_key_extended(bev, key)); | ||||||
|  |         case MODE_KEYS_EXTENDED: | ||||||
|  | 		/* | ||||||
|  | 		 * Some keys are still reported in standard mode, to maintain | ||||||
|  | 		 * compatibility with applications unaware of extended keys. | ||||||
|  | 		 */ | ||||||
|  | 		if (input_key_mode1(bev, key) == -1) | ||||||
|  | 			return (input_key_extended(bev, key)); | ||||||
|  | 		return (0); | ||||||
|  | 	default: | ||||||
|  | 		/* The standard mode. */ | ||||||
|  | 		return (input_key_vt10x(bev, key)); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
| /* Get mouse event string. */ | /* Get mouse event string. */ | ||||||
| int | int | ||||||
| input_key_get_mouse(struct screen *s, struct mouse_event *m, u_int x, u_int y, | input_key_get_mouse(struct screen *s, struct mouse_event *m, u_int x, u_int y, | ||||||
|   | |||||||
							
								
								
									
										26
									
								
								input.c
									
									
									
									
									
								
							
							
						
						
									
										26
									
								
								input.c
									
									
									
									
									
								
							| @@ -1408,17 +1408,29 @@ input_csi_dispatch(struct input_ctx *ictx) | |||||||
| 	case INPUT_CSI_MODSET: | 	case INPUT_CSI_MODSET: | ||||||
| 		n = input_get(ictx, 0, 0, 0); | 		n = input_get(ictx, 0, 0, 0); | ||||||
| 		m = input_get(ictx, 1, 0, 0); | 		m = input_get(ictx, 1, 0, 0); | ||||||
| 		if (options_get_number(global_options, "extended-keys") == 2) | 		/* | ||||||
|  | 		 * Set the extended key reporting mode as per the client request, | ||||||
|  | 		 * unless "extended-keys always" forces us into mode 1. | ||||||
|  | 		 */ | ||||||
|  | 		if (options_get_number(global_options, "extended-keys") != 1) | ||||||
| 			break; | 			break; | ||||||
| 		if (n == 0 || (n == 4 && m == 0)) | 		screen_write_mode_clear(sctx, | ||||||
| 			screen_write_mode_clear(sctx, MODE_KEXTENDED); | 		    MODE_KEYS_EXTENDED|MODE_KEYS_EXTENDED_2); | ||||||
| 		else if (n == 4 && (m == 1 || m == 2)) | 		if (n == 4 && m == 1) | ||||||
| 			screen_write_mode_set(sctx, MODE_KEXTENDED); | 			screen_write_mode_set(sctx, MODE_KEYS_EXTENDED); | ||||||
|  | 		if (n == 4 && m == 2) | ||||||
|  | 			screen_write_mode_set(sctx, MODE_KEYS_EXTENDED_2); | ||||||
| 		break; | 		break; | ||||||
| 	case INPUT_CSI_MODOFF: | 	case INPUT_CSI_MODOFF: | ||||||
| 		n = input_get(ictx, 0, 0, 0); | 		n = input_get(ictx, 0, 0, 0); | ||||||
| 		if (n == 4) | 		/* | ||||||
| 			screen_write_mode_clear(sctx, MODE_KEXTENDED); | 		 * Clear the extended key reporting mode as per the client request, | ||||||
|  | 		 * unless "extended-keys always" forces us into mode 1. | ||||||
|  | 		 */ | ||||||
|  | 		if (n == 4) { | ||||||
|  | 			screen_write_mode_clear(sctx, | ||||||
|  | 			    MODE_KEYS_EXTENDED|MODE_KEYS_EXTENDED_2); | ||||||
|  | 		} | ||||||
| 		break; | 		break; | ||||||
| 	case INPUT_CSI_WINOPS: | 	case INPUT_CSI_WINOPS: | ||||||
| 		input_csi_dispatch_winops(ictx); | 		input_csi_dispatch_winops(ictx); | ||||||
|   | |||||||
| @@ -413,6 +413,8 @@ key_bindings_init(void) | |||||||
| 		"bind -N 'Set the main-horizontal layout' M-3 { select-layout main-horizontal }", | 		"bind -N 'Set the main-horizontal layout' M-3 { select-layout main-horizontal }", | ||||||
| 		"bind -N 'Set the main-vertical layout' M-4 { select-layout main-vertical }", | 		"bind -N 'Set the main-vertical layout' M-4 { select-layout main-vertical }", | ||||||
| 		"bind -N 'Select the tiled layout' M-5 { select-layout tiled }", | 		"bind -N 'Select the tiled layout' M-5 { select-layout tiled }", | ||||||
|  | 		"bind -N 'Set the main-horizontal-mirrored layout' M-6 { select-layout main-horizontal-mirrored }", | ||||||
|  | 		"bind -N 'Set the main-vertical-mirrored layout' M-7 { select-layout main-vertical-mirrored }", | ||||||
| 		"bind -N 'Select the next window with an alert' M-n { next-window -a }", | 		"bind -N 'Select the next window with an alert' M-n { next-window -a }", | ||||||
| 		"bind -N 'Rotate through the panes in reverse' M-o { rotate-window -D }", | 		"bind -N 'Rotate through the panes in reverse' M-o { rotate-window -D }", | ||||||
| 		"bind -N 'Select the previous window with an alert' M-p { previous-window -a }", | 		"bind -N 'Select the previous window with an alert' M-p { previous-window -a }", | ||||||
|   | |||||||
							
								
								
									
										77
									
								
								key-string.c
									
									
									
									
									
								
							
							
						
						
									
										77
									
								
								key-string.c
									
									
									
									
									
								
							| @@ -56,12 +56,47 @@ static const struct { | |||||||
| 	{ "PPage",	KEYC_PPAGE|KEYC_IMPLIED_META }, | 	{ "PPage",	KEYC_PPAGE|KEYC_IMPLIED_META }, | ||||||
| 	{ "PageUp",	KEYC_PPAGE|KEYC_IMPLIED_META }, | 	{ "PageUp",	KEYC_PPAGE|KEYC_IMPLIED_META }, | ||||||
| 	{ "PgUp",	KEYC_PPAGE|KEYC_IMPLIED_META }, | 	{ "PgUp",	KEYC_PPAGE|KEYC_IMPLIED_META }, | ||||||
| 	{ "Tab",	'\011' }, |  | ||||||
| 	{ "BTab",	KEYC_BTAB }, | 	{ "BTab",	KEYC_BTAB }, | ||||||
| 	{ "Space",	' ' }, | 	{ "Space",	' ' }, | ||||||
| 	{ "BSpace",	KEYC_BSPACE }, | 	{ "BSpace",	KEYC_BSPACE }, | ||||||
| 	{ "Enter",	'\r' }, |  | ||||||
| 	{ "Escape",	'\033' }, | 	/* | ||||||
|  | 	 * C0 control characters, with the exception of Tab, Enter, | ||||||
|  | 	 * and Esc, should never appear as keys. We still render them, | ||||||
|  | 	 * so to be able to spot them in logs in case of an abnormality. | ||||||
|  | 	 */ | ||||||
|  | 	{ "[NUL]",	C0_NUL }, | ||||||
|  | 	{ "[SOH]",	C0_SOH }, | ||||||
|  | 	{ "[STX]",	C0_STX }, | ||||||
|  | 	{ "[ETX]",	C0_ETX }, | ||||||
|  | 	{ "[EOT]",	C0_EOT }, | ||||||
|  | 	{ "[ENQ]",	C0_ENQ }, | ||||||
|  | 	{ "[ASC]",	C0_ASC }, | ||||||
|  | 	{ "[BEL]",	C0_BEL }, | ||||||
|  | 	{ "[BS]",	C0_BS }, | ||||||
|  | 	{ "Tab",	C0_HT }, | ||||||
|  | 	{ "[LF]",	C0_LF }, | ||||||
|  | 	{ "[VT]",	C0_VT }, | ||||||
|  | 	{ "[FF]",	C0_FF }, | ||||||
|  | 	{ "Enter",	C0_CR }, | ||||||
|  | 	{ "[SO]",	C0_SO }, | ||||||
|  | 	{ "[SI]",	C0_SI }, | ||||||
|  | 	{ "[DLE]",	C0_DLE }, | ||||||
|  | 	{ "[DC1]",	C0_DC1 }, | ||||||
|  | 	{ "[DC2]",	C0_DC2 }, | ||||||
|  | 	{ "[DC3]",	C0_DC3 }, | ||||||
|  | 	{ "[DC4]",	C0_DC4 }, | ||||||
|  | 	{ "[NAK]",	C0_NAK }, | ||||||
|  | 	{ "[SYN]",	C0_SYN }, | ||||||
|  | 	{ "[ETB]",	C0_ETB }, | ||||||
|  | 	{ "[CAN]",	C0_CAN }, | ||||||
|  | 	{ "[EM]",	C0_EM }, | ||||||
|  | 	{ "[SUB]",	C0_SUB }, | ||||||
|  | 	{ "Escape",	C0_ESC }, | ||||||
|  | 	{ "[FS]",	C0_FS }, | ||||||
|  | 	{ "[GS]",	C0_GS }, | ||||||
|  | 	{ "[RS]",	C0_RS }, | ||||||
|  | 	{ "[US]",	C0_US }, | ||||||
|  |  | ||||||
| 	/* Arrow keys. */ | 	/* Arrow keys. */ | ||||||
| 	{ "Up",		KEYC_UP|KEYC_CURSOR|KEYC_IMPLIED_META }, | 	{ "Up",		KEYC_UP|KEYC_CURSOR|KEYC_IMPLIED_META }, | ||||||
| @@ -206,7 +241,6 @@ 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\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; | ||||||
| @@ -281,26 +315,6 @@ key_string_lookup_string(const char *string) | |||||||
| 			key &= ~KEYC_IMPLIED_META; | 			key &= ~KEYC_IMPLIED_META; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	/* Convert the standard control keys. */ |  | ||||||
| 	if (key <= 127 && |  | ||||||
| 	    (modifiers & KEYC_CTRL) && |  | ||||||
| 	    strchr(other, key) == NULL && |  | ||||||
| 	    key != 9 && |  | ||||||
| 	    key != 13 && |  | ||||||
| 	    key != 27) { |  | ||||||
| 		if (key >= 97 && key <= 122) |  | ||||||
| 			key -= 96; |  | ||||||
| 		else if (key >= 64 && key <= 95) |  | ||||||
|                        key -= 64; |  | ||||||
| 		else if (key == 32) |  | ||||||
| 			key = 0; |  | ||||||
| 		else if (key == 63) |  | ||||||
| 			key = 127; |  | ||||||
| 		else |  | ||||||
| 			return (KEYC_UNKNOWN); |  | ||||||
| 		modifiers &= ~KEYC_CTRL; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	return (key|modifiers); | 	return (key|modifiers); | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -324,10 +338,6 @@ key_string_lookup_key(key_code key, int with_flags) | |||||||
| 		goto out; | 		goto out; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	/* Display C-@ as C-Space. */ |  | ||||||
| 	if ((key & (KEYC_MASK_KEY|KEYC_MASK_MODIFIERS)) == 0) |  | ||||||
| 		key = ' '|KEYC_CTRL; |  | ||||||
|  |  | ||||||
| 	/* Fill in the modifiers. */ | 	/* Fill in the modifiers. */ | ||||||
| 	if (key & KEYC_CTRL) | 	if (key & KEYC_CTRL) | ||||||
| 		strlcat(out, "C-", sizeof out); | 		strlcat(out, "C-", sizeof out); | ||||||
| @@ -427,13 +437,8 @@ key_string_lookup_key(key_code key, int with_flags) | |||||||
| 		goto out; | 		goto out; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	/* Check for standard or control key. */ | 	/* Printable ASCII keys. */ | ||||||
| 	if (key <= 32) { | 	if (key > 32 && key <= 126) { | ||||||
| 		if (key == 0 || key > 26) |  | ||||||
| 			xsnprintf(tmp, sizeof tmp, "C-%c", (int)(64 + key)); |  | ||||||
| 		else |  | ||||||
| 			xsnprintf(tmp, sizeof tmp, "C-%c", (int)(96 + key)); |  | ||||||
| 	} else if (key >= 32 && key <= 126) { |  | ||||||
| 		tmp[0] = key; | 		tmp[0] = key; | ||||||
| 		tmp[1] = '\0'; | 		tmp[1] = '\0'; | ||||||
| 	} else if (key == 127) | 	} else if (key == 127) | ||||||
| @@ -460,8 +465,6 @@ out: | |||||||
| 			strlcat(out, "I", sizeof out); | 			strlcat(out, "I", sizeof out); | ||||||
| 		if (saved & KEYC_BUILD_MODIFIERS) | 		if (saved & KEYC_BUILD_MODIFIERS) | ||||||
| 			strlcat(out, "B", sizeof out); | 			strlcat(out, "B", sizeof out); | ||||||
| 		if (saved & KEYC_EXTENDED) |  | ||||||
| 			strlcat(out, "E", sizeof out); |  | ||||||
| 		if (saved & KEYC_SENT) | 		if (saved & KEYC_SENT) | ||||||
| 			strlcat(out, "S", sizeof out); | 			strlcat(out, "S", sizeof out); | ||||||
| 		strlcat(out, "]", sizeof out); | 		strlcat(out, "]", sizeof out); | ||||||
|   | |||||||
							
								
								
									
										200
									
								
								layout-set.c
									
									
									
									
									
								
							
							
						
						
									
										200
									
								
								layout-set.c
									
									
									
									
									
								
							| @@ -31,7 +31,9 @@ | |||||||
| static void	layout_set_even_h(struct window *); | static void	layout_set_even_h(struct window *); | ||||||
| static void	layout_set_even_v(struct window *); | static void	layout_set_even_v(struct window *); | ||||||
| static void	layout_set_main_h(struct window *); | static void	layout_set_main_h(struct window *); | ||||||
|  | static void	layout_set_main_h_mirrored(struct window *); | ||||||
| static void	layout_set_main_v(struct window *); | static void	layout_set_main_v(struct window *); | ||||||
|  | static void	layout_set_main_v_mirrored(struct window *); | ||||||
| static void	layout_set_tiled(struct window *); | static void	layout_set_tiled(struct window *); | ||||||
|  |  | ||||||
| static const struct { | static const struct { | ||||||
| @@ -41,7 +43,9 @@ static const struct { | |||||||
| 	{ "even-horizontal", layout_set_even_h }, | 	{ "even-horizontal", layout_set_even_h }, | ||||||
| 	{ "even-vertical", layout_set_even_v }, | 	{ "even-vertical", layout_set_even_v }, | ||||||
| 	{ "main-horizontal", layout_set_main_h }, | 	{ "main-horizontal", layout_set_main_h }, | ||||||
|  | 	{ "main-horizontal-mirrored", layout_set_main_h_mirrored }, | ||||||
| 	{ "main-vertical", layout_set_main_v }, | 	{ "main-vertical", layout_set_main_v }, | ||||||
|  | 	{ "main-vertical-mirrored", layout_set_main_v_mirrored }, | ||||||
| 	{ "tiled", layout_set_tiled }, | 	{ "tiled", layout_set_tiled }, | ||||||
| }; | }; | ||||||
|  |  | ||||||
| @@ -279,6 +283,104 @@ layout_set_main_h(struct window *w) | |||||||
| 	server_redraw_window(w); | 	server_redraw_window(w); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | static void | ||||||
|  | layout_set_main_h_mirrored(struct window *w) | ||||||
|  | { | ||||||
|  | 	struct window_pane	*wp; | ||||||
|  | 	struct layout_cell	*lc, *lcmain, *lcother, *lcchild; | ||||||
|  | 	u_int			 n, mainh, otherh, sx, sy; | ||||||
|  | 	char			*cause; | ||||||
|  | 	const char		*s; | ||||||
|  |  | ||||||
|  | 	layout_print_cell(w->layout_root, __func__, 1); | ||||||
|  |  | ||||||
|  | 	/* Get number of panes. */ | ||||||
|  | 	n = window_count_panes(w); | ||||||
|  | 	if (n <= 1) | ||||||
|  | 		return; | ||||||
|  | 	n--;	/* take off main pane */ | ||||||
|  |  | ||||||
|  | 	/* Find available height - take off one line for the border. */ | ||||||
|  | 	sy = w->sy - 1; | ||||||
|  |  | ||||||
|  | 	/* Get the main pane height. */ | ||||||
|  | 	s = options_get_string(w->options, "main-pane-height"); | ||||||
|  | 	mainh = args_string_percentage(s, 0, sy, sy, &cause); | ||||||
|  | 	if (cause != NULL) { | ||||||
|  | 		mainh = 24; | ||||||
|  | 		free(cause); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	/* Work out the other pane height. */ | ||||||
|  | 	if (mainh + PANE_MINIMUM >= sy) { | ||||||
|  | 		if (sy <= PANE_MINIMUM + PANE_MINIMUM) | ||||||
|  | 			mainh = PANE_MINIMUM; | ||||||
|  | 		else | ||||||
|  | 			mainh = sy - PANE_MINIMUM; | ||||||
|  | 		otherh = PANE_MINIMUM; | ||||||
|  | 	} else { | ||||||
|  | 		s = options_get_string(w->options, "other-pane-height"); | ||||||
|  | 		otherh = args_string_percentage(s, 0, sy, sy, &cause); | ||||||
|  | 		if (cause != NULL || otherh == 0) { | ||||||
|  | 			otherh = sy - mainh; | ||||||
|  | 			free(cause); | ||||||
|  | 		} else if (otherh > sy || sy - otherh < mainh) | ||||||
|  | 			otherh = sy - mainh; | ||||||
|  | 		else | ||||||
|  | 			mainh = sy - otherh; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	/* Work out what width is needed. */ | ||||||
|  | 	sx = (n * (PANE_MINIMUM + 1)) - 1; | ||||||
|  | 	if (sx < w->sx) | ||||||
|  | 		sx = w->sx; | ||||||
|  |  | ||||||
|  | 	/* Free old tree and create a new root. */ | ||||||
|  | 	layout_free(w); | ||||||
|  | 	lc = w->layout_root = layout_create_cell(NULL); | ||||||
|  | 	layout_set_size(lc, sx, mainh + otherh + 1, 0, 0); | ||||||
|  | 	layout_make_node(lc, LAYOUT_TOPBOTTOM); | ||||||
|  |  | ||||||
|  | 	/* Create the other pane. */ | ||||||
|  | 	lcother = layout_create_cell(lc); | ||||||
|  | 	layout_set_size(lcother, sx, otherh, 0, 0); | ||||||
|  | 	if (n == 1) { | ||||||
|  | 		wp = TAILQ_NEXT(TAILQ_FIRST(&w->panes), entry); | ||||||
|  | 		layout_make_leaf(lcother, wp); | ||||||
|  | 		TAILQ_INSERT_TAIL(&lc->cells, lcother, entry); | ||||||
|  | 	} else { | ||||||
|  | 		layout_make_node(lcother, LAYOUT_LEFTRIGHT); | ||||||
|  | 		TAILQ_INSERT_TAIL(&lc->cells, lcother, entry); | ||||||
|  |  | ||||||
|  | 		/* Add the remaining panes as children. */ | ||||||
|  | 		TAILQ_FOREACH(wp, &w->panes, entry) { | ||||||
|  | 			if (wp == TAILQ_FIRST(&w->panes)) | ||||||
|  | 				continue; | ||||||
|  | 			lcchild = layout_create_cell(lcother); | ||||||
|  | 			layout_set_size(lcchild, PANE_MINIMUM, otherh, 0, 0); | ||||||
|  | 			layout_make_leaf(lcchild, wp); | ||||||
|  | 			TAILQ_INSERT_TAIL(&lcother->cells, lcchild, entry); | ||||||
|  | 		} | ||||||
|  | 		layout_spread_cell(w, lcother); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	/* Create the main pane. */ | ||||||
|  | 	lcmain = layout_create_cell(lc); | ||||||
|  | 	layout_set_size(lcmain, sx, mainh, 0, 0); | ||||||
|  | 	layout_make_leaf(lcmain, TAILQ_FIRST(&w->panes)); | ||||||
|  | 	TAILQ_INSERT_TAIL(&lc->cells, lcmain, entry); | ||||||
|  |  | ||||||
|  | 	/* Fix cell offsets. */ | ||||||
|  | 	layout_fix_offsets(w); | ||||||
|  | 	layout_fix_panes(w, NULL); | ||||||
|  |  | ||||||
|  | 	layout_print_cell(w->layout_root, __func__, 1); | ||||||
|  |  | ||||||
|  | 	window_resize(w, lc->sx, lc->sy, -1, -1); | ||||||
|  | 	notify_window("window-layout-changed", w); | ||||||
|  | 	server_redraw_window(w); | ||||||
|  | } | ||||||
|  |  | ||||||
| static void | static void | ||||||
| layout_set_main_v(struct window *w) | layout_set_main_v(struct window *w) | ||||||
| { | { | ||||||
| @@ -377,6 +479,104 @@ layout_set_main_v(struct window *w) | |||||||
| 	server_redraw_window(w); | 	server_redraw_window(w); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | static void | ||||||
|  | layout_set_main_v_mirrored(struct window *w) | ||||||
|  | { | ||||||
|  | 	struct window_pane	*wp; | ||||||
|  | 	struct layout_cell	*lc, *lcmain, *lcother, *lcchild; | ||||||
|  | 	u_int			 n, mainw, otherw, sx, sy; | ||||||
|  | 	char			*cause; | ||||||
|  | 	const char		*s; | ||||||
|  |  | ||||||
|  | 	layout_print_cell(w->layout_root, __func__, 1); | ||||||
|  |  | ||||||
|  | 	/* Get number of panes. */ | ||||||
|  | 	n = window_count_panes(w); | ||||||
|  | 	if (n <= 1) | ||||||
|  | 		return; | ||||||
|  | 	n--;	/* take off main pane */ | ||||||
|  |  | ||||||
|  | 	/* Find available width - take off one line for the border. */ | ||||||
|  | 	sx = w->sx - 1; | ||||||
|  |  | ||||||
|  | 	/* Get the main pane width. */ | ||||||
|  | 	s = options_get_string(w->options, "main-pane-width"); | ||||||
|  | 	mainw = args_string_percentage(s, 0, sx, sx, &cause); | ||||||
|  | 	if (cause != NULL) { | ||||||
|  | 		mainw = 80; | ||||||
|  | 		free(cause); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	/* Work out the other pane width. */ | ||||||
|  | 	if (mainw + PANE_MINIMUM >= sx) { | ||||||
|  | 		if (sx <= PANE_MINIMUM + PANE_MINIMUM) | ||||||
|  | 			mainw = PANE_MINIMUM; | ||||||
|  | 		else | ||||||
|  | 			mainw = sx - PANE_MINIMUM; | ||||||
|  | 		otherw = PANE_MINIMUM; | ||||||
|  | 	} else { | ||||||
|  | 		s = options_get_string(w->options, "other-pane-width"); | ||||||
|  | 		otherw = args_string_percentage(s, 0, sx, sx, &cause); | ||||||
|  | 		if (cause != NULL || otherw == 0) { | ||||||
|  | 			otherw = sx - mainw; | ||||||
|  | 			free(cause); | ||||||
|  | 		} else if (otherw > sx || sx - otherw < mainw) | ||||||
|  | 			otherw = sx - mainw; | ||||||
|  | 		else | ||||||
|  | 			mainw = sx - otherw; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	/* Work out what height is needed. */ | ||||||
|  | 	sy = (n * (PANE_MINIMUM + 1)) - 1; | ||||||
|  | 	if (sy < w->sy) | ||||||
|  | 		sy = w->sy; | ||||||
|  |  | ||||||
|  | 	/* Free old tree and create a new root. */ | ||||||
|  | 	layout_free(w); | ||||||
|  | 	lc = w->layout_root = layout_create_cell(NULL); | ||||||
|  | 	layout_set_size(lc, mainw + otherw + 1, sy, 0, 0); | ||||||
|  | 	layout_make_node(lc, LAYOUT_LEFTRIGHT); | ||||||
|  |  | ||||||
|  | 	/* Create the other pane. */ | ||||||
|  | 	lcother = layout_create_cell(lc); | ||||||
|  | 	layout_set_size(lcother, otherw, sy, 0, 0); | ||||||
|  | 	if (n == 1) { | ||||||
|  | 		wp = TAILQ_NEXT(TAILQ_FIRST(&w->panes), entry); | ||||||
|  | 		layout_make_leaf(lcother, wp); | ||||||
|  | 		TAILQ_INSERT_TAIL(&lc->cells, lcother, entry); | ||||||
|  | 	} else { | ||||||
|  | 		layout_make_node(lcother, LAYOUT_TOPBOTTOM); | ||||||
|  | 		TAILQ_INSERT_TAIL(&lc->cells, lcother, entry); | ||||||
|  |  | ||||||
|  | 		/* Add the remaining panes as children. */ | ||||||
|  | 		TAILQ_FOREACH(wp, &w->panes, entry) { | ||||||
|  | 			if (wp == TAILQ_FIRST(&w->panes)) | ||||||
|  | 				continue; | ||||||
|  | 			lcchild = layout_create_cell(lcother); | ||||||
|  | 			layout_set_size(lcchild, otherw, PANE_MINIMUM, 0, 0); | ||||||
|  | 			layout_make_leaf(lcchild, wp); | ||||||
|  | 			TAILQ_INSERT_TAIL(&lcother->cells, lcchild, entry); | ||||||
|  | 		} | ||||||
|  | 		layout_spread_cell(w, lcother); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	/* Create the main pane. */ | ||||||
|  | 	lcmain = layout_create_cell(lc); | ||||||
|  | 	layout_set_size(lcmain, mainw, sy, 0, 0); | ||||||
|  | 	layout_make_leaf(lcmain, TAILQ_FIRST(&w->panes)); | ||||||
|  | 	TAILQ_INSERT_TAIL(&lc->cells, lcmain, entry); | ||||||
|  |  | ||||||
|  | 	/* Fix cell offsets. */ | ||||||
|  | 	layout_fix_offsets(w); | ||||||
|  | 	layout_fix_panes(w, NULL); | ||||||
|  |  | ||||||
|  | 	layout_print_cell(w->layout_root, __func__, 1); | ||||||
|  |  | ||||||
|  | 	window_resize(w, lc->sx, lc->sy, -1, -1); | ||||||
|  | 	notify_window("window-layout-changed", w); | ||||||
|  | 	server_redraw_window(w); | ||||||
|  | } | ||||||
|  |  | ||||||
| void | void | ||||||
| layout_set_tiled(struct window *w) | layout_set_tiled(struct window *w) | ||||||
| { | { | ||||||
|   | |||||||
							
								
								
									
										8
									
								
								menu.c
									
									
									
									
									
								
							
							
						
						
									
										8
									
								
								menu.c
									
									
									
									
									
								
							| @@ -335,7 +335,7 @@ menu_key_cb(struct client *c, void *data, struct key_event *event) | |||||||
| 		c->flags |= CLIENT_REDRAWOVERLAY; | 		c->flags |= CLIENT_REDRAWOVERLAY; | ||||||
| 		return (0); | 		return (0); | ||||||
| 	case KEYC_PPAGE: | 	case KEYC_PPAGE: | ||||||
| 	case '\002': /* C-b */ | 	case 'b'|KEYC_CTRL: | ||||||
| 		if (md->choice < 6) | 		if (md->choice < 6) | ||||||
| 			md->choice = 0; | 			md->choice = 0; | ||||||
| 		else { | 		else { | ||||||
| @@ -394,13 +394,13 @@ menu_key_cb(struct client *c, void *data, struct key_event *event) | |||||||
| 		} | 		} | ||||||
| 		c->flags |= CLIENT_REDRAWOVERLAY; | 		c->flags |= CLIENT_REDRAWOVERLAY; | ||||||
| 		break; | 		break; | ||||||
| 	case '\006': /* C-f */ | 	case 'f'|KEYC_CTRL: | ||||||
| 		break; | 		break; | ||||||
| 	case '\r': | 	case '\r': | ||||||
| 		goto chosen; | 		goto chosen; | ||||||
| 	case '\033': /* Escape */ | 	case '\033': /* Escape */ | ||||||
| 	case '\003': /* C-c */ | 	case 'c'|KEYC_CTRL: | ||||||
| 	case '\007': /* C-g */ | 	case 'g'|KEYC_CTRL: | ||||||
| 	case 'q': | 	case 'q': | ||||||
| 		return (1); | 		return (1); | ||||||
| 	} | 	} | ||||||
|   | |||||||
							
								
								
									
										14
									
								
								mode-tree.c
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								mode-tree.c
									
									
									
									
									
								
							| @@ -1088,22 +1088,22 @@ mode_tree_key(struct mode_tree_data *mtd, struct client *c, key_code *key, | |||||||
| 	switch (*key) { | 	switch (*key) { | ||||||
| 	case 'q': | 	case 'q': | ||||||
| 	case '\033': /* Escape */ | 	case '\033': /* Escape */ | ||||||
| 	case '\007': /* C-g */ | 	case 'g'|KEYC_CTRL: | ||||||
| 		return (1); | 		return (1); | ||||||
| 	case KEYC_UP: | 	case KEYC_UP: | ||||||
| 	case 'k': | 	case 'k': | ||||||
| 	case KEYC_WHEELUP_PANE: | 	case KEYC_WHEELUP_PANE: | ||||||
| 	case '\020': /* C-p */ | 	case 'p'|KEYC_CTRL: | ||||||
| 		mode_tree_up(mtd, 1); | 		mode_tree_up(mtd, 1); | ||||||
| 		break; | 		break; | ||||||
| 	case KEYC_DOWN: | 	case KEYC_DOWN: | ||||||
| 	case 'j': | 	case 'j': | ||||||
| 	case KEYC_WHEELDOWN_PANE: | 	case KEYC_WHEELDOWN_PANE: | ||||||
| 	case '\016': /* C-n */ | 	case 'n'|KEYC_CTRL: | ||||||
| 		mode_tree_down(mtd, 1); | 		mode_tree_down(mtd, 1); | ||||||
| 		break; | 		break; | ||||||
| 	case KEYC_PPAGE: | 	case KEYC_PPAGE: | ||||||
| 	case '\002': /* C-b */ | 	case 'b'|KEYC_CTRL: | ||||||
| 		for (i = 0; i < mtd->height; i++) { | 		for (i = 0; i < mtd->height; i++) { | ||||||
| 			if (mtd->current == 0) | 			if (mtd->current == 0) | ||||||
| 				break; | 				break; | ||||||
| @@ -1111,7 +1111,7 @@ mode_tree_key(struct mode_tree_data *mtd, struct client *c, key_code *key, | |||||||
| 		} | 		} | ||||||
| 		break; | 		break; | ||||||
| 	case KEYC_NPAGE: | 	case KEYC_NPAGE: | ||||||
| 	case '\006': /* C-f */ | 	case 'f'|KEYC_CTRL: | ||||||
| 		for (i = 0; i < mtd->height; i++) { | 		for (i = 0; i < mtd->height; i++) { | ||||||
| 			if (mtd->current == mtd->line_size - 1) | 			if (mtd->current == mtd->line_size - 1) | ||||||
| 				break; | 				break; | ||||||
| @@ -1155,7 +1155,7 @@ mode_tree_key(struct mode_tree_data *mtd, struct client *c, key_code *key, | |||||||
| 		for (i = 0; i < mtd->line_size; i++) | 		for (i = 0; i < mtd->line_size; i++) | ||||||
| 			mtd->line_list[i].item->tagged = 0; | 			mtd->line_list[i].item->tagged = 0; | ||||||
| 		break; | 		break; | ||||||
| 	case '\024': /* C-t */ | 	case 't'|KEYC_CTRL: | ||||||
| 		for (i = 0; i < mtd->line_size; i++) { | 		for (i = 0; i < mtd->line_size; i++) { | ||||||
| 			if ((mtd->line_list[i].item->parent == NULL && | 			if ((mtd->line_list[i].item->parent == NULL && | ||||||
| 			    !mtd->line_list[i].item->no_tag) || | 			    !mtd->line_list[i].item->no_tag) || | ||||||
| @@ -1211,7 +1211,7 @@ mode_tree_key(struct mode_tree_data *mtd, struct client *c, key_code *key, | |||||||
| 		break; | 		break; | ||||||
| 	case '?': | 	case '?': | ||||||
| 	case '/': | 	case '/': | ||||||
| 	case '\023': /* C-s */ | 	case 's'|KEYC_CTRL: | ||||||
| 		mtd->references++; | 		mtd->references++; | ||||||
| 		status_prompt_set(c, NULL, "(search) ", "", | 		status_prompt_set(c, NULL, "(search) ", "", | ||||||
| 		    mode_tree_search_callback, mode_tree_search_free, mtd, | 		    mode_tree_search_callback, mode_tree_search_free, mtd, | ||||||
|   | |||||||
| @@ -93,6 +93,9 @@ static const char *options_table_detach_on_destroy_list[] = { | |||||||
| static const char *options_table_extended_keys_list[] = { | static const char *options_table_extended_keys_list[] = { | ||||||
| 	"off", "on", "always", NULL | 	"off", "on", "always", NULL | ||||||
| }; | }; | ||||||
|  | static const char *options_table_extended_keys_format_list[] = { | ||||||
|  | 	"csi-u", "xterm", NULL | ||||||
|  | }; | ||||||
| static const char *options_table_allow_passthrough_list[] = { | static const char *options_table_allow_passthrough_list[] = { | ||||||
| 	"off", "on", "all", NULL | 	"off", "on", "all", NULL | ||||||
| }; | }; | ||||||
| @@ -314,6 +317,14 @@ const struct options_table_entry options_table[] = { | |||||||
| 		  "that support it." | 		  "that support it." | ||||||
| 	}, | 	}, | ||||||
|  |  | ||||||
|  | 	{ .name = "extended-keys-format", | ||||||
|  | 	  .type = OPTIONS_TABLE_CHOICE, | ||||||
|  | 	  .scope = OPTIONS_TABLE_SERVER, | ||||||
|  | 	  .choices = options_table_extended_keys_format_list, | ||||||
|  | 	  .default_num = 1, | ||||||
|  | 	  .text = "The format of emitted extended key sequences." | ||||||
|  | 	}, | ||||||
|  |  | ||||||
| 	{ .name = "focus-events", | 	{ .name = "focus-events", | ||||||
| 	  .type = OPTIONS_TABLE_FLAG, | 	  .type = OPTIONS_TABLE_FLAG, | ||||||
| 	  .scope = OPTIONS_TABLE_SERVER, | 	  .scope = OPTIONS_TABLE_SERVER, | ||||||
| @@ -613,7 +624,7 @@ const struct options_table_entry options_table[] = { | |||||||
| 	{ .name = "prefix", | 	{ .name = "prefix", | ||||||
| 	  .type = OPTIONS_TABLE_KEY, | 	  .type = OPTIONS_TABLE_KEY, | ||||||
| 	  .scope = OPTIONS_TABLE_SESSION, | 	  .scope = OPTIONS_TABLE_SESSION, | ||||||
| 	  .default_num = '\002', | 	  .default_num = 'b'|KEYC_CTRL, | ||||||
| 	  .text = "The prefix key." | 	  .text = "The prefix key." | ||||||
| 	}, | 	}, | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										2
									
								
								popup.c
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								popup.c
									
									
									
									
									
								
							| @@ -542,7 +542,7 @@ popup_key_cb(struct client *c, void *data, struct key_event *event) | |||||||
| 	} | 	} | ||||||
| 	if ((((pd->flags & (POPUP_CLOSEEXIT|POPUP_CLOSEEXITZERO)) == 0) || | 	if ((((pd->flags & (POPUP_CLOSEEXIT|POPUP_CLOSEEXITZERO)) == 0) || | ||||||
| 	    pd->job == NULL) && | 	    pd->job == NULL) && | ||||||
| 	    (event->key == '\033' || event->key == '\003')) | 	    (event->key == '\033' || event->key == ('c'|KEYC_CTRL))) | ||||||
| 		return (1); | 		return (1); | ||||||
| 	if (pd->job != NULL) { | 	if (pd->job != NULL) { | ||||||
| 		if (KEYC_IS_MOUSE(event->key)) { | 		if (KEYC_IS_MOUSE(event->key)) { | ||||||
|   | |||||||
| @@ -326,8 +326,9 @@ screen_write_reset(struct screen_write_ctx *ctx) | |||||||
| 	screen_write_scrollregion(ctx, 0, screen_size_y(s) - 1); | 	screen_write_scrollregion(ctx, 0, screen_size_y(s) - 1); | ||||||
|  |  | ||||||
| 	s->mode = MODE_CURSOR|MODE_WRAP; | 	s->mode = MODE_CURSOR|MODE_WRAP; | ||||||
|  |  | ||||||
| 	if (options_get_number(global_options, "extended-keys") == 2) | 	if (options_get_number(global_options, "extended-keys") == 2) | ||||||
| 		s->mode |= MODE_KEXTENDED; | 		s->mode = (s->mode & ~EXTENDED_KEY_MODES)|MODE_KEYS_EXTENDED; | ||||||
|  |  | ||||||
| 	screen_write_clearscreen(ctx, 8); | 	screen_write_clearscreen(ctx, 8); | ||||||
| 	screen_write_set_cursor(ctx, 0, 0); | 	screen_write_set_cursor(ctx, 0, 0); | ||||||
|   | |||||||
							
								
								
									
										9
									
								
								screen.c
									
									
									
									
									
								
							
							
						
						
									
										9
									
								
								screen.c
									
									
									
									
									
								
							| @@ -110,8 +110,9 @@ screen_reinit(struct screen *s) | |||||||
| 	s->rlower = screen_size_y(s) - 1; | 	s->rlower = screen_size_y(s) - 1; | ||||||
|  |  | ||||||
| 	s->mode = MODE_CURSOR|MODE_WRAP|(s->mode & MODE_CRLF); | 	s->mode = MODE_CURSOR|MODE_WRAP|(s->mode & MODE_CRLF); | ||||||
|  |  | ||||||
| 	if (options_get_number(global_options, "extended-keys") == 2) | 	if (options_get_number(global_options, "extended-keys") == 2) | ||||||
| 		s->mode |= MODE_KEXTENDED; | 		s->mode = (s->mode & ~EXTENDED_KEY_MODES)|MODE_KEYS_EXTENDED; | ||||||
|  |  | ||||||
| 	if (s->saved_grid != NULL) | 	if (s->saved_grid != NULL) | ||||||
| 		screen_alternate_off(s, NULL, 0); | 		screen_alternate_off(s, NULL, 0); | ||||||
| @@ -730,8 +731,10 @@ screen_mode_to_string(int mode) | |||||||
| 		strlcat(tmp, "ORIGIN,", sizeof tmp); | 		strlcat(tmp, "ORIGIN,", sizeof tmp); | ||||||
| 	if (mode & MODE_CRLF) | 	if (mode & MODE_CRLF) | ||||||
| 		strlcat(tmp, "CRLF,", sizeof tmp); | 		strlcat(tmp, "CRLF,", sizeof tmp); | ||||||
| 	if (mode & MODE_KEXTENDED) | 	if (mode & MODE_KEYS_EXTENDED) | ||||||
| 		strlcat(tmp, "KEXTENDED,", sizeof tmp); | 		strlcat(tmp, "KEYS_EXTENDED,", sizeof tmp); | ||||||
|  | 	if (mode & MODE_KEYS_EXTENDED_2) | ||||||
|  | 		strlcat(tmp, "KEYS_EXTENDED_2,", sizeof tmp); | ||||||
| 	tmp[strlen(tmp) - 1] = '\0'; | 	tmp[strlen(tmp) - 1] = '\0'; | ||||||
| 	return (tmp); | 	return (tmp); | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										77
									
								
								status.c
									
									
									
									
									
								
							
							
						
						
									
										77
									
								
								status.c
									
									
									
									
									
								
							| @@ -839,19 +839,19 @@ status_prompt_translate_key(struct client *c, key_code key, key_code *new_key) | |||||||
| { | { | ||||||
| 	if (c->prompt_mode == PROMPT_ENTRY) { | 	if (c->prompt_mode == PROMPT_ENTRY) { | ||||||
| 		switch (key) { | 		switch (key) { | ||||||
| 		case '\001': /* C-a */ | 		case 'a'|KEYC_CTRL: | ||||||
| 		case '\003': /* C-c */ | 		case 'c'|KEYC_CTRL: | ||||||
| 		case '\005': /* C-e */ | 		case 'e'|KEYC_CTRL: | ||||||
| 		case '\007': /* C-g */ | 		case 'g'|KEYC_CTRL: | ||||||
| 		case '\010': /* C-h */ | 		case 'h'|KEYC_CTRL: | ||||||
| 		case '\011': /* Tab */ | 		case '\011': /* Tab */ | ||||||
| 		case '\013': /* C-k */ | 		case 'k'|KEYC_CTRL: | ||||||
| 		case '\016': /* C-n */ | 		case 'n'|KEYC_CTRL: | ||||||
| 		case '\020': /* C-p */ | 		case 'p'|KEYC_CTRL: | ||||||
| 		case '\024': /* C-t */ | 		case 't'|KEYC_CTRL: | ||||||
| 		case '\025': /* C-u */ | 		case 'u'|KEYC_CTRL: | ||||||
| 		case '\027': /* C-w */ | 		case 'w'|KEYC_CTRL: | ||||||
| 		case '\031': /* C-y */ | 		case 'y'|KEYC_CTRL: | ||||||
| 		case '\n': | 		case '\n': | ||||||
| 		case '\r': | 		case '\r': | ||||||
| 		case KEYC_LEFT|KEYC_CTRL: | 		case KEYC_LEFT|KEYC_CTRL: | ||||||
| @@ -890,7 +890,7 @@ status_prompt_translate_key(struct client *c, key_code key, key_code *new_key) | |||||||
| 	case 'S': | 	case 'S': | ||||||
| 		c->prompt_mode = PROMPT_ENTRY; | 		c->prompt_mode = PROMPT_ENTRY; | ||||||
| 		c->flags |= CLIENT_REDRAWSTATUS; | 		c->flags |= CLIENT_REDRAWSTATUS; | ||||||
| 		*new_key = '\025'; /* C-u */ | 		*new_key = 'u'|KEYC_CTRL; | ||||||
| 		return (1); | 		return (1); | ||||||
| 	case 'i': | 	case 'i': | ||||||
| 	case '\033': /* Escape */ | 	case '\033': /* Escape */ | ||||||
| @@ -911,7 +911,7 @@ status_prompt_translate_key(struct client *c, key_code key, key_code *new_key) | |||||||
| 		return (1); | 		return (1); | ||||||
| 	case 'C': | 	case 'C': | ||||||
| 	case 'D': | 	case 'D': | ||||||
| 		*new_key = '\013'; /* C-k */ | 		*new_key = 'k'|KEYC_CTRL; | ||||||
| 		return (1); | 		return (1); | ||||||
| 	case KEYC_BSPACE: | 	case KEYC_BSPACE: | ||||||
| 	case 'X': | 	case 'X': | ||||||
| @@ -924,7 +924,7 @@ status_prompt_translate_key(struct client *c, key_code key, key_code *new_key) | |||||||
| 		*new_key = 'B'|KEYC_VI; | 		*new_key = 'B'|KEYC_VI; | ||||||
| 		return (1); | 		return (1); | ||||||
| 	case 'd': | 	case 'd': | ||||||
| 		*new_key = '\025'; /* C-u */ | 		*new_key = 'u'|KEYC_CTRL; | ||||||
| 		return (1); | 		return (1); | ||||||
| 	case 'e': | 	case 'e': | ||||||
| 		*new_key = 'e'|KEYC_VI; | 		*new_key = 'e'|KEYC_VI; | ||||||
| @@ -939,10 +939,10 @@ status_prompt_translate_key(struct client *c, key_code key, key_code *new_key) | |||||||
| 		*new_key = 'W'|KEYC_VI; | 		*new_key = 'W'|KEYC_VI; | ||||||
| 		return (1); | 		return (1); | ||||||
| 	case 'p': | 	case 'p': | ||||||
| 		*new_key = '\031'; /* C-y */ | 		*new_key = 'y'|KEYC_CTRL; | ||||||
| 		return (1); | 		return (1); | ||||||
| 	case 'q': | 	case 'q': | ||||||
| 		*new_key = '\003'; /* C-c */ | 		*new_key = 'c'|KEYC_CTRL; | ||||||
| 		return (1); | 		return (1); | ||||||
| 	case 's': | 	case 's': | ||||||
| 	case KEYC_DC: | 	case KEYC_DC: | ||||||
| @@ -966,8 +966,8 @@ status_prompt_translate_key(struct client *c, key_code key, key_code *new_key) | |||||||
| 	case 'k': | 	case 'k': | ||||||
| 		*new_key = KEYC_UP; | 		*new_key = KEYC_UP; | ||||||
| 		return (1); | 		return (1); | ||||||
| 	case '\010' /* C-h */: | 	case 'h'|KEYC_CTRL: | ||||||
| 	case '\003' /* C-c */: | 	case 'c'|KEYC_CTRL: | ||||||
| 	case '\n': | 	case '\n': | ||||||
| 	case '\r': | 	case '\r': | ||||||
| 		return (1); | 		return (1); | ||||||
| @@ -1263,28 +1263,28 @@ status_prompt_key(struct client *c, key_code key) | |||||||
| process_key: | process_key: | ||||||
| 	switch (key) { | 	switch (key) { | ||||||
| 	case KEYC_LEFT: | 	case KEYC_LEFT: | ||||||
| 	case '\002': /* C-b */ | 	case 'b'|KEYC_CTRL: | ||||||
| 		if (c->prompt_index > 0) { | 		if (c->prompt_index > 0) { | ||||||
| 			c->prompt_index--; | 			c->prompt_index--; | ||||||
| 			break; | 			break; | ||||||
| 		} | 		} | ||||||
| 		break; | 		break; | ||||||
| 	case KEYC_RIGHT: | 	case KEYC_RIGHT: | ||||||
| 	case '\006': /* C-f */ | 	case 'f'|KEYC_CTRL: | ||||||
| 		if (c->prompt_index < size) { | 		if (c->prompt_index < size) { | ||||||
| 			c->prompt_index++; | 			c->prompt_index++; | ||||||
| 			break; | 			break; | ||||||
| 		} | 		} | ||||||
| 		break; | 		break; | ||||||
| 	case KEYC_HOME: | 	case KEYC_HOME: | ||||||
| 	case '\001': /* C-a */ | 	case 'a'|KEYC_CTRL: | ||||||
| 		if (c->prompt_index != 0) { | 		if (c->prompt_index != 0) { | ||||||
| 			c->prompt_index = 0; | 			c->prompt_index = 0; | ||||||
| 			break; | 			break; | ||||||
| 		} | 		} | ||||||
| 		break; | 		break; | ||||||
| 	case KEYC_END: | 	case KEYC_END: | ||||||
| 	case '\005': /* C-e */ | 	case 'e'|KEYC_CTRL: | ||||||
| 		if (c->prompt_index != size) { | 		if (c->prompt_index != size) { | ||||||
| 			c->prompt_index = size; | 			c->prompt_index = size; | ||||||
| 			break; | 			break; | ||||||
| @@ -1295,7 +1295,7 @@ process_key: | |||||||
| 			goto changed; | 			goto changed; | ||||||
| 		break; | 		break; | ||||||
| 	case KEYC_BSPACE: | 	case KEYC_BSPACE: | ||||||
| 	case '\010': /* C-h */ | 	case 'h'|KEYC_CTRL: | ||||||
| 		if (c->prompt_index != 0) { | 		if (c->prompt_index != 0) { | ||||||
| 			if (c->prompt_index == size) | 			if (c->prompt_index == size) | ||||||
| 				c->prompt_buffer[--c->prompt_index].size = 0; | 				c->prompt_buffer[--c->prompt_index].size = 0; | ||||||
| @@ -1310,7 +1310,7 @@ process_key: | |||||||
| 		} | 		} | ||||||
| 		break; | 		break; | ||||||
| 	case KEYC_DC: | 	case KEYC_DC: | ||||||
| 	case '\004': /* C-d */ | 	case 'd'|KEYC_CTRL: | ||||||
| 		if (c->prompt_index != size) { | 		if (c->prompt_index != size) { | ||||||
| 			memmove(c->prompt_buffer + c->prompt_index, | 			memmove(c->prompt_buffer + c->prompt_index, | ||||||
| 			    c->prompt_buffer + c->prompt_index + 1, | 			    c->prompt_buffer + c->prompt_index + 1, | ||||||
| @@ -1319,17 +1319,17 @@ process_key: | |||||||
| 			goto changed; | 			goto changed; | ||||||
| 		} | 		} | ||||||
| 		break; | 		break; | ||||||
| 	case '\025': /* C-u */ | 	case 'u'|KEYC_CTRL: | ||||||
| 		c->prompt_buffer[0].size = 0; | 		c->prompt_buffer[0].size = 0; | ||||||
| 		c->prompt_index = 0; | 		c->prompt_index = 0; | ||||||
| 		goto changed; | 		goto changed; | ||||||
| 	case '\013': /* C-k */ | 	case 'k'|KEYC_CTRL: | ||||||
| 		if (c->prompt_index < size) { | 		if (c->prompt_index < size) { | ||||||
| 			c->prompt_buffer[c->prompt_index].size = 0; | 			c->prompt_buffer[c->prompt_index].size = 0; | ||||||
| 			goto changed; | 			goto changed; | ||||||
| 		} | 		} | ||||||
| 		break; | 		break; | ||||||
| 	case '\027': /* C-w */ | 	case 'w'|KEYC_CTRL: | ||||||
| 		separators = options_get_string(oo, "word-separators"); | 		separators = options_get_string(oo, "word-separators"); | ||||||
| 		idx = c->prompt_index; | 		idx = c->prompt_index; | ||||||
|  |  | ||||||
| @@ -1397,7 +1397,7 @@ process_key: | |||||||
| 		status_prompt_backward_word(c, separators); | 		status_prompt_backward_word(c, separators); | ||||||
| 		goto changed; | 		goto changed; | ||||||
| 	case KEYC_UP: | 	case KEYC_UP: | ||||||
| 	case '\020': /* C-p */ | 	case 'p'|KEYC_CTRL: | ||||||
| 		histstr = status_prompt_up_history(c->prompt_hindex, | 		histstr = status_prompt_up_history(c->prompt_hindex, | ||||||
| 		    c->prompt_type); | 		    c->prompt_type); | ||||||
| 		if (histstr == NULL) | 		if (histstr == NULL) | ||||||
| @@ -1407,7 +1407,7 @@ process_key: | |||||||
| 		c->prompt_index = utf8_strlen(c->prompt_buffer); | 		c->prompt_index = utf8_strlen(c->prompt_buffer); | ||||||
| 		goto changed; | 		goto changed; | ||||||
| 	case KEYC_DOWN: | 	case KEYC_DOWN: | ||||||
| 	case '\016': /* C-n */ | 	case 'n'|KEYC_CTRL: | ||||||
| 		histstr = status_prompt_down_history(c->prompt_hindex, | 		histstr = status_prompt_down_history(c->prompt_hindex, | ||||||
| 		    c->prompt_type); | 		    c->prompt_type); | ||||||
| 		if (histstr == NULL) | 		if (histstr == NULL) | ||||||
| @@ -1416,11 +1416,11 @@ process_key: | |||||||
| 		c->prompt_buffer = utf8_fromcstr(histstr); | 		c->prompt_buffer = utf8_fromcstr(histstr); | ||||||
| 		c->prompt_index = utf8_strlen(c->prompt_buffer); | 		c->prompt_index = utf8_strlen(c->prompt_buffer); | ||||||
| 		goto changed; | 		goto changed; | ||||||
| 	case '\031': /* C-y */ | 	case 'y'|KEYC_CTRL: | ||||||
| 		if (status_prompt_paste(c)) | 		if (status_prompt_paste(c)) | ||||||
| 			goto changed; | 			goto changed; | ||||||
| 		break; | 		break; | ||||||
| 	case '\024': /* C-t */ | 	case 't'|KEYC_CTRL: | ||||||
| 		idx = c->prompt_index; | 		idx = c->prompt_index; | ||||||
| 		if (idx < size) | 		if (idx < size) | ||||||
| 			idx++; | 			idx++; | ||||||
| @@ -1443,12 +1443,12 @@ process_key: | |||||||
| 		free(s); | 		free(s); | ||||||
| 		break; | 		break; | ||||||
| 	case '\033': /* Escape */ | 	case '\033': /* Escape */ | ||||||
| 	case '\003': /* C-c */ | 	case 'c'|KEYC_CTRL: | ||||||
| 	case '\007': /* C-g */ | 	case 'g'|KEYC_CTRL: | ||||||
| 		if (c->prompt_inputcb(c, c->prompt_data, NULL, 1) == 0) | 		if (c->prompt_inputcb(c, c->prompt_data, NULL, 1) == 0) | ||||||
| 			status_prompt_clear(c); | 			status_prompt_clear(c); | ||||||
| 		break; | 		break; | ||||||
| 	case '\022': /* C-r */ | 	case 'r'|KEYC_CTRL: | ||||||
| 		if (~c->prompt_flags & PROMPT_INCREMENTAL) | 		if (~c->prompt_flags & PROMPT_INCREMENTAL) | ||||||
| 			break; | 			break; | ||||||
| 		if (c->prompt_buffer[0].size == 0) { | 		if (c->prompt_buffer[0].size == 0) { | ||||||
| @@ -1459,7 +1459,7 @@ process_key: | |||||||
| 		} else | 		} else | ||||||
| 			prefix = '-'; | 			prefix = '-'; | ||||||
| 		goto changed; | 		goto changed; | ||||||
| 	case '\023': /* C-s */ | 	case 's'|KEYC_CTRL: | ||||||
| 		if (~c->prompt_flags & PROMPT_INCREMENTAL) | 		if (~c->prompt_flags & PROMPT_INCREMENTAL) | ||||||
| 			break; | 			break; | ||||||
| 		if (c->prompt_buffer[0].size == 0) { | 		if (c->prompt_buffer[0].size == 0) { | ||||||
| @@ -1626,8 +1626,9 @@ status_prompt_complete_list(u_int *size, const char *s, int at_start) | |||||||
| 	struct options_entry			 *o; | 	struct options_entry			 *o; | ||||||
| 	struct options_array_item		 *a; | 	struct options_array_item		 *a; | ||||||
| 	const char				 *layouts[] = { | 	const char				 *layouts[] = { | ||||||
| 		"even-horizontal", "even-vertical", "main-horizontal", | 		"even-horizontal", "even-vertical", | ||||||
| 		"main-vertical", "tiled", NULL | 		"main-horizontal", "main-horizontal-mirrored", | ||||||
|  | 		"main-vertical", "main-vertical-mirrored", "tiled", NULL | ||||||
| 	}; | 	}; | ||||||
|  |  | ||||||
| 	*size = 0; | 	*size = 0; | ||||||
|   | |||||||
							
								
								
									
										114
									
								
								tmux.1
									
									
									
									
									
								
							
							
						
						
									
										114
									
								
								tmux.1
									
									
									
									
									
								
							| @@ -372,8 +372,10 @@ Enter copy mode and scroll one page up. | |||||||
| Change to the pane above, below, to the left, or to the right of the current | Change to the pane above, below, to the left, or to the right of the current | ||||||
| pane. | pane. | ||||||
| .It M-1 to M-5 | .It M-1 to M-5 | ||||||
| Arrange panes in one of the five preset layouts: even-horizontal, | Arrange panes in one of the seven preset layouts: | ||||||
| even-vertical, main-horizontal, main-vertical, or tiled. | even-horizontal, even-vertical, | ||||||
|  | main-horizontal, main-horizontal-mirrored, | ||||||
|  | main-vertical, main-vertical, or tiled. | ||||||
| .It Space | .It Space | ||||||
| Arrange the current window in the next preset layout. | Arrange the current window in the next preset layout. | ||||||
| .It M-n | .It M-n | ||||||
| @@ -2164,14 +2166,20 @@ are spread from left to right in the leftover space at the bottom. | |||||||
| Use the | Use the | ||||||
| .Em main-pane-height | .Em main-pane-height | ||||||
| window option to specify the height of the top pane. | window option to specify the height of the top pane. | ||||||
| .It Ic main-vertical | .It Ic main-horizontal-mirrored | ||||||
| Similar to | The same as | ||||||
| .Ic main-horizontal | .Ic main-horizontal | ||||||
| but the large pane is placed on the left and the others spread from top to | but mirrored so the main pane is at the bottom of the window. | ||||||
| bottom along the right. | .It Ic main-vertical | ||||||
| See the | A large (main) pane is shown on the left of the window and the remaining panes | ||||||
|  | are spread from top to bottom in the leftover space on the right. | ||||||
|  | Use the | ||||||
| .Em main-pane-width | .Em main-pane-width | ||||||
| window option. | window option to specify the width of the left pane. | ||||||
|  | .It Ic main-vertical-mirrored | ||||||
|  | The same as | ||||||
|  | .Ic main-vertical | ||||||
|  | but mirrored so the main pane is on the right of the window. | ||||||
| .It Ic tiled | .It Ic tiled | ||||||
| Panes are spread out as evenly as possible over the window in both rows and | Panes are spread out as evenly as possible over the window in both rows and | ||||||
| columns. | columns. | ||||||
| @@ -3735,6 +3743,10 @@ Note that aliases are expanded when a command is parsed rather than when it is | |||||||
| executed, so binding an alias with | executed, so binding an alias with | ||||||
| .Ic bind-key | .Ic bind-key | ||||||
| will bind the expanded form. | will bind the expanded form. | ||||||
|  | .It Ic copy-command Ar shell-command | ||||||
|  | Give the command to pipe to if the | ||||||
|  | .Ic copy-pipe | ||||||
|  | copy mode command is used without arguments. | ||||||
| .It Ic default-terminal Ar terminal | .It Ic default-terminal Ar terminal | ||||||
| Set the default terminal for new windows created in this session - the | Set the default terminal for new windows created in this session - the | ||||||
| default value of the | default value of the | ||||||
| @@ -3748,10 +3760,6 @@ be set to | |||||||
| .Ql screen , | .Ql screen , | ||||||
| .Ql tmux | .Ql tmux | ||||||
| or a derivative of them. | or a derivative of them. | ||||||
| .It Ic copy-command Ar shell-command |  | ||||||
| Give the command to pipe to if the |  | ||||||
| .Ic copy-pipe |  | ||||||
| copy mode command is used without arguments. |  | ||||||
| .It Ic escape-time Ar time | .It Ic escape-time Ar time | ||||||
| Set the time in milliseconds for which | Set the time in milliseconds for which | ||||||
| .Nm | .Nm | ||||||
| @@ -3773,22 +3781,53 @@ If enabled, the server will exit when there are no attached clients. | |||||||
| .It Xo Ic extended-keys | .It Xo Ic extended-keys | ||||||
| .Op Ic on | off | always | .Op Ic on | off | always | ||||||
| .Xc | .Xc | ||||||
| When | Controls how modified keys (keys pressed together with Control, Meta, or Shift) | ||||||
| .Ic on | are reported. | ||||||
| or | This is the equivalent of the | ||||||
| .Ic always , | .Ic modifyOtherKeys | ||||||
| the escape sequence to enable extended keys is sent to the terminal, if | .Xr xterm 1 | ||||||
| .Nm | resource. | ||||||
| knows that it is supported. | .Pp | ||||||
| .Nm | When set to | ||||||
| always recognises extended keys itself. |  | ||||||
| If this option is |  | ||||||
| .Ic on , | .Ic on , | ||||||
| .Nm | the program inside the pane can request one of two modes: mode 1 which changes | ||||||
| will only forward extended keys to applications when they request them; if | the sequence for only keys which lack an existing well-known representation; or | ||||||
|  | mode 2 which changes the sequence for all keys. | ||||||
|  | When set to | ||||||
| .Ic always , | .Ic always , | ||||||
|  | mode 1 output is forced and the program cannot change it. | ||||||
|  | When set to | ||||||
|  | .Ic off , | ||||||
|  | this feature is disabled and only standard keys are reported. | ||||||
|  | .Pp | ||||||
| .Nm | .Nm | ||||||
| will always forward the keys. | will always request extended keys itself if the terminal supports them. | ||||||
|  | See also the | ||||||
|  | .Ic extkeys | ||||||
|  | feature for the | ||||||
|  | .Ic terminal-features | ||||||
|  | option, the | ||||||
|  | .Ic extended-keys-format | ||||||
|  | option and the | ||||||
|  | .Ic pane_key_mode | ||||||
|  | variable. | ||||||
|  | .It Xo Ic extended-keys-format | ||||||
|  | .Op Ic csi-u | xterm | ||||||
|  | .Xc | ||||||
|  | Selects one of the two possible formats for reporting modified keys to | ||||||
|  | applications. | ||||||
|  | This is the equivalent of the | ||||||
|  | .Ic formatOtherKeys | ||||||
|  | .Xr xterm 1 | ||||||
|  | resource. | ||||||
|  | For example, C-S-a will be reported as | ||||||
|  | .Ql ^[[27;6;65~ | ||||||
|  | when set to | ||||||
|  | .Ic xterm , | ||||||
|  | and as | ||||||
|  | .Ql ^[[65;6u | ||||||
|  | when set to | ||||||
|  | .Ic csi-u . | ||||||
| .It Xo Ic focus-events | .It Xo Ic focus-events | ||||||
| .Op Ic on | off | .Op Ic on | off | ||||||
| .Xc | .Xc | ||||||
| @@ -4454,9 +4493,11 @@ Set the character used to fill areas of the terminal unused by a window. | |||||||
| .It Ic main-pane-height Ar height | .It Ic main-pane-height Ar height | ||||||
| .It Ic main-pane-width Ar width | .It Ic main-pane-width Ar width | ||||||
| Set the width or height of the main (left or top) pane in the | Set the width or height of the main (left or top) pane in the | ||||||
| .Ic main-horizontal | .Ic main-horizontal, | ||||||
|  | .Ic main-horizontal-mirrored, | ||||||
|  | .Ic main-vertical, | ||||||
| or | or | ||||||
| .Ic main-vertical | .Ic main-vertical-mirrored | ||||||
| layouts. | layouts. | ||||||
| If suffixed by | If suffixed by | ||||||
| .Ql % , | .Ql % , | ||||||
| @@ -4530,7 +4571,9 @@ An interval of zero disables the monitoring. | |||||||
| .It Ic other-pane-height Ar height | .It Ic other-pane-height Ar height | ||||||
| Set the height of the other panes (not the main pane) in the | Set the height of the other panes (not the main pane) in the | ||||||
| .Ic main-horizontal | .Ic main-horizontal | ||||||
| layout. | and | ||||||
|  | .Ic main-horizontal-mirrored | ||||||
|  | layouts. | ||||||
| If this option is set to 0 (the default), it will have no effect. | If this option is set to 0 (the default), it will have no effect. | ||||||
| If both the | If both the | ||||||
| .Ic main-pane-height | .Ic main-pane-height | ||||||
| @@ -4547,7 +4590,9 @@ Like | |||||||
| .Ic other-pane-height , | .Ic other-pane-height , | ||||||
| but set the width of other panes in the | but set the width of other panes in the | ||||||
| .Ic main-vertical | .Ic main-vertical | ||||||
| layout. | and | ||||||
|  | .Ic main-vertical-mirrored | ||||||
|  | layouts. | ||||||
| .Pp | .Pp | ||||||
| .It Ic pane-active-border-style Ar style | .It Ic pane-active-border-style Ar style | ||||||
| Set the pane border style for the currently active pane. | Set the pane border style for the currently active pane. | ||||||
| @@ -5514,6 +5559,7 @@ The following variables are available, where appropriate: | |||||||
| .It Li "pane_in_mode" Ta "" Ta "1 if pane is in a mode" | .It Li "pane_in_mode" Ta "" Ta "1 if pane is in a mode" | ||||||
| .It Li "pane_index" Ta "#P" Ta "Index of pane" | .It Li "pane_index" Ta "#P" Ta "Index of pane" | ||||||
| .It Li "pane_input_off" Ta "" Ta "1 if input to pane is disabled" | .It Li "pane_input_off" Ta "" Ta "1 if input to pane is disabled" | ||||||
|  | .It Li "pane_key_mode" Ta "" Ta "Extended key reporting mode in this pane" | ||||||
| .It Li "pane_last" Ta "" Ta "1 if last pane" | .It Li "pane_last" Ta "" Ta "1 if last pane" | ||||||
| .It Li "pane_left" Ta "" Ta "Left of pane" | .It Li "pane_left" Ta "" Ta "Left of pane" | ||||||
| .It Li "pane_marked" Ta "" Ta "1 if this is the marked pane" | .It Li "pane_marked" Ta "" Ta "1 if this is the marked pane" | ||||||
| @@ -6572,6 +6618,11 @@ is given, the buffer is also sent to the clipboard for | |||||||
| using the | using the | ||||||
| .Xr xterm 1 | .Xr xterm 1 | ||||||
| escape sequence, if possible. | escape sequence, if possible. | ||||||
|  | If | ||||||
|  | .Ar path | ||||||
|  | is | ||||||
|  | .Ql - , | ||||||
|  | the contents are read from stdin. | ||||||
| .Tg pasteb | .Tg pasteb | ||||||
| .It Xo Ic paste-buffer | .It Xo Ic paste-buffer | ||||||
| .Op Fl dpr | .Op Fl dpr | ||||||
| @@ -6609,6 +6660,11 @@ Save the contents of the specified paste buffer to | |||||||
| The | The | ||||||
| .Fl a | .Fl a | ||||||
| option appends to rather than overwriting the file. | option appends to rather than overwriting the file. | ||||||
|  | If | ||||||
|  | .Ar path | ||||||
|  | is | ||||||
|  | .Ql - , | ||||||
|  | the contents are read from stdin. | ||||||
| .It Xo Ic set-buffer | .It Xo Ic set-buffer | ||||||
| .Op Fl aw | .Op Fl aw | ||||||
| .Op Fl b Ar buffer-name | .Op Fl b Ar buffer-name | ||||||
|   | |||||||
							
								
								
									
										43
									
								
								tmux.h
									
									
									
									
									
								
							
							
						
						
									
										43
									
								
								tmux.h
									
									
									
									
									
								
							| @@ -147,8 +147,7 @@ struct winlink; | |||||||
| #define KEYC_IMPLIED_META    0x08000000000000ULL | #define KEYC_IMPLIED_META    0x08000000000000ULL | ||||||
| #define KEYC_BUILD_MODIFIERS 0x10000000000000ULL | #define KEYC_BUILD_MODIFIERS 0x10000000000000ULL | ||||||
| #define KEYC_VI		     0x20000000000000ULL | #define KEYC_VI		     0x20000000000000ULL | ||||||
| #define KEYC_EXTENDED	     0x40000000000000ULL | #define KEYC_SENT	     0x40000000000000ULL | ||||||
| #define KEYC_SENT	     0x80000000000000ULL |  | ||||||
|  |  | ||||||
| /* Masks for key bits. */ | /* Masks for key bits. */ | ||||||
| #define KEYC_MASK_MODIFIERS  0x00f00000000000ULL | #define KEYC_MASK_MODIFIERS  0x00f00000000000ULL | ||||||
| @@ -196,6 +195,42 @@ struct winlink; | |||||||
|  */ |  */ | ||||||
| typedef unsigned long long key_code; | typedef unsigned long long key_code; | ||||||
|  |  | ||||||
|  | /* C0 control characters */ | ||||||
|  | enum { | ||||||
|  | 	C0_NUL, | ||||||
|  | 	C0_SOH, | ||||||
|  | 	C0_STX, | ||||||
|  | 	C0_ETX, | ||||||
|  | 	C0_EOT, | ||||||
|  | 	C0_ENQ, | ||||||
|  | 	C0_ASC, | ||||||
|  | 	C0_BEL, | ||||||
|  | 	C0_BS, | ||||||
|  | 	C0_HT, | ||||||
|  | 	C0_LF, | ||||||
|  | 	C0_VT, | ||||||
|  | 	C0_FF, | ||||||
|  | 	C0_CR, | ||||||
|  | 	C0_SO, | ||||||
|  | 	C0_SI, | ||||||
|  | 	C0_DLE, | ||||||
|  | 	C0_DC1, | ||||||
|  | 	C0_DC2, | ||||||
|  | 	C0_DC3, | ||||||
|  | 	C0_DC4, | ||||||
|  | 	C0_NAK, | ||||||
|  | 	C0_SYN, | ||||||
|  | 	C0_ETB, | ||||||
|  | 	C0_CAN, | ||||||
|  | 	C0_EM, | ||||||
|  | 	C0_SUB, | ||||||
|  | 	C0_ESC, | ||||||
|  | 	C0_FS, | ||||||
|  | 	C0_GS, | ||||||
|  | 	C0_RS, | ||||||
|  | 	C0_US | ||||||
|  | }; | ||||||
|  |  | ||||||
| /* Special key codes. */ | /* Special key codes. */ | ||||||
| enum { | enum { | ||||||
| 	/* Focus events. */ | 	/* Focus events. */ | ||||||
| @@ -591,14 +626,16 @@ enum tty_code_code { | |||||||
| #define MODE_MOUSE_ALL 0x1000 | #define MODE_MOUSE_ALL 0x1000 | ||||||
| #define MODE_ORIGIN 0x2000 | #define MODE_ORIGIN 0x2000 | ||||||
| #define MODE_CRLF 0x4000 | #define MODE_CRLF 0x4000 | ||||||
| #define MODE_KEXTENDED 0x8000 | #define MODE_KEYS_EXTENDED 0x8000 | ||||||
| #define MODE_CURSOR_VERY_VISIBLE 0x10000 | #define MODE_CURSOR_VERY_VISIBLE 0x10000 | ||||||
| #define MODE_CURSOR_BLINKING_SET 0x20000 | #define MODE_CURSOR_BLINKING_SET 0x20000 | ||||||
|  | #define MODE_KEYS_EXTENDED_2 0x40000 | ||||||
|  |  | ||||||
| #define ALL_MODES 0xffffff | #define ALL_MODES 0xffffff | ||||||
| #define ALL_MOUSE_MODES (MODE_MOUSE_STANDARD|MODE_MOUSE_BUTTON|MODE_MOUSE_ALL) | #define ALL_MOUSE_MODES (MODE_MOUSE_STANDARD|MODE_MOUSE_BUTTON|MODE_MOUSE_ALL) | ||||||
| #define MOTION_MOUSE_MODES (MODE_MOUSE_BUTTON|MODE_MOUSE_ALL) | #define MOTION_MOUSE_MODES (MODE_MOUSE_BUTTON|MODE_MOUSE_ALL) | ||||||
| #define CURSOR_MODES (MODE_CURSOR|MODE_CURSOR_BLINKING|MODE_CURSOR_VERY_VISIBLE) | #define CURSOR_MODES (MODE_CURSOR|MODE_CURSOR_BLINKING|MODE_CURSOR_VERY_VISIBLE) | ||||||
|  | #define EXTENDED_KEY_MODES (MODE_KEYS_EXTENDED|MODE_KEYS_EXTENDED_2) | ||||||
|  |  | ||||||
| /* Mouse protocol constants. */ | /* Mouse protocol constants. */ | ||||||
| #define MOUSE_PARAM_MAX 0xff | #define MOUSE_PARAM_MAX 0xff | ||||||
|   | |||||||
| @@ -237,7 +237,7 @@ static const struct tty_feature tty_feature_sync = { | |||||||
|  |  | ||||||
| /* Terminal supports extended keys. */ | /* Terminal supports extended keys. */ | ||||||
| static const char *const tty_feature_extkeys_capabilities[] = { | static const char *const tty_feature_extkeys_capabilities[] = { | ||||||
| 	"Eneks=\\E[>4;1m", | 	"Eneks=\\E[>4;2m", | ||||||
| 	"Dseks=\\E[>4m", | 	"Dseks=\\E[>4m", | ||||||
| 	NULL | 	NULL | ||||||
| }; | }; | ||||||
|   | |||||||
							
								
								
									
										58
									
								
								tty-keys.c
									
									
									
									
									
								
							
							
						
						
									
										58
									
								
								tty-keys.c
									
									
									
									
									
								
							| @@ -664,7 +664,7 @@ tty_keys_next(struct tty *tty) | |||||||
| 	size_t			 len, size; | 	size_t			 len, size; | ||||||
| 	cc_t			 bspace; | 	cc_t			 bspace; | ||||||
| 	int			 delay, expired = 0, n; | 	int			 delay, expired = 0, n; | ||||||
| 	key_code		 key; | 	key_code		 key, onlykey; | ||||||
| 	struct mouse_event	 m = { 0 }; | 	struct mouse_event	 m = { 0 }; | ||||||
| 	struct key_event	*event; | 	struct key_event	*event; | ||||||
|  |  | ||||||
| @@ -801,6 +801,26 @@ first_key: | |||||||
| 		key = (u_char)buf[0]; | 		key = (u_char)buf[0]; | ||||||
| 		size = 1; | 		size = 1; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	/* C-Space is special. */ | ||||||
|  | 	if ((key & KEYC_MASK_KEY) == C0_NUL) | ||||||
|  | 		key = ' ' | KEYC_CTRL | (key & KEYC_META); | ||||||
|  |  | ||||||
|  | 	/* | ||||||
|  | 	 * Fix up all C0 control codes that don't have a dedicated key into | ||||||
|  | 	 * corresponding Ctrl keys. Convert characters in the A-Z range into | ||||||
|  | 	 * lowercase, so ^A becomes a|CTRL. | ||||||
|  | 	 */ | ||||||
|  | 	onlykey = key & KEYC_MASK_KEY; | ||||||
|  | 	if (onlykey < 0x20 && onlykey != C0_BS && | ||||||
|  | 	    onlykey != C0_HT && onlykey != C0_CR && | ||||||
|  | 	    onlykey != C0_ESC) { | ||||||
|  | 		onlykey |= 0x40; | ||||||
|  | 		if (onlykey >= 'A' && onlykey <= 'Z') | ||||||
|  | 			onlykey |= 0x20; | ||||||
|  | 		key = onlykey | KEYC_CTRL | (key & KEYC_META); | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	goto complete_key; | 	goto complete_key; | ||||||
|  |  | ||||||
| partial_key: | partial_key: | ||||||
| @@ -910,7 +930,6 @@ tty_keys_extended_key(struct tty *tty, const char *buf, size_t len, | |||||||
| 	char		 tmp[64]; | 	char		 tmp[64]; | ||||||
| 	cc_t		 bspace; | 	cc_t		 bspace; | ||||||
| 	key_code	 nkey; | 	key_code	 nkey; | ||||||
| 	key_code	 onlykey; |  | ||||||
| 	struct utf8_data ud; | 	struct utf8_data ud; | ||||||
| 	utf8_char        uc; | 	utf8_char        uc; | ||||||
|  |  | ||||||
| @@ -974,7 +993,13 @@ tty_keys_extended_key(struct tty *tty, const char *buf, size_t len, | |||||||
| 	/* Update the modifiers. */ | 	/* Update the modifiers. */ | ||||||
| 	if (modifiers > 0) { | 	if (modifiers > 0) { | ||||||
| 		modifiers--; | 		modifiers--; | ||||||
| 		if (modifiers & 1) | 		/* | ||||||
|  | 		 * The Shift modifier may not be reported in some input modes, | ||||||
|  | 		 * which is unfortunate, as in general case determining if a | ||||||
|  | 		 * character is shifted or not requires knowing the input | ||||||
|  | 		 * keyboard layout. So we only fix up the trivial case. | ||||||
|  | 		 */ | ||||||
|  | 		if (modifiers & 1 || (nkey >= 'A' && nkey <= 'Z')) | ||||||
| 			nkey |= KEYC_SHIFT; | 			nkey |= KEYC_SHIFT; | ||||||
| 		if (modifiers & 2) | 		if (modifiers & 2) | ||||||
| 			nkey |= (KEYC_META|KEYC_IMPLIED_META); /* Alt */ | 			nkey |= (KEYC_META|KEYC_IMPLIED_META); /* Alt */ | ||||||
| @@ -984,34 +1009,15 @@ tty_keys_extended_key(struct tty *tty, const char *buf, size_t len, | |||||||
| 			nkey |= (KEYC_META|KEYC_IMPLIED_META); /* Meta */ | 			nkey |= (KEYC_META|KEYC_IMPLIED_META); /* Meta */ | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	/* | 	/* Convert S-Tab into Backtab. */ | ||||||
| 	 * Don't allow both KEYC_CTRL and as an implied modifier. Also convert | 	if ((nkey & KEYC_MASK_KEY) == '\011' && (nkey & KEYC_SHIFT)) | ||||||
| 	 * C-X into C-x and so on. | 		nkey = KEYC_BTAB | (nkey & ~KEYC_MASK_KEY & ~KEYC_SHIFT); | ||||||
| 	 */ |  | ||||||
| 	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) { | 	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, nkey, key_string_lookup_key(nkey, 1)); | 		    (int)*size, buf, nkey, key_string_lookup_key(nkey, 1)); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	*key = nkey; | 	*key = nkey; | ||||||
| 	return (0); | 	return (0); | ||||||
| } | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Thomas Adam
					Thomas Adam