mirror of
				https://github.com/tmux/tmux.git
				synced 2025-11-03 16:46:18 +00:00 
			
		
		
		
	Merge branch 'obsd-master'
This commit is contained in:
		
							
								
								
									
										9
									
								
								client.c
									
									
									
									
									
								
							
							
						
						
									
										9
									
								
								client.c
									
									
									
									
									
								
							@@ -261,8 +261,13 @@ client_main(int argc, char **argv, int flags)
 | 
				
			|||||||
	/* Initialize the client socket and start the server. */
 | 
						/* Initialize the client socket and start the server. */
 | 
				
			||||||
	fd = client_connect(socket_path, cmdflags & CMD_STARTSERVER);
 | 
						fd = client_connect(socket_path, cmdflags & CMD_STARTSERVER);
 | 
				
			||||||
	if (fd == -1) {
 | 
						if (fd == -1) {
 | 
				
			||||||
		fprintf(stderr, "failed to connect to server: %s\n",
 | 
							if (errno == ECONNREFUSED) {
 | 
				
			||||||
		    strerror(errno));
 | 
								fprintf(stderr, "no server running on %s\n",
 | 
				
			||||||
 | 
								    socket_path);
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								fprintf(stderr, "error connecting to %s (%s)\n",
 | 
				
			||||||
 | 
								    socket_path, strerror(errno));
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		return (1);
 | 
							return (1);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -33,8 +33,8 @@ enum cmd_retval	 cmd_bind_key_mode_table(struct cmd *, struct cmd_q *, int);
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
const struct cmd_entry cmd_bind_key_entry = {
 | 
					const struct cmd_entry cmd_bind_key_entry = {
 | 
				
			||||||
	"bind-key", "bind",
 | 
						"bind-key", "bind",
 | 
				
			||||||
	"cnrt:", 1, -1,
 | 
						"cnrt:T:", 1, -1,
 | 
				
			||||||
	"[-cnr] [-t mode-table] key command [arguments]",
 | 
						"[-cnr] [-t mode-table] [-T key-table] key command [arguments]",
 | 
				
			||||||
	0,
 | 
						0,
 | 
				
			||||||
	cmd_bind_key_exec
 | 
						cmd_bind_key_exec
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
@@ -46,6 +46,7 @@ cmd_bind_key_exec(struct cmd *self, struct cmd_q *cmdq)
 | 
				
			|||||||
	char		*cause;
 | 
						char		*cause;
 | 
				
			||||||
	struct cmd_list	*cmdlist;
 | 
						struct cmd_list	*cmdlist;
 | 
				
			||||||
	int		 key;
 | 
						int		 key;
 | 
				
			||||||
 | 
						const char	*tablename;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (args_has(args, 't')) {
 | 
						if (args_has(args, 't')) {
 | 
				
			||||||
		if (args->argc != 2 && args->argc != 3) {
 | 
							if (args->argc != 2 && args->argc != 3) {
 | 
				
			||||||
@@ -68,6 +69,13 @@ cmd_bind_key_exec(struct cmd *self, struct cmd_q *cmdq)
 | 
				
			|||||||
	if (args_has(args, 't'))
 | 
						if (args_has(args, 't'))
 | 
				
			||||||
		return (cmd_bind_key_mode_table(self, cmdq, key));
 | 
							return (cmd_bind_key_mode_table(self, cmdq, key));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (args_has(args, 'T'))
 | 
				
			||||||
 | 
							tablename = args_get(args, 'T');
 | 
				
			||||||
 | 
						else if (args_has(args, 'n'))
 | 
				
			||||||
 | 
							tablename = "root";
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							tablename = "prefix";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	cmdlist = cmd_list_parse(args->argc - 1, args->argv + 1, NULL, 0,
 | 
						cmdlist = cmd_list_parse(args->argc - 1, args->argv + 1, NULL, 0,
 | 
				
			||||||
	    &cause);
 | 
						    &cause);
 | 
				
			||||||
	if (cmdlist == NULL) {
 | 
						if (cmdlist == NULL) {
 | 
				
			||||||
@@ -76,9 +84,7 @@ cmd_bind_key_exec(struct cmd *self, struct cmd_q *cmdq)
 | 
				
			|||||||
		return (CMD_RETURN_ERROR);
 | 
							return (CMD_RETURN_ERROR);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!args_has(args, 'n'))
 | 
						key_bindings_add(tablename, key, args_has(args, 'r'), cmdlist);
 | 
				
			||||||
	    key |= KEYC_PREFIX;
 | 
					 | 
				
			||||||
	key_bindings_add(key, args_has(args, 'r'), cmdlist);
 | 
					 | 
				
			||||||
	return (CMD_RETURN_NORMAL);
 | 
						return (CMD_RETURN_NORMAL);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -68,8 +68,11 @@ cmd_copy_mode_exec(struct cmd *self, struct cmd_q *cmdq)
 | 
				
			|||||||
			return (CMD_RETURN_NORMAL);
 | 
								return (CMD_RETURN_NORMAL);
 | 
				
			||||||
		window_copy_init_from_pane(wp);
 | 
							window_copy_init_from_pane(wp);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if (args_has(args, 'M'))
 | 
						if (args_has(args, 'M')) {
 | 
				
			||||||
 | 
							if (wp->mode != NULL && wp->mode != &window_copy_mode)
 | 
				
			||||||
 | 
								return (CMD_RETURN_NORMAL);
 | 
				
			||||||
		window_copy_start_drag(c, &cmdq->item->mouse);
 | 
							window_copy_start_drag(c, &cmdq->item->mouse);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	if (wp->mode == &window_copy_mode && args_has(self->args, 'u'))
 | 
						if (wp->mode == &window_copy_mode && args_has(self->args, 'u'))
 | 
				
			||||||
		window_copy_pageup(wp);
 | 
							window_copy_pageup(wp);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -46,9 +46,12 @@ const struct cmd_entry cmd_if_shell_entry = {
 | 
				
			|||||||
struct cmd_if_shell_data {
 | 
					struct cmd_if_shell_data {
 | 
				
			||||||
	char			*cmd_if;
 | 
						char			*cmd_if;
 | 
				
			||||||
	char			*cmd_else;
 | 
						char			*cmd_else;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct cmd_q		*cmdq;
 | 
						struct cmd_q		*cmdq;
 | 
				
			||||||
 | 
						struct mouse_event	 mouse;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	int			 bflag;
 | 
						int			 bflag;
 | 
				
			||||||
	int		 started;
 | 
						int			 references;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
enum cmd_retval
 | 
					enum cmd_retval
 | 
				
			||||||
@@ -95,23 +98,26 @@ cmd_if_shell_exec(struct cmd *self, struct cmd_q *cmdq)
 | 
				
			|||||||
			}
 | 
								}
 | 
				
			||||||
			return (CMD_RETURN_ERROR);
 | 
								return (CMD_RETURN_ERROR);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		cmdq_run(cmdq, cmdlist, NULL);
 | 
							cmdq_run(cmdq, cmdlist, &cmdq->item->mouse);
 | 
				
			||||||
		cmd_list_free(cmdlist);
 | 
							cmd_list_free(cmdlist);
 | 
				
			||||||
		return (CMD_RETURN_NORMAL);
 | 
							return (CMD_RETURN_NORMAL);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	cdata = xmalloc(sizeof *cdata);
 | 
						cdata = xmalloc(sizeof *cdata);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	cdata->cmd_if = xstrdup(args->argv[1]);
 | 
						cdata->cmd_if = xstrdup(args->argv[1]);
 | 
				
			||||||
	if (args->argc == 3)
 | 
						if (args->argc == 3)
 | 
				
			||||||
		cdata->cmd_else = xstrdup(args->argv[2]);
 | 
							cdata->cmd_else = xstrdup(args->argv[2]);
 | 
				
			||||||
	else
 | 
						else
 | 
				
			||||||
		cdata->cmd_else = NULL;
 | 
							cdata->cmd_else = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	cdata->bflag = args_has(args, 'b');
 | 
						cdata->bflag = args_has(args, 'b');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	cdata->started = 0;
 | 
					 | 
				
			||||||
	cdata->cmdq = cmdq;
 | 
						cdata->cmdq = cmdq;
 | 
				
			||||||
 | 
						memcpy(&cdata->mouse, &cmdq->item->mouse, sizeof cdata->mouse);
 | 
				
			||||||
	cmdq->references++;
 | 
						cmdq->references++;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						cdata->references = 1;
 | 
				
			||||||
	job_run(shellcmd, s, cmd_if_shell_callback, cmd_if_shell_free, cdata);
 | 
						job_run(shellcmd, s, cmd_if_shell_callback, cmd_if_shell_free, cdata);
 | 
				
			||||||
	free(shellcmd);
 | 
						free(shellcmd);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -146,13 +152,12 @@ cmd_if_shell_callback(struct job *job)
 | 
				
			|||||||
		return;
 | 
							return;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	cdata->started = 1;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	cmdq1 = cmdq_new(cmdq->client);
 | 
						cmdq1 = cmdq_new(cmdq->client);
 | 
				
			||||||
	cmdq1->emptyfn = cmd_if_shell_done;
 | 
						cmdq1->emptyfn = cmd_if_shell_done;
 | 
				
			||||||
	cmdq1->data = cdata;
 | 
						cmdq1->data = cdata;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	cmdq_run(cmdq1, cmdlist, NULL);
 | 
						cdata->references++;
 | 
				
			||||||
 | 
						cmdq_run(cmdq1, cmdlist, &cdata->mouse);
 | 
				
			||||||
	cmd_list_free(cmdlist);
 | 
						cmd_list_free(cmdlist);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -164,12 +169,14 @@ cmd_if_shell_done(struct cmd_q *cmdq1)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	if (cmdq1->client_exit >= 0)
 | 
						if (cmdq1->client_exit >= 0)
 | 
				
			||||||
		cmdq->client_exit = cmdq1->client_exit;
 | 
							cmdq->client_exit = cmdq1->client_exit;
 | 
				
			||||||
 | 
						cmdq_free(cmdq1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (--cdata->references != 0)
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!cmdq_free(cmdq) && !cdata->bflag)
 | 
						if (!cmdq_free(cmdq) && !cdata->bflag)
 | 
				
			||||||
		cmdq_continue(cmdq);
 | 
							cmdq_continue(cmdq);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	cmdq_free(cmdq1);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	free(cdata->cmd_else);
 | 
						free(cdata->cmd_else);
 | 
				
			||||||
	free(cdata->cmd_if);
 | 
						free(cdata->cmd_if);
 | 
				
			||||||
	free(cdata);
 | 
						free(cdata);
 | 
				
			||||||
@@ -181,7 +188,7 @@ cmd_if_shell_free(void *data)
 | 
				
			|||||||
	struct cmd_if_shell_data	*cdata = data;
 | 
						struct cmd_if_shell_data	*cdata = data;
 | 
				
			||||||
	struct cmd_q			*cmdq = cdata->cmdq;
 | 
						struct cmd_q			*cmdq = cdata->cmdq;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (cdata->started)
 | 
						if (--cdata->references != 0)
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!cmdq_free(cmdq) && !cdata->bflag)
 | 
						if (!cmdq_free(cmdq) && !cdata->bflag)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -33,8 +33,8 @@ enum cmd_retval	 cmd_list_keys_commands(struct cmd *, struct cmd_q *);
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
const struct cmd_entry cmd_list_keys_entry = {
 | 
					const struct cmd_entry cmd_list_keys_entry = {
 | 
				
			||||||
	"list-keys", "lsk",
 | 
						"list-keys", "lsk",
 | 
				
			||||||
	"t:", 0, 0,
 | 
						"t:T:", 0, 0,
 | 
				
			||||||
	"[-t key-table]",
 | 
						"[-t mode-table] [-T key-table]",
 | 
				
			||||||
	0,
 | 
						0,
 | 
				
			||||||
	cmd_list_keys_exec
 | 
						cmd_list_keys_exec
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
@@ -51,11 +51,12 @@ enum cmd_retval
 | 
				
			|||||||
cmd_list_keys_exec(struct cmd *self, struct cmd_q *cmdq)
 | 
					cmd_list_keys_exec(struct cmd *self, struct cmd_q *cmdq)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct args		*args = self->args;
 | 
						struct args		*args = self->args;
 | 
				
			||||||
 | 
						struct key_table	*table;
 | 
				
			||||||
	struct key_binding	*bd;
 | 
						struct key_binding	*bd;
 | 
				
			||||||
	const char		*key;
 | 
						const char		*key, *tablename, *r;
 | 
				
			||||||
	char			 tmp[BUFSIZ], flags[8];
 | 
						char			 tmp[BUFSIZ];
 | 
				
			||||||
	size_t			 used;
 | 
						size_t			 used;
 | 
				
			||||||
	int			 width, keywidth;
 | 
						int			 repeat, width, tablewidth, keywidth;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (self->entry == &cmd_list_commands_entry)
 | 
						if (self->entry == &cmd_list_commands_entry)
 | 
				
			||||||
		return (cmd_list_keys_commands(self, cmdq));
 | 
							return (cmd_list_keys_commands(self, cmdq));
 | 
				
			||||||
@@ -63,47 +64,58 @@ cmd_list_keys_exec(struct cmd *self, struct cmd_q *cmdq)
 | 
				
			|||||||
	if (args_has(args, 't'))
 | 
						if (args_has(args, 't'))
 | 
				
			||||||
		return (cmd_list_keys_table(self, cmdq));
 | 
							return (cmd_list_keys_table(self, cmdq));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	width = 0;
 | 
						tablename = args_get(args, 'T');
 | 
				
			||||||
 | 
						if (tablename != NULL && key_bindings_get_table(tablename, 0) == NULL) {
 | 
				
			||||||
	RB_FOREACH(bd, key_bindings, &key_bindings) {
 | 
							cmdq_error(cmdq, "table %s doesn't exist", tablename);
 | 
				
			||||||
		key = key_string_lookup_key(bd->key & ~KEYC_PREFIX);
 | 
							return (CMD_RETURN_ERROR);
 | 
				
			||||||
		if (key == NULL)
 | 
					 | 
				
			||||||
			continue;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		keywidth = strlen(key);
 | 
					 | 
				
			||||||
		if (!(bd->key & KEYC_PREFIX)) {
 | 
					 | 
				
			||||||
			if (bd->can_repeat)
 | 
					 | 
				
			||||||
				keywidth += 4;
 | 
					 | 
				
			||||||
			else
 | 
					 | 
				
			||||||
				keywidth += 3;
 | 
					 | 
				
			||||||
		} else if (bd->can_repeat)
 | 
					 | 
				
			||||||
			keywidth += 3;
 | 
					 | 
				
			||||||
		if (keywidth > width)
 | 
					 | 
				
			||||||
			width = keywidth;
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	RB_FOREACH(bd, key_bindings, &key_bindings) {
 | 
						repeat = 0;
 | 
				
			||||||
		key = key_string_lookup_key(bd->key & ~KEYC_PREFIX);
 | 
						tablewidth = keywidth = 0;
 | 
				
			||||||
 | 
						RB_FOREACH(table, key_tables, &key_tables) {
 | 
				
			||||||
 | 
							if (tablename != NULL && strcmp(table->name, tablename) != 0)
 | 
				
			||||||
 | 
								continue;
 | 
				
			||||||
 | 
							RB_FOREACH(bd, key_bindings, &table->key_bindings) {
 | 
				
			||||||
 | 
								key = key_string_lookup_key(bd->key);
 | 
				
			||||||
			if (key == NULL)
 | 
								if (key == NULL)
 | 
				
			||||||
				continue;
 | 
									continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		*flags = '\0';
 | 
					 | 
				
			||||||
		if (!(bd->key & KEYC_PREFIX)) {
 | 
					 | 
				
			||||||
			if (bd->can_repeat)
 | 
								if (bd->can_repeat)
 | 
				
			||||||
				xsnprintf(flags, sizeof flags, "-rn ");
 | 
									repeat = 1;
 | 
				
			||||||
			else
 | 
					 | 
				
			||||||
				xsnprintf(flags, sizeof flags, "-n ");
 | 
					 | 
				
			||||||
		} else if (bd->can_repeat)
 | 
					 | 
				
			||||||
			xsnprintf(flags, sizeof flags, "-r ");
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		used = xsnprintf(tmp, sizeof tmp, "%s%*s ",
 | 
								width = strlen(table->name);
 | 
				
			||||||
		    flags, (int) (width - strlen(flags)), key);
 | 
								if (width > tablewidth)
 | 
				
			||||||
		if (used >= sizeof tmp)
 | 
									tablewidth =width;
 | 
				
			||||||
 | 
								width = strlen(key);
 | 
				
			||||||
 | 
								if (width > keywidth)
 | 
				
			||||||
 | 
									keywidth = width;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						RB_FOREACH(table, key_tables, &key_tables) {
 | 
				
			||||||
 | 
							if (tablename != NULL && strcmp(table->name, tablename) != 0)
 | 
				
			||||||
 | 
								continue;
 | 
				
			||||||
 | 
							RB_FOREACH(bd, key_bindings, &table->key_bindings) {
 | 
				
			||||||
 | 
								key = key_string_lookup_key(bd->key);
 | 
				
			||||||
 | 
								if (key == NULL)
 | 
				
			||||||
				continue;
 | 
									continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		cmd_list_print(bd->cmdlist, tmp + used, (sizeof tmp) - used);
 | 
								if (!repeat)
 | 
				
			||||||
 | 
									r = "";
 | 
				
			||||||
 | 
								else if (bd->can_repeat)
 | 
				
			||||||
 | 
									r = "-r ";
 | 
				
			||||||
 | 
								else
 | 
				
			||||||
 | 
									r = "   ";
 | 
				
			||||||
 | 
								used = xsnprintf(tmp, sizeof tmp, "%s-T %-*s %-*s ", r,
 | 
				
			||||||
 | 
								    (int)tablewidth, table->name, (int)keywidth, key);
 | 
				
			||||||
 | 
								if (used < sizeof tmp) {
 | 
				
			||||||
 | 
									cmd_list_print(bd->cmdlist, tmp + used,
 | 
				
			||||||
 | 
									    (sizeof tmp) - used);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			cmdq_print(cmdq, "bind-key %s", tmp);
 | 
								cmdq_print(cmdq, "bind-key %s", tmp);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return (CMD_RETURN_NORMAL);
 | 
						return (CMD_RETURN_NORMAL);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -51,7 +51,7 @@ cmd_move_window_exec(struct cmd *self, struct cmd_q *cmdq)
 | 
				
			|||||||
	struct session	*src, *dst, *s;
 | 
						struct session	*src, *dst, *s;
 | 
				
			||||||
	struct winlink	*wl;
 | 
						struct winlink	*wl;
 | 
				
			||||||
	char		*cause;
 | 
						char		*cause;
 | 
				
			||||||
	int		 idx, kflag, dflag;
 | 
						int		 idx, kflag, dflag, sflag;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (args_has(args, 'r')) {
 | 
						if (args_has(args, 'r')) {
 | 
				
			||||||
		s = cmd_find_session(cmdq, args_get(args, 't'), 0);
 | 
							s = cmd_find_session(cmdq, args_get(args, 't'), 0);
 | 
				
			||||||
@@ -71,6 +71,7 @@ cmd_move_window_exec(struct cmd *self, struct cmd_q *cmdq)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	kflag = args_has(self->args, 'k');
 | 
						kflag = args_has(self->args, 'k');
 | 
				
			||||||
	dflag = args_has(self->args, 'd');
 | 
						dflag = args_has(self->args, 'd');
 | 
				
			||||||
 | 
						sflag = args_has(self->args, 's');
 | 
				
			||||||
	if (server_link_window(src, wl, dst, idx, kflag, !dflag,
 | 
						if (server_link_window(src, wl, dst, idx, kflag, !dflag,
 | 
				
			||||||
	    &cause) != 0) {
 | 
						    &cause) != 0) {
 | 
				
			||||||
		cmdq_error(cmdq, "can't link window: %s", cause);
 | 
							cmdq_error(cmdq, "can't link window: %s", cause);
 | 
				
			||||||
@@ -79,6 +80,15 @@ cmd_move_window_exec(struct cmd *self, struct cmd_q *cmdq)
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	if (self->entry == &cmd_move_window_entry)
 | 
						if (self->entry == &cmd_move_window_entry)
 | 
				
			||||||
		server_unlink_window(src, wl);
 | 
							server_unlink_window(src, wl);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						 * Renumber the winlinks in the src session only, the destination
 | 
				
			||||||
 | 
						 * session already has the correct winlink id to us, either
 | 
				
			||||||
 | 
						 * automatically or specified by -s.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						if (!sflag && options_get_number(&src->options, "renumber-windows"))
 | 
				
			||||||
 | 
							session_renumber_windows(src);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	recalculate_sizes();
 | 
						recalculate_sizes();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return (CMD_RETURN_NORMAL);
 | 
						return (CMD_RETURN_NORMAL);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -31,8 +31,8 @@ enum cmd_retval	 cmd_switch_client_exec(struct cmd *, struct cmd_q *);
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
const struct cmd_entry cmd_switch_client_entry = {
 | 
					const struct cmd_entry cmd_switch_client_entry = {
 | 
				
			||||||
	"switch-client", "switchc",
 | 
						"switch-client", "switchc",
 | 
				
			||||||
	"lc:npt:r", 0, 0,
 | 
						"lc:npt:rT:", 0, 0,
 | 
				
			||||||
	"[-lnpr] [-c target-client] [-t target-session]",
 | 
						"[-lnpr] [-c target-client] [-t target-session] [-T key-table]",
 | 
				
			||||||
	CMD_READONLY,
 | 
						CMD_READONLY,
 | 
				
			||||||
	cmd_switch_client_exec
 | 
						cmd_switch_client_exec
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
@@ -46,7 +46,8 @@ cmd_switch_client_exec(struct cmd *self, struct cmd_q *cmdq)
 | 
				
			|||||||
	struct winlink		*wl = NULL;
 | 
						struct winlink		*wl = NULL;
 | 
				
			||||||
	struct window 		*w = NULL;
 | 
						struct window 		*w = NULL;
 | 
				
			||||||
	struct window_pane	*wp = NULL;
 | 
						struct window_pane	*wp = NULL;
 | 
				
			||||||
	const char		*tflag;
 | 
						const char		*tflag, *tablename;
 | 
				
			||||||
 | 
						struct key_table	*table;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if ((c = cmd_find_client(cmdq, args_get(args, 'c'), 0)) == NULL)
 | 
						if ((c = cmd_find_client(cmdq, args_get(args, 'c'), 0)) == NULL)
 | 
				
			||||||
		return (CMD_RETURN_ERROR);
 | 
							return (CMD_RETURN_ERROR);
 | 
				
			||||||
@@ -58,6 +59,18 @@ cmd_switch_client_exec(struct cmd *self, struct cmd_q *cmdq)
 | 
				
			|||||||
			c->flags |= CLIENT_READONLY;
 | 
								c->flags |= CLIENT_READONLY;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						tablename = args_get(args, 'T');
 | 
				
			||||||
 | 
						if (tablename != NULL) {
 | 
				
			||||||
 | 
							table = key_bindings_get_table(tablename, 0);
 | 
				
			||||||
 | 
							if (table == NULL) {
 | 
				
			||||||
 | 
								cmdq_error(cmdq, "table %s doesn't exist", tablename);
 | 
				
			||||||
 | 
								return (CMD_RETURN_ERROR);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							table->references++;
 | 
				
			||||||
 | 
							key_bindings_unref_table(c->keytable);
 | 
				
			||||||
 | 
							c->keytable = table;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	tflag = args_get(args, 't');
 | 
						tflag = args_get(args, 't');
 | 
				
			||||||
	if (args_has(args, 'n')) {
 | 
						if (args_has(args, 'n')) {
 | 
				
			||||||
		if ((s = session_next_session(c->session)) == NULL) {
 | 
							if ((s = session_next_session(c->session)) == NULL) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -31,8 +31,8 @@ enum cmd_retval	 cmd_unbind_key_mode_table(struct cmd *, struct cmd_q *, int);
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
const struct cmd_entry cmd_unbind_key_entry = {
 | 
					const struct cmd_entry cmd_unbind_key_entry = {
 | 
				
			||||||
	"unbind-key", "unbind",
 | 
						"unbind-key", "unbind",
 | 
				
			||||||
	"acnt:", 0, 1,
 | 
						"acnt:T:", 0, 1,
 | 
				
			||||||
	"[-acn] [-t mode-table] key",
 | 
						"[-acn] [-t mode-table] [-T key-table] key",
 | 
				
			||||||
	0,
 | 
						0,
 | 
				
			||||||
	cmd_unbind_key_exec
 | 
						cmd_unbind_key_exec
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
@@ -41,8 +41,8 @@ enum cmd_retval
 | 
				
			|||||||
cmd_unbind_key_exec(struct cmd *self, struct cmd_q *cmdq)
 | 
					cmd_unbind_key_exec(struct cmd *self, struct cmd_q *cmdq)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct args	*args = self->args;
 | 
						struct args	*args = self->args;
 | 
				
			||||||
	struct key_binding	*bd;
 | 
					 | 
				
			||||||
	int		 key;
 | 
						int		 key;
 | 
				
			||||||
 | 
						const char	*tablename;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!args_has(args, 'a')) {
 | 
						if (!args_has(args, 'a')) {
 | 
				
			||||||
		if (args->argc != 1) {
 | 
							if (args->argc != 1) {
 | 
				
			||||||
@@ -66,16 +66,31 @@ cmd_unbind_key_exec(struct cmd *self, struct cmd_q *cmdq)
 | 
				
			|||||||
		return (cmd_unbind_key_mode_table(self, cmdq, key));
 | 
							return (cmd_unbind_key_mode_table(self, cmdq, key));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (key == KEYC_NONE) {
 | 
						if (key == KEYC_NONE) {
 | 
				
			||||||
		while (!RB_EMPTY(&key_bindings)) {
 | 
							tablename = args_get(args, 'T');
 | 
				
			||||||
			bd = RB_ROOT(&key_bindings);
 | 
							if (tablename == NULL) {
 | 
				
			||||||
			key_bindings_remove(bd->key);
 | 
								key_bindings_remove_table("root");
 | 
				
			||||||
 | 
								key_bindings_remove_table("prefix");
 | 
				
			||||||
 | 
								return (CMD_RETURN_NORMAL);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							if (key_bindings_get_table(tablename, 0) == NULL) {
 | 
				
			||||||
 | 
								cmdq_error(cmdq, "table %s doesn't exist", tablename);
 | 
				
			||||||
 | 
								return (CMD_RETURN_ERROR);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							key_bindings_remove_table(tablename);
 | 
				
			||||||
		return (CMD_RETURN_NORMAL);
 | 
							return (CMD_RETURN_NORMAL);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!args_has(args, 'n'))
 | 
						if (args_has(args, 'T')) {
 | 
				
			||||||
		key |= KEYC_PREFIX;
 | 
							tablename = args_get(args, 'T');
 | 
				
			||||||
	key_bindings_remove(key);
 | 
							if (key_bindings_get_table(tablename, 0) == NULL) {
 | 
				
			||||||
 | 
								cmdq_error(cmdq, "table %s doesn't exist", tablename);
 | 
				
			||||||
 | 
								return (CMD_RETURN_ERROR);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						} else if (args_has(args, 'n'))
 | 
				
			||||||
 | 
							tablename = "root";
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							tablename = "prefix";
 | 
				
			||||||
 | 
						key_bindings_remove(tablename, key);
 | 
				
			||||||
	return (CMD_RETURN_NORMAL);
 | 
						return (CMD_RETURN_NORMAL);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										8
									
								
								cmd.c
									
									
									
									
									
								
							
							
						
						
									
										8
									
								
								cmd.c
									
									
									
									
									
								
							@@ -780,15 +780,15 @@ cmd_lookup_index(struct session *s, const char *name, int *ambiguous)
 | 
				
			|||||||
	const char	*errstr;
 | 
						const char	*errstr;
 | 
				
			||||||
	u_int		 idx;
 | 
						u_int		 idx;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						idx = strtonum(name, 0, INT_MAX, &errstr);
 | 
				
			||||||
 | 
						if (errstr == NULL)
 | 
				
			||||||
 | 
							return (idx);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if ((wl = cmd_lookup_window(s, name, ambiguous)) != NULL)
 | 
						if ((wl = cmd_lookup_window(s, name, ambiguous)) != NULL)
 | 
				
			||||||
		return (wl->idx);
 | 
							return (wl->idx);
 | 
				
			||||||
	if (*ambiguous)
 | 
						if (*ambiguous)
 | 
				
			||||||
		return (-1);
 | 
							return (-1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	idx = strtonum(name, 0, INT_MAX, &errstr);
 | 
					 | 
				
			||||||
	if (errstr == NULL)
 | 
					 | 
				
			||||||
		return (idx);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return (-1);
 | 
						return (-1);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										13
									
								
								format.c
									
									
									
									
									
								
							
							
						
						
									
										13
									
								
								format.c
									
									
									
									
									
								
							@@ -546,7 +546,11 @@ format_defaults_client(struct format_tree *ft, struct client *c)
 | 
				
			|||||||
	format_add(ft, "client_activity", "%lld", (long long) t);
 | 
						format_add(ft, "client_activity", "%lld", (long long) t);
 | 
				
			||||||
	format_add(ft, "client_activity_string", "%s", format_time_string(t));
 | 
						format_add(ft, "client_activity_string", "%s", format_time_string(t));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	format_add(ft, "client_prefix", "%d", !!(c->flags & CLIENT_PREFIX));
 | 
						if (strcmp(c->keytable->name, "root") == 0)
 | 
				
			||||||
 | 
							format_add(ft, "client_prefix", "%d", 0);
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							format_add(ft, "client_prefix", "%d", 1);
 | 
				
			||||||
 | 
						format_add(ft, "client_key_table", "%s", c->keytable->name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (c->tty.flags & TTY_UTF8)
 | 
						if (c->tty.flags & TTY_UTF8)
 | 
				
			||||||
		format_add(ft, "client_utf8", "%d", 1);
 | 
							format_add(ft, "client_utf8", "%d", 1);
 | 
				
			||||||
@@ -574,7 +578,10 @@ format_defaults_window(struct format_tree *ft, struct window *w)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	ft->w = w;
 | 
						ft->w = w;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	layout = layout_dump(w);
 | 
						if (w->saved_layout_root != NULL)
 | 
				
			||||||
 | 
							layout = layout_dump(w->saved_layout_root);
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							layout = layout_dump(w->layout_root);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	format_add(ft, "window_id", "@%u", w->id);
 | 
						format_add(ft, "window_id", "@%u", w->id);
 | 
				
			||||||
	format_add(ft, "window_name", "%s", w->name);
 | 
						format_add(ft, "window_name", "%s", w->name);
 | 
				
			||||||
@@ -728,6 +735,8 @@ format_defaults_pane(struct format_tree *ft, struct window_pane *wp)
 | 
				
			|||||||
	format_add(ft, "wrap_flag", "%d",
 | 
						format_add(ft, "wrap_flag", "%d",
 | 
				
			||||||
	    !!(wp->base.mode & MODE_WRAP));
 | 
						    !!(wp->base.mode & MODE_WRAP));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						format_add(ft, "mouse_any_flag", "%d",
 | 
				
			||||||
 | 
						    !!(wp->base.mode & (MODE_MOUSE_STANDARD|MODE_MOUSE_BUTTON)));
 | 
				
			||||||
	format_add(ft, "mouse_standard_flag", "%d",
 | 
						format_add(ft, "mouse_standard_flag", "%d",
 | 
				
			||||||
	    !!(wp->base.mode & MODE_MOUSE_STANDARD));
 | 
						    !!(wp->base.mode & MODE_MOUSE_STANDARD));
 | 
				
			||||||
	format_add(ft, "mouse_button_flag", "%d",
 | 
						format_add(ft, "mouse_button_flag", "%d",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -250,5 +250,6 @@ input_key_mouse(struct window_pane *wp, struct mouse_event *m)
 | 
				
			|||||||
		buf[len++] = x + 33;
 | 
							buf[len++] = x + 33;
 | 
				
			||||||
		buf[len++] = y + 33;
 | 
							buf[len++] = y + 33;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						log_debug("writing mouse %.*s", (int)len, buf);
 | 
				
			||||||
	bufferevent_write(wp->event, buf, len);
 | 
						bufferevent_write(wp->event, buf, len);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										114
									
								
								key-bindings.c
									
									
									
									
									
								
							
							
						
						
									
										114
									
								
								key-bindings.c
									
									
									
									
									
								
							@@ -25,60 +25,120 @@
 | 
				
			|||||||
#include "tmux.h"
 | 
					#include "tmux.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
RB_GENERATE(key_bindings, key_binding, entry, key_bindings_cmp);
 | 
					RB_GENERATE(key_bindings, key_binding, entry, key_bindings_cmp);
 | 
				
			||||||
 | 
					RB_GENERATE(key_tables, key_table, entry, key_table_cmp);
 | 
				
			||||||
 | 
					struct key_tables key_tables = RB_INITIALIZER(&key_tables);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct key_bindings	key_bindings;
 | 
					int
 | 
				
			||||||
 | 
					key_table_cmp(struct key_table *e1, struct key_table *e2)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return (strcmp(e1->name, e2->name));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int
 | 
					int
 | 
				
			||||||
key_bindings_cmp(struct key_binding *bd1, struct key_binding *bd2)
 | 
					key_bindings_cmp(struct key_binding *bd1, struct key_binding *bd2)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int	key1, key2;
 | 
						return (bd1->key - bd2->key);
 | 
				
			||||||
 | 
					 | 
				
			||||||
	key1 = bd1->key & ~KEYC_PREFIX;
 | 
					 | 
				
			||||||
	key2 = bd2->key & ~KEYC_PREFIX;
 | 
					 | 
				
			||||||
	if (key1 != key2)
 | 
					 | 
				
			||||||
		return (key1 - key2);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (bd1->key & KEYC_PREFIX && !(bd2->key & KEYC_PREFIX))
 | 
					 | 
				
			||||||
		return (-1);
 | 
					 | 
				
			||||||
	if (bd2->key & KEYC_PREFIX && !(bd1->key & KEYC_PREFIX))
 | 
					 | 
				
			||||||
		return (1);
 | 
					 | 
				
			||||||
	return (0);
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct key_binding *
 | 
					struct key_table *
 | 
				
			||||||
key_bindings_lookup(int key)
 | 
					key_bindings_get_table(const char *name, int create)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct key_binding	bd;
 | 
						struct key_table	table_find, *table;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bd.key = key;
 | 
						table_find.name = name;
 | 
				
			||||||
	return (RB_FIND(key_bindings, &key_bindings, &bd));
 | 
						table = RB_FIND(key_tables, &key_tables, &table_find);
 | 
				
			||||||
 | 
						if (table != NULL || !create)
 | 
				
			||||||
 | 
							return (table);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						table = xmalloc(sizeof *table);
 | 
				
			||||||
 | 
						table->name = xstrdup(name);
 | 
				
			||||||
 | 
						RB_INIT(&table->key_bindings);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						table->references = 1; /* one reference in key_tables */
 | 
				
			||||||
 | 
						RB_INSERT(key_tables, &key_tables, table);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return (table);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
key_bindings_add(int key, int can_repeat, struct cmd_list *cmdlist)
 | 
					key_bindings_unref_table(struct key_table *table)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct key_binding	*bd;
 | 
						struct key_binding	*bd;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	key_bindings_remove(key);
 | 
						if (--table->references != 0)
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						while (!RB_EMPTY(&table->key_bindings)) {
 | 
				
			||||||
 | 
							bd = RB_ROOT(&table->key_bindings);
 | 
				
			||||||
 | 
							RB_REMOVE(key_bindings, &table->key_bindings, bd);
 | 
				
			||||||
 | 
							cmd_list_free(bd->cmdlist);
 | 
				
			||||||
 | 
							free(bd);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						free((void *)table->name);
 | 
				
			||||||
 | 
						free(table);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					key_bindings_add(const char *name, int key, int can_repeat,
 | 
				
			||||||
 | 
					    struct cmd_list *cmdlist)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct key_table	*table;
 | 
				
			||||||
 | 
						struct key_binding	 bd_find, *bd;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						table = key_bindings_get_table(name, 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bd_find.key = key;
 | 
				
			||||||
 | 
						bd = RB_FIND(key_bindings, &table->key_bindings, &bd_find);
 | 
				
			||||||
 | 
						if (bd != NULL) {
 | 
				
			||||||
 | 
							RB_REMOVE(key_bindings, &table->key_bindings, bd);
 | 
				
			||||||
 | 
							cmd_list_free(bd->cmdlist);
 | 
				
			||||||
 | 
							free(bd);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bd = xmalloc(sizeof *bd);
 | 
						bd = xmalloc(sizeof *bd);
 | 
				
			||||||
	bd->key = key;
 | 
						bd->key = key;
 | 
				
			||||||
	RB_INSERT(key_bindings, &key_bindings, bd);
 | 
						RB_INSERT(key_bindings, &table->key_bindings, bd);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bd->can_repeat = can_repeat;
 | 
						bd->can_repeat = can_repeat;
 | 
				
			||||||
	bd->cmdlist = cmdlist;
 | 
						bd->cmdlist = cmdlist;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
key_bindings_remove(int key)
 | 
					key_bindings_remove(const char *name, int key)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct key_binding	*bd;
 | 
						struct key_table	*table;
 | 
				
			||||||
 | 
						struct key_binding	 bd_find, *bd;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if ((bd = key_bindings_lookup(key)) == NULL)
 | 
						table = key_bindings_get_table(name, 0);
 | 
				
			||||||
 | 
						if (table == NULL)
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
	RB_REMOVE(key_bindings, &key_bindings, bd);
 | 
					
 | 
				
			||||||
 | 
						bd_find.key = key;
 | 
				
			||||||
 | 
						bd = RB_FIND(key_bindings, &table->key_bindings, &bd_find);
 | 
				
			||||||
 | 
						if (bd == NULL)
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						RB_REMOVE(key_bindings, &table->key_bindings, bd);
 | 
				
			||||||
	cmd_list_free(bd->cmdlist);
 | 
						cmd_list_free(bd->cmdlist);
 | 
				
			||||||
	free(bd);
 | 
						free(bd);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (RB_EMPTY(&table->key_bindings)) {
 | 
				
			||||||
 | 
							RB_REMOVE(key_tables, &key_tables, table);
 | 
				
			||||||
 | 
							key_bindings_unref_table(table);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					key_bindings_remove_table(const char *name)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct key_table	*table;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						table = key_bindings_get_table(name, 0);
 | 
				
			||||||
 | 
						if (table != NULL) {
 | 
				
			||||||
 | 
							RB_REMOVE(key_tables, &key_tables, table);
 | 
				
			||||||
 | 
							key_bindings_unref_table(table);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
@@ -161,7 +221,7 @@ key_bindings_init(void)
 | 
				
			|||||||
		"bind -n MouseDown1Pane select-pane -t=\\; send-keys -M",
 | 
							"bind -n MouseDown1Pane select-pane -t=\\; send-keys -M",
 | 
				
			||||||
		"bind -n MouseDrag1Border resize-pane -M",
 | 
							"bind -n MouseDrag1Border resize-pane -M",
 | 
				
			||||||
		"bind -n MouseDown1Status select-window -t=",
 | 
							"bind -n MouseDown1Status select-window -t=",
 | 
				
			||||||
		"bind -n MouseDrag1Pane copy-mode -M",
 | 
							"bind -n MouseDrag1Pane if -Ft= '#{mouse_any_flag}' 'if -Ft= \"#{pane_in_mode}\" \"copy-mode -M\" \"send-keys -M\"' 'copy-mode -M'",
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
	u_int		 i;
 | 
						u_int		 i;
 | 
				
			||||||
	struct cmd_list	*cmdlist;
 | 
						struct cmd_list	*cmdlist;
 | 
				
			||||||
@@ -169,8 +229,6 @@ key_bindings_init(void)
 | 
				
			|||||||
	int		 error;
 | 
						int		 error;
 | 
				
			||||||
	struct cmd_q	*cmdq;
 | 
						struct cmd_q	*cmdq;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	RB_INIT(&key_bindings);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	cmdq = cmdq_new(NULL);
 | 
						cmdq = cmdq_new(NULL);
 | 
				
			||||||
	for (i = 0; i < nitems(defaults); i++) {
 | 
						for (i = 0; i < nitems(defaults); i++) {
 | 
				
			||||||
		error = cmd_string_parse(defaults[i], &cmdlist,
 | 
							error = cmd_string_parse(defaults[i], &cmdlist,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -55,12 +55,12 @@ layout_checksum(const char *layout)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
/* Dump layout as a string. */
 | 
					/* Dump layout as a string. */
 | 
				
			||||||
char *
 | 
					char *
 | 
				
			||||||
layout_dump(struct window *w)
 | 
					layout_dump(struct layout_cell *root)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	char	layout[BUFSIZ], *out;
 | 
						char	layout[BUFSIZ], *out;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	*layout = '\0';
 | 
						*layout = '\0';
 | 
				
			||||||
	if (layout_append(w->layout_root, layout, sizeof layout) != 0)
 | 
						if (layout_append(root, layout, sizeof layout) != 0)
 | 
				
			||||||
		return (NULL);
 | 
							return (NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	xasprintf(&out, "%04x,%s", layout_checksum(layout), layout);
 | 
						xasprintf(&out, "%04x,%s", layout_checksum(layout), layout);
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										148
									
								
								server-client.c
									
									
									
									
									
								
							
							
						
						
									
										148
									
								
								server-client.c
									
									
									
									
									
								
							@@ -29,6 +29,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#include "tmux.h"
 | 
					#include "tmux.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void	server_client_key_table(struct client *, const char *);
 | 
				
			||||||
void	server_client_check_focus(struct window_pane *);
 | 
					void	server_client_check_focus(struct window_pane *);
 | 
				
			||||||
void	server_client_check_resize(struct window_pane *);
 | 
					void	server_client_check_resize(struct window_pane *);
 | 
				
			||||||
int	server_client_check_mouse(struct client *);
 | 
					int	server_client_check_mouse(struct client *);
 | 
				
			||||||
@@ -44,6 +45,15 @@ void	server_client_msg_command(struct client *, struct imsg *);
 | 
				
			|||||||
void	server_client_msg_identify(struct client *, struct imsg *);
 | 
					void	server_client_msg_identify(struct client *, struct imsg *);
 | 
				
			||||||
void	server_client_msg_shell(struct client *);
 | 
					void	server_client_msg_shell(struct client *);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Set client key table. */
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					server_client_key_table(struct client *c, const char *name)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						key_bindings_unref_table(c->keytable);
 | 
				
			||||||
 | 
						c->keytable = key_bindings_get_table(name, 1);
 | 
				
			||||||
 | 
						c->keytable->references++;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Create a new client. */
 | 
					/* Create a new client. */
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
server_client_create(int fd)
 | 
					server_client_create(int fd)
 | 
				
			||||||
@@ -92,6 +102,9 @@ server_client_create(int fd)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	c->flags |= CLIENT_FOCUSED;
 | 
						c->flags |= CLIENT_FOCUSED;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						c->keytable = key_bindings_get_table("root", 1);
 | 
				
			||||||
 | 
						c->keytable->references++;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	evtimer_set(&c->repeat_timer, server_client_repeat_timer, c);
 | 
						evtimer_set(&c->repeat_timer, server_client_repeat_timer, c);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
 | 
						for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
 | 
				
			||||||
@@ -163,6 +176,8 @@ server_client_lost(struct client *c)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	evtimer_del(&c->repeat_timer);
 | 
						evtimer_del(&c->repeat_timer);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						key_bindings_unref_table(c->keytable);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (event_initialized(&c->identify_timer))
 | 
						if (event_initialized(&c->identify_timer))
 | 
				
			||||||
		evtimer_del(&c->identify_timer);
 | 
							evtimer_del(&c->identify_timer);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -375,7 +390,7 @@ server_client_check_mouse(struct client *c)
 | 
				
			|||||||
		c->tty.mouse_drag_release = NULL;
 | 
							c->tty.mouse_drag_release = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		c->tty.mouse_drag_flag = 0;
 | 
							c->tty.mouse_drag_flag = 0;
 | 
				
			||||||
		return (KEYC_NONE);
 | 
							return (KEYC_MOUSE); /* not a key, but still may want to pass */
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Convert to a key binding. */
 | 
						/* Convert to a key binding. */
 | 
				
			||||||
@@ -526,16 +541,19 @@ void
 | 
				
			|||||||
server_client_handle_key(struct client *c, int key)
 | 
					server_client_handle_key(struct client *c, int key)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct mouse_event	*m = &c->tty.mouse;
 | 
						struct mouse_event	*m = &c->tty.mouse;
 | 
				
			||||||
	struct session		*s;
 | 
						struct session		*s = c->session;
 | 
				
			||||||
	struct window		*w;
 | 
						struct window		*w;
 | 
				
			||||||
	struct window_pane	*wp;
 | 
						struct window_pane	*wp;
 | 
				
			||||||
	struct timeval		 tv;
 | 
						struct timeval		 tv;
 | 
				
			||||||
	struct key_binding	*bd;
 | 
						struct key_table	*table = c->keytable;
 | 
				
			||||||
	int		      	 xtimeout, isprefix, ispaste;
 | 
						struct key_binding	 bd_find, *bd;
 | 
				
			||||||
 | 
						int			 xtimeout;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Check the client is good to accept input. */
 | 
						/* Check the client is good to accept input. */
 | 
				
			||||||
	if ((c->flags & (CLIENT_DEAD|CLIENT_SUSPENDED)) != 0)
 | 
						if (s == NULL || (c->flags & (CLIENT_DEAD|CLIENT_SUSPENDED)) != 0)
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
 | 
						w = s->curw->window;
 | 
				
			||||||
 | 
						wp = w->active;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* No session, do nothing. */
 | 
						/* No session, do nothing. */
 | 
				
			||||||
	if (c->session == NULL)
 | 
						if (c->session == NULL)
 | 
				
			||||||
@@ -551,7 +569,7 @@ server_client_handle_key(struct client *c, int key)
 | 
				
			|||||||
	    sizeof s->last_activity_time);
 | 
						    sizeof s->last_activity_time);
 | 
				
			||||||
	memcpy(&s->activity_time, &c->activity_time, sizeof s->activity_time);
 | 
						memcpy(&s->activity_time, &c->activity_time, sizeof s->activity_time);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Special case: number keys jump to pane in identify mode. */
 | 
						/* Number keys jump to pane in identify mode. */
 | 
				
			||||||
	if (c->flags & CLIENT_IDENTIFY && key >= '0' && key <= '9') {
 | 
						if (c->flags & CLIENT_IDENTIFY && key >= '0' && key <= '9') {
 | 
				
			||||||
		if (c->flags & CLIENT_READONLY)
 | 
							if (c->flags & CLIENT_READONLY)
 | 
				
			||||||
			return;
 | 
								return;
 | 
				
			||||||
@@ -592,74 +610,88 @@ server_client_handle_key(struct client *c, int key)
 | 
				
			|||||||
	} else
 | 
						} else
 | 
				
			||||||
		m->valid = 0;
 | 
							m->valid = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Is this a prefix key? */
 | 
						/* Treat everything as a regular key when pasting is detected. */
 | 
				
			||||||
	if (key == options_get_number(&s->options, "prefix"))
 | 
						if (server_client_assume_paste(s)) {
 | 
				
			||||||
		isprefix = 1;
 | 
					 | 
				
			||||||
	else if (key == options_get_number(&s->options, "prefix2"))
 | 
					 | 
				
			||||||
		isprefix = 1;
 | 
					 | 
				
			||||||
	else
 | 
					 | 
				
			||||||
		isprefix = 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* Treat prefix as a regular key when pasting is detected. */
 | 
					 | 
				
			||||||
	ispaste = server_client_assume_paste(s);
 | 
					 | 
				
			||||||
	if (ispaste)
 | 
					 | 
				
			||||||
		isprefix = 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* No previous prefix key. */
 | 
					 | 
				
			||||||
	if (!(c->flags & CLIENT_PREFIX)) {
 | 
					 | 
				
			||||||
		if (isprefix) {
 | 
					 | 
				
			||||||
			c->flags |= CLIENT_PREFIX;
 | 
					 | 
				
			||||||
			server_status_client(c);
 | 
					 | 
				
			||||||
			return;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		/* Try as a non-prefix key binding. */
 | 
					 | 
				
			||||||
		if (ispaste || (bd = key_bindings_lookup(key)) == NULL) {
 | 
					 | 
				
			||||||
		if (!(c->flags & CLIENT_READONLY))
 | 
							if (!(c->flags & CLIENT_READONLY))
 | 
				
			||||||
			window_pane_key(wp, c, s, key, m);
 | 
								window_pane_key(wp, c, s, key, m);
 | 
				
			||||||
		} else
 | 
					 | 
				
			||||||
			key_bindings_dispatch(bd, c, m);
 | 
					 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Prefix key already pressed. Reset prefix and lookup key. */
 | 
					retry:
 | 
				
			||||||
	c->flags &= ~CLIENT_PREFIX;
 | 
						/* Try to see if there is a key binding in the current table. */
 | 
				
			||||||
 | 
						bd_find.key = key;
 | 
				
			||||||
 | 
						bd = RB_FIND(key_bindings, &table->key_bindings, &bd_find);
 | 
				
			||||||
 | 
						if (bd != NULL) {
 | 
				
			||||||
 | 
							/*
 | 
				
			||||||
 | 
							 * Key was matched in this table. If currently repeating but a
 | 
				
			||||||
 | 
							 * non-repeating binding was found, stop repeating and try
 | 
				
			||||||
 | 
							 * again in the root table.
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							if ((c->flags & CLIENT_REPEAT) && !bd->can_repeat) {
 | 
				
			||||||
 | 
								server_client_key_table(c, "root");
 | 
				
			||||||
 | 
								c->flags &= ~CLIENT_REPEAT;
 | 
				
			||||||
			server_status_client(c);
 | 
								server_status_client(c);
 | 
				
			||||||
	if ((bd = key_bindings_lookup(key | KEYC_PREFIX)) == NULL) {
 | 
								goto retry;
 | 
				
			||||||
		/* If repeating, treat this as a key, else ignore. */
 | 
					 | 
				
			||||||
		if (c->flags & CLIENT_REPEAT) {
 | 
					 | 
				
			||||||
			c->flags &= ~CLIENT_REPEAT;
 | 
					 | 
				
			||||||
			if (isprefix)
 | 
					 | 
				
			||||||
				c->flags |= CLIENT_PREFIX;
 | 
					 | 
				
			||||||
			else if (!(c->flags & CLIENT_READONLY))
 | 
					 | 
				
			||||||
				window_pane_key(wp, c, s, key, m);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		return;
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* If already repeating, but this key can't repeat, skip it. */
 | 
							/*
 | 
				
			||||||
	if (c->flags & CLIENT_REPEAT && !bd->can_repeat) {
 | 
							 * Take a reference to this table to make sure the key binding
 | 
				
			||||||
		c->flags &= ~CLIENT_REPEAT;
 | 
							 * doesn't disappear.
 | 
				
			||||||
		if (isprefix)
 | 
							 */
 | 
				
			||||||
			c->flags |= CLIENT_PREFIX;
 | 
							table->references++;
 | 
				
			||||||
		else if (!(c->flags & CLIENT_READONLY))
 | 
					 | 
				
			||||||
			window_pane_key(wp, c, s, key, m);
 | 
					 | 
				
			||||||
		return;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* If this key can repeat, reset the repeat flags and timer. */
 | 
							/*
 | 
				
			||||||
 | 
							 * If this is a repeating key, start the timer. Otherwise reset
 | 
				
			||||||
 | 
							 * the client back to the root table.
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
		xtimeout = options_get_number(&s->options, "repeat-time");
 | 
							xtimeout = options_get_number(&s->options, "repeat-time");
 | 
				
			||||||
		if (xtimeout != 0 && bd->can_repeat) {
 | 
							if (xtimeout != 0 && bd->can_repeat) {
 | 
				
			||||||
		c->flags |= CLIENT_PREFIX|CLIENT_REPEAT;
 | 
								c->flags |= CLIENT_REPEAT;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			tv.tv_sec = xtimeout / 1000;
 | 
								tv.tv_sec = xtimeout / 1000;
 | 
				
			||||||
			tv.tv_usec = (xtimeout % 1000) * 1000L;
 | 
								tv.tv_usec = (xtimeout % 1000) * 1000L;
 | 
				
			||||||
			evtimer_del(&c->repeat_timer);
 | 
								evtimer_del(&c->repeat_timer);
 | 
				
			||||||
			evtimer_add(&c->repeat_timer, &tv);
 | 
								evtimer_add(&c->repeat_timer, &tv);
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								c->flags &= ~CLIENT_REPEAT;
 | 
				
			||||||
 | 
								server_client_key_table(c, "root");
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							server_status_client(c);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/* Dispatch the key binding. */
 | 
				
			||||||
 | 
							key_bindings_dispatch(bd, c, m);
 | 
				
			||||||
 | 
							key_bindings_unref_table(table);
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Dispatch the command. */
 | 
						/*
 | 
				
			||||||
	key_bindings_dispatch(bd, c, m);
 | 
						 * No match in this table. If repeating, switch the client back to the
 | 
				
			||||||
 | 
						 * root table and try again.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						if (c->flags & CLIENT_REPEAT) {
 | 
				
			||||||
 | 
							server_client_key_table(c, "root");
 | 
				
			||||||
 | 
							c->flags &= ~CLIENT_REPEAT;
 | 
				
			||||||
 | 
							server_status_client(c);
 | 
				
			||||||
 | 
							goto retry;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* If no match and we're not in the root table, that's it. */
 | 
				
			||||||
 | 
						if (strcmp(c->keytable->name, "root") != 0) {
 | 
				
			||||||
 | 
							server_client_key_table(c, "root");
 | 
				
			||||||
 | 
							server_status_client(c);
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						 * No match, but in the root table. Prefix switches to the prefix table
 | 
				
			||||||
 | 
						 * and everything else is passed through.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						if (key == options_get_number(&s->options, "prefix") ||
 | 
				
			||||||
 | 
						    key == options_get_number(&s->options, "prefix2")) {
 | 
				
			||||||
 | 
							server_client_key_table(c, "prefix");
 | 
				
			||||||
 | 
							server_status_client(c);
 | 
				
			||||||
 | 
						} else if (!(c->flags & CLIENT_READONLY))
 | 
				
			||||||
 | 
							window_pane_key(wp, c, s, key, m);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Client functions that need to happen every loop. */
 | 
					/* Client functions that need to happen every loop. */
 | 
				
			||||||
@@ -857,9 +889,9 @@ server_client_repeat_timer(unused int fd, unused short events, void *data)
 | 
				
			|||||||
	struct client	*c = data;
 | 
						struct client	*c = data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (c->flags & CLIENT_REPEAT) {
 | 
						if (c->flags & CLIENT_REPEAT) {
 | 
				
			||||||
		if (c->flags & CLIENT_PREFIX)
 | 
							server_client_key_table(c, "root");
 | 
				
			||||||
 | 
							c->flags &= ~CLIENT_REPEAT;
 | 
				
			||||||
		server_status_client(c);
 | 
							server_status_client(c);
 | 
				
			||||||
		c->flags &= ~(CLIENT_PREFIX|CLIENT_REPEAT);
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -351,7 +351,6 @@ server_unlink_window(struct session *s, struct winlink *wl)
 | 
				
			|||||||
		server_destroy_session_group(s);
 | 
							server_destroy_session_group(s);
 | 
				
			||||||
	else
 | 
						else
 | 
				
			||||||
		server_redraw_session_group(s);
 | 
							server_redraw_session_group(s);
 | 
				
			||||||
	session_renumber_windows(s);
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										20
									
								
								server.c
									
									
									
									
									
								
							
							
						
						
									
										20
									
								
								server.c
									
									
									
									
									
								
							@@ -78,24 +78,22 @@ server_create_socket(void)
 | 
				
			|||||||
	size = strlcpy(sa.sun_path, socket_path, sizeof sa.sun_path);
 | 
						size = strlcpy(sa.sun_path, socket_path, sizeof sa.sun_path);
 | 
				
			||||||
	if (size >= sizeof sa.sun_path) {
 | 
						if (size >= sizeof sa.sun_path) {
 | 
				
			||||||
		errno = ENAMETOOLONG;
 | 
							errno = ENAMETOOLONG;
 | 
				
			||||||
		fatal("socket failed");
 | 
							return (-1);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	unlink(sa.sun_path);
 | 
						unlink(sa.sun_path);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
 | 
						if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
 | 
				
			||||||
		fatal("socket failed");
 | 
							return (-1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	mask = umask(S_IXUSR|S_IXGRP|S_IRWXO);
 | 
						mask = umask(S_IXUSR|S_IXGRP|S_IRWXO);
 | 
				
			||||||
	if (bind(fd, (struct sockaddr *) &sa, SUN_LEN(&sa)) == -1)
 | 
						if (bind(fd, (struct sockaddr *) &sa, SUN_LEN(&sa)) == -1)
 | 
				
			||||||
		fatal("bind failed");
 | 
							return (-1);
 | 
				
			||||||
	umask(mask);
 | 
						umask(mask);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (listen(fd, 16) == -1)
 | 
						if (listen(fd, 16) == -1)
 | 
				
			||||||
		fatal("listen failed");
 | 
							return (-1);
 | 
				
			||||||
	setblocking(fd, 0);
 | 
						setblocking(fd, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	server_update_socket();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return (fd);
 | 
						return (fd);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -156,6 +154,9 @@ server_start(int lockfd, char *lockfile)
 | 
				
			|||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	server_fd = server_create_socket();
 | 
						server_fd = server_create_socket();
 | 
				
			||||||
 | 
						if (server_fd == -1)
 | 
				
			||||||
 | 
							fatal("couldn't create socket");
 | 
				
			||||||
 | 
						server_update_socket();
 | 
				
			||||||
	server_client_create(pair[1]);
 | 
						server_client_create(pair[1]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	unlink(lockfile);
 | 
						unlink(lockfile);
 | 
				
			||||||
@@ -388,6 +389,7 @@ server_add_accept(int timeout)
 | 
				
			|||||||
void
 | 
					void
 | 
				
			||||||
server_signal_callback(int sig, unused short events, unused void *data)
 | 
					server_signal_callback(int sig, unused short events, unused void *data)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						int	fd;
 | 
				
			||||||
	switch (sig) {
 | 
						switch (sig) {
 | 
				
			||||||
	case SIGTERM:
 | 
						case SIGTERM:
 | 
				
			||||||
		server_shutdown = 1;
 | 
							server_shutdown = 1;
 | 
				
			||||||
@@ -398,8 +400,12 @@ server_signal_callback(int sig, unused short events, unused void *data)
 | 
				
			|||||||
		break;
 | 
							break;
 | 
				
			||||||
	case SIGUSR1:
 | 
						case SIGUSR1:
 | 
				
			||||||
		event_del(&server_ev_accept);
 | 
							event_del(&server_ev_accept);
 | 
				
			||||||
 | 
							fd = server_create_socket();
 | 
				
			||||||
 | 
							if (fd != -1) {
 | 
				
			||||||
			close(server_fd);
 | 
								close(server_fd);
 | 
				
			||||||
		server_fd = server_create_socket();
 | 
								server_fd = fd;
 | 
				
			||||||
 | 
								server_update_socket();
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		server_add_accept(0);
 | 
							server_add_accept(0);
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										108
									
								
								tmux.1
									
									
									
									
									
								
							
							
						
						
									
										108
									
								
								tmux.1
									
									
									
									
									
								
							@@ -163,7 +163,8 @@ If the socket is accidentally removed, the
 | 
				
			|||||||
.Dv SIGUSR1
 | 
					.Dv SIGUSR1
 | 
				
			||||||
signal may be sent to the
 | 
					signal may be sent to the
 | 
				
			||||||
.Nm
 | 
					.Nm
 | 
				
			||||||
server process to recreate it.
 | 
					server process to recreate it (note that this will fail if any parent
 | 
				
			||||||
 | 
					directories are missing).
 | 
				
			||||||
.It Fl l
 | 
					.It Fl l
 | 
				
			||||||
Behave as a login shell.
 | 
					Behave as a login shell.
 | 
				
			||||||
This flag currently has no effect and is for compatibility with other shells
 | 
					This flag currently has no effect and is for compatibility with other shells
 | 
				
			||||||
@@ -842,6 +843,7 @@ Suspend a client by sending
 | 
				
			|||||||
.Op Fl lnpr
 | 
					.Op Fl lnpr
 | 
				
			||||||
.Op Fl c Ar target-client
 | 
					.Op Fl c Ar target-client
 | 
				
			||||||
.Op Fl t Ar target-session
 | 
					.Op Fl t Ar target-session
 | 
				
			||||||
 | 
					.Op Fl T Ar key-table
 | 
				
			||||||
.Xc
 | 
					.Xc
 | 
				
			||||||
.D1 (alias: Ic switchc )
 | 
					.D1 (alias: Ic switchc )
 | 
				
			||||||
Switch the current session for client
 | 
					Switch the current session for client
 | 
				
			||||||
@@ -859,6 +861,22 @@ respectively.
 | 
				
			|||||||
toggles whether a client is read-only (see the
 | 
					toggles whether a client is read-only (see the
 | 
				
			||||||
.Ic attach-session
 | 
					.Ic attach-session
 | 
				
			||||||
command).
 | 
					command).
 | 
				
			||||||
 | 
					.Pp
 | 
				
			||||||
 | 
					.Fl T
 | 
				
			||||||
 | 
					sets the client's key table; the next key from the client will be interpreted from
 | 
				
			||||||
 | 
					.Ar key-table .
 | 
				
			||||||
 | 
					This may be used to configure multiple prefix keys, or to bind commands to
 | 
				
			||||||
 | 
					sequences of keys.
 | 
				
			||||||
 | 
					For example, to make typing
 | 
				
			||||||
 | 
					.Ql abc
 | 
				
			||||||
 | 
					run the
 | 
				
			||||||
 | 
					.Ic list-keys
 | 
				
			||||||
 | 
					command:
 | 
				
			||||||
 | 
					.Bd -literal -offset indent
 | 
				
			||||||
 | 
					bind-key -Ttable2 c list-keys
 | 
				
			||||||
 | 
					bind-key -Ttable1 b switch-client -Ttable2
 | 
				
			||||||
 | 
					bind-key -Troot   a switch-client -Ttable1
 | 
				
			||||||
 | 
					.Ed
 | 
				
			||||||
.El
 | 
					.El
 | 
				
			||||||
.Sh WINDOWS AND PANES
 | 
					.Sh WINDOWS AND PANES
 | 
				
			||||||
A
 | 
					A
 | 
				
			||||||
@@ -1935,6 +1953,7 @@ Commands related to key bindings are as follows:
 | 
				
			|||||||
.It Xo Ic bind-key
 | 
					.It Xo Ic bind-key
 | 
				
			||||||
.Op Fl cnr
 | 
					.Op Fl cnr
 | 
				
			||||||
.Op Fl t Ar mode-table
 | 
					.Op Fl t Ar mode-table
 | 
				
			||||||
 | 
					.Op Fl T Ar key-table
 | 
				
			||||||
.Ar key Ar command Op Ar arguments
 | 
					.Ar key Ar command Op Ar arguments
 | 
				
			||||||
.Xc
 | 
					.Xc
 | 
				
			||||||
.D1 (alias: Ic bind )
 | 
					.D1 (alias: Ic bind )
 | 
				
			||||||
@@ -1942,16 +1961,40 @@ Bind key
 | 
				
			|||||||
.Ar key
 | 
					.Ar key
 | 
				
			||||||
to
 | 
					to
 | 
				
			||||||
.Ar command .
 | 
					.Ar command .
 | 
				
			||||||
By default (without
 | 
					Keys are bound in a key table.
 | 
				
			||||||
.Fl t )
 | 
					By default (without -T), the key is bound in
 | 
				
			||||||
the primary key bindings are modified (those normally activated with the prefix
 | 
					the
 | 
				
			||||||
key); in this case, if
 | 
					.Em prefix
 | 
				
			||||||
.Fl n
 | 
					key table.
 | 
				
			||||||
is specified, it is not necessary to use the prefix key,
 | 
					This table is used for keys pressed after the prefix key (for example,
 | 
				
			||||||
.Ar command
 | 
					by default
 | 
				
			||||||
 | 
					.Ql c
 | 
				
			||||||
is bound to
 | 
					is bound to
 | 
				
			||||||
.Ar key
 | 
					.Ic new-window
 | 
				
			||||||
alone.
 | 
					in the
 | 
				
			||||||
 | 
					.Em prefix
 | 
				
			||||||
 | 
					table, so
 | 
				
			||||||
 | 
					.Ql C-b c
 | 
				
			||||||
 | 
					creates a new window).
 | 
				
			||||||
 | 
					The
 | 
				
			||||||
 | 
					.Em root
 | 
				
			||||||
 | 
					table is used for keys pressed without the prefix key: binding
 | 
				
			||||||
 | 
					.Ql c
 | 
				
			||||||
 | 
					to
 | 
				
			||||||
 | 
					.Ic new-window
 | 
				
			||||||
 | 
					in the
 | 
				
			||||||
 | 
					.Em root
 | 
				
			||||||
 | 
					table (not recommended) means a plain
 | 
				
			||||||
 | 
					.Ql c
 | 
				
			||||||
 | 
					will create a new window.
 | 
				
			||||||
 | 
					.Fl n
 | 
				
			||||||
 | 
					is an alias
 | 
				
			||||||
 | 
					for
 | 
				
			||||||
 | 
					.Fl T Ar root .
 | 
				
			||||||
 | 
					Keys may also be bound in custom key tables and the
 | 
				
			||||||
 | 
					.Ic switch-client
 | 
				
			||||||
 | 
					.Fl T
 | 
				
			||||||
 | 
					command used to switch to them from a key binding.
 | 
				
			||||||
The
 | 
					The
 | 
				
			||||||
.Fl r
 | 
					.Fl r
 | 
				
			||||||
flag indicates this key may repeat, see the
 | 
					flag indicates this key may repeat, see the
 | 
				
			||||||
@@ -1967,21 +2010,33 @@ is bound in
 | 
				
			|||||||
the binding for command mode with
 | 
					the binding for command mode with
 | 
				
			||||||
.Fl c
 | 
					.Fl c
 | 
				
			||||||
or for normal mode without.
 | 
					or for normal mode without.
 | 
				
			||||||
 | 
					See the
 | 
				
			||||||
 | 
					.Sx WINDOWS AND PANES
 | 
				
			||||||
 | 
					section and the
 | 
				
			||||||
 | 
					.Ic list-keys
 | 
				
			||||||
 | 
					command for information on mode key bindings.
 | 
				
			||||||
 | 
					.Pp
 | 
				
			||||||
To view the default bindings and possible commands, see the
 | 
					To view the default bindings and possible commands, see the
 | 
				
			||||||
.Ic list-keys
 | 
					.Ic list-keys
 | 
				
			||||||
command.
 | 
					command.
 | 
				
			||||||
.It Ic list-keys Op Fl t Ar key-table
 | 
					.It Xo Ic list-keys
 | 
				
			||||||
 | 
					.Op Fl t Ar mode-table
 | 
				
			||||||
 | 
					.Op Fl T Ar key-table
 | 
				
			||||||
 | 
					.Xc
 | 
				
			||||||
.D1 (alias: Ic lsk )
 | 
					.D1 (alias: Ic lsk )
 | 
				
			||||||
List all key bindings.
 | 
					List all key bindings.
 | 
				
			||||||
Without
 | 
					Without
 | 
				
			||||||
.Fl t
 | 
					.Fl T
 | 
				
			||||||
the primary key bindings - those executed when preceded by the prefix key -
 | 
					all key tables are printed.
 | 
				
			||||||
are printed.
 | 
					With
 | 
				
			||||||
 | 
					.Fl T
 | 
				
			||||||
 | 
					only
 | 
				
			||||||
 | 
					.Ar key-table .
 | 
				
			||||||
.Pp
 | 
					.Pp
 | 
				
			||||||
With
 | 
					With
 | 
				
			||||||
.Fl t ,
 | 
					.Fl t ,
 | 
				
			||||||
the key bindings in
 | 
					the key bindings in
 | 
				
			||||||
.Ar key-table
 | 
					.Ar mode-table
 | 
				
			||||||
are listed; this may be one of:
 | 
					are listed; this may be one of:
 | 
				
			||||||
.Em vi-edit ,
 | 
					.Em vi-edit ,
 | 
				
			||||||
.Em emacs-edit ,
 | 
					.Em emacs-edit ,
 | 
				
			||||||
@@ -2026,31 +2081,22 @@ the secondary prefix key, to a window as if it was pressed.
 | 
				
			|||||||
.It Xo Ic unbind-key
 | 
					.It Xo Ic unbind-key
 | 
				
			||||||
.Op Fl acn
 | 
					.Op Fl acn
 | 
				
			||||||
.Op Fl t Ar mode-table
 | 
					.Op Fl t Ar mode-table
 | 
				
			||||||
 | 
					.Op Fl T Ar key-table
 | 
				
			||||||
.Ar key
 | 
					.Ar key
 | 
				
			||||||
.Xc
 | 
					.Xc
 | 
				
			||||||
.D1 (alias: Ic unbind )
 | 
					.D1 (alias: Ic unbind )
 | 
				
			||||||
Unbind the command bound to
 | 
					Unbind the command bound to
 | 
				
			||||||
.Ar key .
 | 
					.Ar key .
 | 
				
			||||||
Without
 | 
					.Fl c ,
 | 
				
			||||||
 | 
					.Fl n ,
 | 
				
			||||||
 | 
					.Fl T
 | 
				
			||||||
 | 
					and
 | 
				
			||||||
.Fl t
 | 
					.Fl t
 | 
				
			||||||
the primary key bindings are modified; in this case, if
 | 
					are the same as for
 | 
				
			||||||
.Fl n
 | 
					.Ic bind-key .
 | 
				
			||||||
is specified, the command bound to
 | 
					 | 
				
			||||||
.Ar key
 | 
					 | 
				
			||||||
without a prefix (if any) is removed.
 | 
					 | 
				
			||||||
If
 | 
					If
 | 
				
			||||||
.Fl a
 | 
					.Fl a
 | 
				
			||||||
is present, all key bindings are removed.
 | 
					is present, all key bindings are removed.
 | 
				
			||||||
.Pp
 | 
					 | 
				
			||||||
If
 | 
					 | 
				
			||||||
.Fl t
 | 
					 | 
				
			||||||
is present,
 | 
					 | 
				
			||||||
.Ar key
 | 
					 | 
				
			||||||
in
 | 
					 | 
				
			||||||
.Ar mode-table
 | 
					 | 
				
			||||||
is unbound: the binding for command mode with
 | 
					 | 
				
			||||||
.Fl c
 | 
					 | 
				
			||||||
or for normal mode without.
 | 
					 | 
				
			||||||
.El
 | 
					.El
 | 
				
			||||||
.Sh OPTIONS
 | 
					.Sh OPTIONS
 | 
				
			||||||
The appearance and behaviour of
 | 
					The appearance and behaviour of
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										33
									
								
								tmux.h
									
									
									
									
									
								
							
							
						
						
									
										33
									
								
								tmux.h
									
									
									
									
									
								
							@@ -87,10 +87,9 @@ extern char   **environ;
 | 
				
			|||||||
#define KEYC_ESCAPE 0x2000
 | 
					#define KEYC_ESCAPE 0x2000
 | 
				
			||||||
#define KEYC_CTRL 0x4000
 | 
					#define KEYC_CTRL 0x4000
 | 
				
			||||||
#define KEYC_SHIFT 0x8000
 | 
					#define KEYC_SHIFT 0x8000
 | 
				
			||||||
#define KEYC_PREFIX 0x10000
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Mask to obtain key w/o modifiers. */
 | 
					/* Mask to obtain key w/o modifiers. */
 | 
				
			||||||
#define KEYC_MASK_MOD (KEYC_ESCAPE|KEYC_CTRL|KEYC_SHIFT|KEYC_PREFIX)
 | 
					#define KEYC_MASK_MOD (KEYC_ESCAPE|KEYC_CTRL|KEYC_SHIFT)
 | 
				
			||||||
#define KEYC_MASK_KEY (~KEYC_MASK_MOD)
 | 
					#define KEYC_MASK_KEY (~KEYC_MASK_MOD)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Is this a mouse key? */
 | 
					/* Is this a mouse key? */
 | 
				
			||||||
@@ -1299,7 +1298,7 @@ struct client {
 | 
				
			|||||||
	struct screen	 status;
 | 
						struct screen	 status;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define CLIENT_TERMINAL 0x1
 | 
					#define CLIENT_TERMINAL 0x1
 | 
				
			||||||
#define CLIENT_PREFIX 0x2
 | 
					/* 0x2 unused */
 | 
				
			||||||
#define CLIENT_EXIT 0x4
 | 
					#define CLIENT_EXIT 0x4
 | 
				
			||||||
#define CLIENT_REDRAW 0x8
 | 
					#define CLIENT_REDRAW 0x8
 | 
				
			||||||
#define CLIENT_STATUS 0x10
 | 
					#define CLIENT_STATUS 0x10
 | 
				
			||||||
@@ -1318,6 +1317,7 @@ struct client {
 | 
				
			|||||||
#define CLIENT_256COLOURS 0x20000
 | 
					#define CLIENT_256COLOURS 0x20000
 | 
				
			||||||
#define CLIENT_IDENTIFIED 0x40000
 | 
					#define CLIENT_IDENTIFIED 0x40000
 | 
				
			||||||
	int		 flags;
 | 
						int		 flags;
 | 
				
			||||||
 | 
						struct key_table *keytable;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct event	 identify_timer;
 | 
						struct event	 identify_timer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -1438,7 +1438,7 @@ struct cmd_entry {
 | 
				
			|||||||
	enum cmd_retval	 (*exec)(struct cmd *, struct cmd_q *);
 | 
						enum cmd_retval	 (*exec)(struct cmd *, struct cmd_q *);
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Key binding. */
 | 
					/* Key binding and key table. */
 | 
				
			||||||
struct key_binding {
 | 
					struct key_binding {
 | 
				
			||||||
	int			 key;
 | 
						int			 key;
 | 
				
			||||||
	struct cmd_list		*cmdlist;
 | 
						struct cmd_list		*cmdlist;
 | 
				
			||||||
@@ -1447,6 +1447,15 @@ struct key_binding {
 | 
				
			|||||||
	RB_ENTRY(key_binding)	 entry;
 | 
						RB_ENTRY(key_binding)	 entry;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
RB_HEAD(key_bindings, key_binding);
 | 
					RB_HEAD(key_bindings, key_binding);
 | 
				
			||||||
 | 
					struct key_table {
 | 
				
			||||||
 | 
						const char		 *name;
 | 
				
			||||||
 | 
						struct key_bindings	 key_bindings;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						u_int			 references;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						RB_ENTRY(key_table)	 entry;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					RB_HEAD(key_tables, key_table);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Option table entries. The option table is the user-visible part of the
 | 
					 * Option table entries. The option table is the user-visible part of the
 | 
				
			||||||
@@ -1874,12 +1883,16 @@ void	cmd_wait_for_flush(void);
 | 
				
			|||||||
int	client_main(int, char **, int);
 | 
					int	client_main(int, char **, int);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* key-bindings.c */
 | 
					/* key-bindings.c */
 | 
				
			||||||
extern struct key_bindings key_bindings;
 | 
					 | 
				
			||||||
int	 key_bindings_cmp(struct key_binding *, struct key_binding *);
 | 
					 | 
				
			||||||
RB_PROTOTYPE(key_bindings, key_binding, entry, key_bindings_cmp);
 | 
					RB_PROTOTYPE(key_bindings, key_binding, entry, key_bindings_cmp);
 | 
				
			||||||
struct key_binding *key_bindings_lookup(int);
 | 
					RB_PROTOTYPE(key_tables, key_table, entry, key_table_cmp);
 | 
				
			||||||
void	 key_bindings_add(int, int, struct cmd_list *);
 | 
					extern struct key_tables key_tables;
 | 
				
			||||||
void	 key_bindings_remove(int);
 | 
					int	 key_table_cmp(struct key_table *, struct key_table *);
 | 
				
			||||||
 | 
					int	 key_bindings_cmp(struct key_binding *, struct key_binding *);
 | 
				
			||||||
 | 
					struct 	 key_table *key_bindings_get_table(const char *, int);
 | 
				
			||||||
 | 
					void 	 key_bindings_unref_table(struct key_table *);
 | 
				
			||||||
 | 
					void	 key_bindings_add(const char *, int, int, struct cmd_list *);
 | 
				
			||||||
 | 
					void	 key_bindings_remove(const char *, int);
 | 
				
			||||||
 | 
					void	 key_bindings_remove_table(const char *);
 | 
				
			||||||
void	 key_bindings_init(void);
 | 
					void	 key_bindings_init(void);
 | 
				
			||||||
void	 key_bindings_dispatch(struct key_binding *, struct client *,
 | 
					void	 key_bindings_dispatch(struct key_binding *, struct client *,
 | 
				
			||||||
	     struct mouse_event *);
 | 
						     struct mouse_event *);
 | 
				
			||||||
@@ -2210,7 +2223,7 @@ struct layout_cell *layout_split_pane(
 | 
				
			|||||||
void		 layout_close_pane(struct window_pane *);
 | 
					void		 layout_close_pane(struct window_pane *);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* layout-custom.c */
 | 
					/* layout-custom.c */
 | 
				
			||||||
char		*layout_dump(struct window *);
 | 
					char		*layout_dump(struct layout_cell *);
 | 
				
			||||||
int		 layout_parse(struct window *, const char *);
 | 
					int		 layout_parse(struct window *, const char *);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* layout-set.c */
 | 
					/* layout-set.c */
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										4
									
								
								utf8.c
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								utf8.c
									
									
									
									
									
								
							@@ -291,9 +291,9 @@ utf8_build(void)
 | 
				
			|||||||
		while (*ptr != NULL) {
 | 
							while (*ptr != NULL) {
 | 
				
			||||||
			node = *ptr;
 | 
								node = *ptr;
 | 
				
			||||||
			if (item->last < node->first)
 | 
								if (item->last < node->first)
 | 
				
			||||||
				ptr = &(node->left);
 | 
									ptr = &node->left;
 | 
				
			||||||
			else if (item->first > node->last)
 | 
								else if (item->first > node->last)
 | 
				
			||||||
				ptr = &(node->right);
 | 
									ptr = &node->right;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		*ptr = item;
 | 
							*ptr = item;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2217,13 +2217,11 @@ void
 | 
				
			|||||||
window_copy_start_drag(struct client *c, unused struct mouse_event *m)
 | 
					window_copy_start_drag(struct client *c, unused struct mouse_event *m)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct window_pane	*wp;
 | 
						struct window_pane	*wp;
 | 
				
			||||||
	struct window_copy_mode_data	*data;
 | 
					 | 
				
			||||||
	u_int			 x, y;
 | 
						u_int			 x, y;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	wp = cmd_mouse_pane(m, NULL, NULL);
 | 
						wp = cmd_mouse_pane(m, NULL, NULL);
 | 
				
			||||||
	if (wp->mode != &window_copy_mode)
 | 
						if (wp == NULL || wp->mode != &window_copy_mode)
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
	data = wp->modedata;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (cmd_mouse_at(wp, m, &x, &y, 1) != 0)
 | 
						if (cmd_mouse_at(wp, m, &x, &y, 1) != 0)
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
@@ -2244,7 +2242,7 @@ window_copy_drag_update(unused struct client *c, struct mouse_event *m)
 | 
				
			|||||||
	u_int				 x, y, old_cy;
 | 
						u_int				 x, y, old_cy;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	wp = cmd_mouse_pane(m, NULL, NULL);
 | 
						wp = cmd_mouse_pane(m, NULL, NULL);
 | 
				
			||||||
	if (wp->mode != &window_copy_mode)
 | 
						if (wp == NULL || wp->mode != &window_copy_mode)
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
	data = wp->modedata;
 | 
						data = wp->modedata;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -2261,12 +2259,10 @@ void
 | 
				
			|||||||
window_copy_drag_release(unused struct client *c, struct mouse_event *m)
 | 
					window_copy_drag_release(unused struct client *c, struct mouse_event *m)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct window_pane	*wp;
 | 
						struct window_pane	*wp;
 | 
				
			||||||
	struct window_copy_mode_data	*data;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	wp = cmd_mouse_pane(m, NULL, NULL);
 | 
						wp = cmd_mouse_pane(m, NULL, NULL);
 | 
				
			||||||
	if (wp->mode != &window_copy_mode)
 | 
						if (wp == NULL || wp->mode != &window_copy_mode)
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
	data = wp->modedata;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	window_copy_copy_selection(wp, NULL);
 | 
						window_copy_copy_selection(wp, NULL);
 | 
				
			||||||
	window_pane_reset_mode(wp);
 | 
						window_pane_reset_mode(wp);
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										1
									
								
								window.c
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								window.c
									
									
									
									
									
								
							@@ -518,6 +518,7 @@ window_unzoom(struct window *w)
 | 
				
			|||||||
	w->flags &= ~WINDOW_ZOOMED;
 | 
						w->flags &= ~WINDOW_ZOOMED;
 | 
				
			||||||
	layout_free(w);
 | 
						layout_free(w);
 | 
				
			||||||
	w->layout_root = w->saved_layout_root;
 | 
						w->layout_root = w->saved_layout_root;
 | 
				
			||||||
 | 
						w->saved_layout_root = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	TAILQ_FOREACH(wp, &w->panes, entry) {
 | 
						TAILQ_FOREACH(wp, &w->panes, entry) {
 | 
				
			||||||
		wp->layout_cell = wp->saved_layout_cell;
 | 
							wp->layout_cell = wp->saved_layout_cell;
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user