mirror of
				https://github.com/tmux/tmux.git
				synced 2025-11-03 16:46:18 +00:00 
			
		
		
		
	Don't set key KEYC_NONE on xterm_keys_find match()
When calling xterm_keys_find(); if we get a complete match, don't set the key to unknown before calling the action to complete the binding; otherwise non-prefixed bindings will not work. From Thomas Adam
This commit is contained in:
		
							
								
								
									
										148
									
								
								tty-keys.c
									
									
									
									
									
								
							
							
						
						
									
										148
									
								
								tty-keys.c
									
									
									
									
									
								
							@@ -353,17 +353,19 @@ tty_keys_build(struct tty *tty)
 | 
				
			|||||||
		tdkr = &tty_default_raw_keys[i];
 | 
							tdkr = &tty_default_raw_keys[i];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		s = tdkr->string;
 | 
							s = tdkr->string;
 | 
				
			||||||
		if (s[0] == '\033' && s[1] != '\0')
 | 
							if (*s != '\0')
 | 
				
			||||||
			tty_keys_add(tty, s + 1, tdkr->key);
 | 
								tty_keys_add(tty, s, tdkr->key);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	for (i = 0; i < nitems(tty_default_code_keys); i++) {
 | 
						for (i = 0; i < nitems(tty_default_code_keys); i++) {
 | 
				
			||||||
		tdkc = &tty_default_code_keys[i];
 | 
							tdkc = &tty_default_code_keys[i];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		s = tty_term_string(tty->term, tdkc->code);
 | 
							s = tty_term_string(tty->term, tdkc->code);
 | 
				
			||||||
		if (s[0] == '\033' || s[1] == '\0')
 | 
							if (*s != '\0')
 | 
				
			||||||
			tty_keys_add(tty, s + 1, tdkc->key);
 | 
								tty_keys_add(tty, s, tdkc->key);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						tty_keys_add(tty, "abc", 'x');
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Free the entire key tree. */
 | 
					/* Free the entire key tree. */
 | 
				
			||||||
@@ -439,34 +441,18 @@ tty_keys_next(struct tty *tty)
 | 
				
			|||||||
	cc_t		 bspace;
 | 
						cc_t		 bspace;
 | 
				
			||||||
	int		 key, delay;
 | 
						int		 key, delay;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Get key buffer. */
 | 
				
			||||||
	buf = EVBUFFER_DATA(tty->event->input);
 | 
						buf = EVBUFFER_DATA(tty->event->input);
 | 
				
			||||||
	len = EVBUFFER_LENGTH(tty->event->input);
 | 
						len = EVBUFFER_LENGTH(tty->event->input);
 | 
				
			||||||
	if (len == 0)
 | 
						if (len == 0)
 | 
				
			||||||
		return (0);
 | 
							return (0);
 | 
				
			||||||
	log_debug("keys are %zu (%.*s)", len, (int) len, buf);
 | 
						log_debug("keys are %zu (%.*s)", len, (int) len, buf);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* If a normal key, return it. */
 | 
					 | 
				
			||||||
	if (*buf != '\033') {
 | 
					 | 
				
			||||||
		key = (u_char) *buf;
 | 
					 | 
				
			||||||
		evbuffer_drain(tty->event->input, 1);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		/*
 | 
					 | 
				
			||||||
		 * Check for backspace key using termios VERASE - the terminfo
 | 
					 | 
				
			||||||
		 * kbs entry is extremely unreliable, so cannot be safely
 | 
					 | 
				
			||||||
		 * used. termios should have a better idea.
 | 
					 | 
				
			||||||
		 */
 | 
					 | 
				
			||||||
		bspace = tty->tio.c_cc[VERASE];
 | 
					 | 
				
			||||||
		if (bspace != _POSIX_VDISABLE && key == bspace)
 | 
					 | 
				
			||||||
			key = KEYC_BSPACE;
 | 
					 | 
				
			||||||
		goto handle_key;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* Is this device attributes response? */
 | 
						/* Is this device attributes response? */
 | 
				
			||||||
	switch (tty_keys_device(tty, buf, len, &size)) {
 | 
						switch (tty_keys_device(tty, buf, len, &size)) {
 | 
				
			||||||
	case 0:		/* yes */
 | 
						case 0:		/* yes */
 | 
				
			||||||
		evbuffer_drain(tty->event->input, size);
 | 
					 | 
				
			||||||
		key = KEYC_NONE;
 | 
							key = KEYC_NONE;
 | 
				
			||||||
		goto handle_key;
 | 
							goto complete_key;
 | 
				
			||||||
	case -1:	/* no, or not valid */
 | 
						case -1:	/* no, or not valid */
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	case 1:		/* partial */
 | 
						case 1:		/* partial */
 | 
				
			||||||
@@ -476,9 +462,8 @@ tty_keys_next(struct tty *tty)
 | 
				
			|||||||
	/* Is this a mouse key press? */
 | 
						/* Is this a mouse key press? */
 | 
				
			||||||
	switch (tty_keys_mouse(tty, buf, len, &size)) {
 | 
						switch (tty_keys_mouse(tty, buf, len, &size)) {
 | 
				
			||||||
	case 0:		/* yes */
 | 
						case 0:		/* yes */
 | 
				
			||||||
		evbuffer_drain(tty->event->input, size);
 | 
					 | 
				
			||||||
		key = KEYC_MOUSE;
 | 
							key = KEYC_MOUSE;
 | 
				
			||||||
		goto handle_key;
 | 
							goto complete_key;
 | 
				
			||||||
	case -1:	/* no, or not valid */
 | 
						case -1:	/* no, or not valid */
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	case 1:		/* partial */
 | 
						case 1:		/* partial */
 | 
				
			||||||
@@ -488,8 +473,7 @@ tty_keys_next(struct tty *tty)
 | 
				
			|||||||
	/* Try to parse a key with an xterm-style modifier. */
 | 
						/* Try to parse a key with an xterm-style modifier. */
 | 
				
			||||||
	switch (xterm_keys_find(buf, len, &size, &key)) {
 | 
						switch (xterm_keys_find(buf, len, &size, &key)) {
 | 
				
			||||||
	case 0:		/* found */
 | 
						case 0:		/* found */
 | 
				
			||||||
		evbuffer_drain(tty->event->input, size);
 | 
							goto complete_key;
 | 
				
			||||||
		goto handle_key;
 | 
					 | 
				
			||||||
	case -1:	/* not found */
 | 
						case -1:	/* not found */
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	case 1:
 | 
						case 1:
 | 
				
			||||||
@@ -497,93 +481,90 @@ tty_keys_next(struct tty *tty)
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Look for matching key string and return if found. */
 | 
						/* Look for matching key string and return if found. */
 | 
				
			||||||
	tk = tty_keys_find(tty, buf + 1, len - 1, &size);
 | 
						tk = tty_keys_find(tty, buf, len, &size);
 | 
				
			||||||
	if (tk != NULL) {
 | 
						if (tk != NULL) {
 | 
				
			||||||
 | 
							if (tk->next != NULL)
 | 
				
			||||||
 | 
								goto partial_key;
 | 
				
			||||||
		key = tk->key;
 | 
							key = tk->key;
 | 
				
			||||||
		goto found_key;
 | 
							goto complete_key;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Skip the escape. */
 | 
						/* Is this a meta key? */
 | 
				
			||||||
	buf++;
 | 
						if (len >= 2 && buf[0] == '\033') {
 | 
				
			||||||
	len--;
 | 
							if (buf[1] != '\033') {
 | 
				
			||||||
 | 
								key = buf[1] | KEYC_ESCAPE;
 | 
				
			||||||
 | 
								size = 2;
 | 
				
			||||||
 | 
								goto complete_key;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Is there a normal key following? */
 | 
					 | 
				
			||||||
	if (len != 0 && *buf != '\033') {
 | 
					 | 
				
			||||||
		key = *buf | KEYC_ESCAPE;
 | 
					 | 
				
			||||||
		evbuffer_drain(tty->event->input, 2);
 | 
					 | 
				
			||||||
		goto handle_key;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* Or a key string? */
 | 
					 | 
				
			||||||
	if (len > 1) {
 | 
					 | 
				
			||||||
		tk = tty_keys_find(tty, buf + 1, len - 1, &size);
 | 
							tk = tty_keys_find(tty, buf + 1, len - 1, &size);
 | 
				
			||||||
		if (tk != NULL) {
 | 
							if (tk != NULL) {
 | 
				
			||||||
			key = tk->key | KEYC_ESCAPE;
 | 
					 | 
				
			||||||
			size++;	/* include escape */
 | 
								size++;	/* include escape */
 | 
				
			||||||
			goto found_key;
 | 
								if (tk->next != NULL)
 | 
				
			||||||
 | 
									goto partial_key;
 | 
				
			||||||
 | 
								key = tk->key;
 | 
				
			||||||
 | 
								if (key != KEYC_NONE)
 | 
				
			||||||
 | 
									key |= KEYC_ESCAPE;
 | 
				
			||||||
 | 
								goto complete_key;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Escape and then nothing useful - fall through. */
 | 
					first_key:
 | 
				
			||||||
 | 
						/* No key found, take first. */
 | 
				
			||||||
 | 
						key = (u_char) *buf;
 | 
				
			||||||
 | 
						size = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						 * Check for backspace key using termios VERASE - the terminfo
 | 
				
			||||||
 | 
						 * kbs entry is extremely unreliable, so cannot be safely
 | 
				
			||||||
 | 
						 * used. termios should have a better idea.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						bspace = tty->tio.c_cc[VERASE];
 | 
				
			||||||
 | 
						if (bspace != _POSIX_VDISABLE && key == bspace)
 | 
				
			||||||
 | 
							key = KEYC_BSPACE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						goto complete_key;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
partial_key:
 | 
					partial_key:
 | 
				
			||||||
	/*
 | 
						log_debug("partial key %.*s", (int) len, buf);
 | 
				
			||||||
	 * Escape but no key string. If have already seen an escape and the
 | 
					
 | 
				
			||||||
	 * timer has expired, give up waiting and send the escape.
 | 
						/* If timer is going, check for expiration. */
 | 
				
			||||||
	 */
 | 
						if (tty->flags & TTY_TIMER) {
 | 
				
			||||||
	if ((tty->flags & TTY_ESCAPE) &&
 | 
							if (evtimer_initialized(&tty->key_timer) &&
 | 
				
			||||||
	    evtimer_initialized(&tty->key_timer) &&
 | 
							    !evtimer_pending(&tty->key_timer, NULL))
 | 
				
			||||||
	    !evtimer_pending(&tty->key_timer, NULL)) {
 | 
								goto first_key;
 | 
				
			||||||
		evbuffer_drain(tty->event->input, 1);
 | 
							return (0);
 | 
				
			||||||
		key = '\033';
 | 
					 | 
				
			||||||
		goto handle_key;
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Fall through to start the timer. */
 | 
						/* Get the time period. */
 | 
				
			||||||
 | 
					 | 
				
			||||||
start_timer:
 | 
					 | 
				
			||||||
	/* If already waiting for timer, do nothing. */
 | 
					 | 
				
			||||||
	if (evtimer_initialized(&tty->key_timer) &&
 | 
					 | 
				
			||||||
	    evtimer_pending(&tty->key_timer, NULL))
 | 
					 | 
				
			||||||
		return (0);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* Start the timer and wait for expiry or more data. */
 | 
					 | 
				
			||||||
	delay = options_get_number(&global_options, "escape-time");
 | 
						delay = options_get_number(&global_options, "escape-time");
 | 
				
			||||||
	tv.tv_sec = delay / 1000;
 | 
						tv.tv_sec = delay / 1000;
 | 
				
			||||||
	tv.tv_usec = (delay % 1000) * 1000L;
 | 
						tv.tv_usec = (delay % 1000) * 1000L;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Start the timer. */
 | 
				
			||||||
	if (event_initialized(&tty->key_timer))
 | 
						if (event_initialized(&tty->key_timer))
 | 
				
			||||||
		evtimer_del(&tty->key_timer);
 | 
							evtimer_del(&tty->key_timer);
 | 
				
			||||||
	evtimer_set(&tty->key_timer, tty_keys_callback, tty);
 | 
						evtimer_set(&tty->key_timer, tty_keys_callback, tty);
 | 
				
			||||||
	evtimer_add(&tty->key_timer, &tv);
 | 
						evtimer_add(&tty->key_timer, &tv);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	tty->flags |= TTY_ESCAPE;
 | 
						tty->flags |= TTY_TIMER;
 | 
				
			||||||
	return (0);
 | 
						return (0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
found_key:
 | 
					complete_key:
 | 
				
			||||||
	if (tk->next != NULL) {
 | 
						log_debug("complete key %.*s %#x", (int) size, buf, key);
 | 
				
			||||||
		/* Partial key. Start the timer if not already expired. */
 | 
					 | 
				
			||||||
		if (!(tty->flags & TTY_ESCAPE))
 | 
					 | 
				
			||||||
			goto start_timer;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/* Otherwise, if no key, send the escape alone. */
 | 
						/* Remove data from buffer. */
 | 
				
			||||||
		if (tk->key == KEYC_NONE)
 | 
						evbuffer_drain(tty->event->input, size);
 | 
				
			||||||
			goto partial_key;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/* Or fall through to send the partial key found. */
 | 
						/* Remove key timer. */
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	evbuffer_drain(tty->event->input, size + 1);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	goto handle_key;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
handle_key:
 | 
					 | 
				
			||||||
	if (event_initialized(&tty->key_timer))
 | 
						if (event_initialized(&tty->key_timer))
 | 
				
			||||||
		evtimer_del(&tty->key_timer);
 | 
							evtimer_del(&tty->key_timer);
 | 
				
			||||||
 | 
						tty->flags &= ~TTY_TIMER;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Fire the key. */
 | 
				
			||||||
	if (key != KEYC_NONE)
 | 
						if (key != KEYC_NONE)
 | 
				
			||||||
		server_client_handle_key(tty->client, key);
 | 
							server_client_handle_key(tty->client, key);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	tty->flags &= ~TTY_ESCAPE;
 | 
					 | 
				
			||||||
	return (1);
 | 
						return (1);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -594,11 +575,10 @@ tty_keys_callback(unused int fd, unused short events, void *data)
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
	struct tty	*tty = data;
 | 
						struct tty	*tty = data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!(tty->flags & TTY_ESCAPE))
 | 
						if (tty->flags & TTY_TIMER) {
 | 
				
			||||||
		return;
 | 
							while (tty_keys_next(tty))
 | 
				
			||||||
 | 
								;
 | 
				
			||||||
	while (tty_keys_next(tty))
 | 
						}
 | 
				
			||||||
		;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user