mirror of
				https://github.com/tmux/tmux.git
				synced 2025-10-26 12:27:15 +00:00 
			
		
		
		
	Merge branch 'master' into sixel
This commit is contained in:
		
							
								
								
									
										2
									
								
								.github/CONTRIBUTING.md
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.github/CONTRIBUTING.md
									
									
									
									
										vendored
									
									
								
							| @@ -29,7 +29,7 @@ uname -sp && tmux -V && echo $TERM | |||||||
|  |  | ||||||
| Also include: | Also include: | ||||||
|  |  | ||||||
| - Your platform (Linux, OS X, or whatever). | - Your platform (Linux, macOS, or whatever). | ||||||
|  |  | ||||||
| - A brief description of the problem with steps to reproduce. | - A brief description of the problem with steps to reproduce. | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										2
									
								
								.github/README.md
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.github/README.md
									
									
									
									
										vendored
									
									
								
							| @@ -4,7 +4,7 @@ tmux is a terminal multiplexer: it enables a number of terminals to be created, | |||||||
| accessed, and controlled from a single screen. tmux may be detached from a | accessed, and controlled from a single screen. tmux may be detached from a | ||||||
| screen and continue running in the background, then later reattached. | screen and continue running in the background, then later reattached. | ||||||
|  |  | ||||||
| This release runs on OpenBSD, FreeBSD, NetBSD, Linux, OS X and Solaris. | This release runs on OpenBSD, FreeBSD, NetBSD, Linux, macOS and Solaris. | ||||||
|  |  | ||||||
| ## Dependencies | ## Dependencies | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										2
									
								
								README
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								README
									
									
									
									
									
								
							| @@ -4,7 +4,7 @@ tmux is a terminal multiplexer: it enables a number of terminals to be created, | |||||||
| accessed, and controlled from a single screen. tmux may be detached from a | accessed, and controlled from a single screen. tmux may be detached from a | ||||||
| screen and continue running in the background, then later reattached. | screen and continue running in the background, then later reattached. | ||||||
|  |  | ||||||
| This release runs on OpenBSD, FreeBSD, NetBSD, Linux, OS X and Solaris. | This release runs on OpenBSD, FreeBSD, NetBSD, Linux, macOS and Solaris. | ||||||
|  |  | ||||||
| * Dependencies | * Dependencies | ||||||
|  |  | ||||||
|   | |||||||
| @@ -3,7 +3,7 @@ tmuxへようこそ! | |||||||
| tmuxはターミナルマルチプレクサーです。複数のターミナルを一つのスクリーン内に作成し、操作することができます。 | tmuxはターミナルマルチプレクサーです。複数のターミナルを一つのスクリーン内に作成し、操作することができます。 | ||||||
| バックグラウンドで処理を実行中に一度スクリーンから離れて後から復帰することも可能です。 | バックグラウンドで処理を実行中に一度スクリーンから離れて後から復帰することも可能です。 | ||||||
|  |  | ||||||
| OpenBSD、FreeBSD、NetBSD、Linux、OS X、Solarisで実行できます。 | OpenBSD、FreeBSD、NetBSD、Linux、macOS、Solarisで実行できます。 | ||||||
|  |  | ||||||
| tmuxはlibevent 2.x.に依存します。 下記からダウンロードしてください。 | tmuxはlibevent 2.x.に依存します。 下記からダウンロードしてください。 | ||||||
|  |  | ||||||
|   | |||||||
| @@ -108,6 +108,7 @@ args_value_as_string(struct args_value *value) | |||||||
| 	case ARGS_STRING: | 	case ARGS_STRING: | ||||||
| 		return (value->string); | 		return (value->string); | ||||||
| 	} | 	} | ||||||
|  | 	fatalx("unexpected argument type"); | ||||||
| } | } | ||||||
|  |  | ||||||
| /* Create an empty arguments set. */ | /* Create an empty arguments set. */ | ||||||
| @@ -753,6 +754,7 @@ args_make_commands(struct args_command_state *state, int argc, char **argv, | |||||||
| 	case CMD_PARSE_SUCCESS: | 	case CMD_PARSE_SUCCESS: | ||||||
| 		return (pr->cmdlist); | 		return (pr->cmdlist); | ||||||
| 	} | 	} | ||||||
|  | 	fatalx("invalid parse return state"); | ||||||
| } | } | ||||||
|  |  | ||||||
| /* Free commands state. */ | /* Free commands state. */ | ||||||
|   | |||||||
| @@ -72,7 +72,7 @@ cmd_confirm_before_exec(struct cmd *self, struct cmdq_item *item) | |||||||
| 	int				 wait = !args_has(args, 'b'); | 	int				 wait = !args_has(args, 'b'); | ||||||
|  |  | ||||||
| 	cdata = xcalloc(1, sizeof *cdata); | 	cdata = xcalloc(1, sizeof *cdata); | ||||||
| 	cdata->cmdlist = args_make_commands_now(self, item, 0, 0); | 	cdata->cmdlist = args_make_commands_now(self, item, 0, 1); | ||||||
| 	if (cdata->cmdlist == NULL) | 	if (cdata->cmdlist == NULL) | ||||||
| 		return (CMD_RETURN_ERROR); | 		return (CMD_RETURN_ERROR); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -52,10 +52,12 @@ const struct cmd_entry cmd_display_popup_entry = { | |||||||
| 	.name = "display-popup", | 	.name = "display-popup", | ||||||
| 	.alias = "popup", | 	.alias = "popup", | ||||||
|  |  | ||||||
| 	.args = { "BCc:d:Eh:t:w:x:y:", 0, -1, NULL }, | 	.args = { "Bb:Cc:d:e:Eh:s:S:t:T:w:x:y:", 0, -1, NULL }, | ||||||
| 	.usage = "[-BCE] [-c target-client] [-d start-directory] [-h height] " | 	.usage = "[-BCE] [-b border-lines] [-c target-client] " | ||||||
| 		 CMD_TARGET_PANE_USAGE " [-w width] " | 		 "[-d start-directory] [-e environment] [-h height] " | ||||||
| 		 "[-x position] [-y position] [shell-command]", | 		 "[-s style] [-S border-style] " CMD_TARGET_PANE_USAGE | ||||||
|  | 		 "[-T title] [-w width] [-x position] [-y position] " | ||||||
|  | 		 "[shell-command]", | ||||||
|  |  | ||||||
| 	.target = { 't', CMD_FIND_PANE, 0 }, | 	.target = { 't', CMD_FIND_PANE, 0 }, | ||||||
|  |  | ||||||
| @@ -353,9 +355,16 @@ cmd_display_popup_exec(struct cmd *self, struct cmdq_item *item) | |||||||
| 	struct client		*tc = cmdq_get_target_client(item); | 	struct client		*tc = cmdq_get_target_client(item); | ||||||
| 	struct tty		*tty = &tc->tty; | 	struct tty		*tty = &tc->tty; | ||||||
| 	const char		*value, *shell, *shellcmd = NULL; | 	const char		*value, *shell, *shellcmd = NULL; | ||||||
| 	char			*cwd, *cause, **argv = NULL; | 	const char		*style = args_get(args, 's'); | ||||||
|  | 	const char		*border_style = args_get(args, 'S'); | ||||||
|  | 	char			*cwd, *cause = NULL, **argv = NULL, *title; | ||||||
| 	int			 flags = 0, argc = 0; | 	int			 flags = 0, argc = 0; | ||||||
|  | 	enum box_lines		 lines = BOX_LINES_DEFAULT; | ||||||
| 	u_int			 px, py, w, h, count = args_count(args); | 	u_int			 px, py, w, h, count = args_count(args); | ||||||
|  | 	struct args_value	*av; | ||||||
|  | 	struct environ		*env = NULL; | ||||||
|  | 	struct options		*o = s->curw->window->options; | ||||||
|  | 	struct options_entry	*oe; | ||||||
|  |  | ||||||
| 	if (args_has(args, 'C')) { | 	if (args_has(args, 'C')) { | ||||||
| 		server_client_clear_overlay(tc); | 		server_client_clear_overlay(tc); | ||||||
| @@ -391,6 +400,20 @@ cmd_display_popup_exec(struct cmd *self, struct cmdq_item *item) | |||||||
| 	if (!cmd_display_menu_get_position(tc, item, args, &px, &py, w, h)) | 	if (!cmd_display_menu_get_position(tc, item, args, &px, &py, w, h)) | ||||||
| 		return (CMD_RETURN_NORMAL); | 		return (CMD_RETURN_NORMAL); | ||||||
|  |  | ||||||
|  | 	value = args_get(args, 'b'); | ||||||
|  | 	if (args_has(args, 'B')) | ||||||
|  | 		lines = BOX_LINES_NONE; | ||||||
|  | 	else if (value != NULL) { | ||||||
|  | 		oe = options_get(o, "popup-border-lines"); | ||||||
|  | 		lines = options_find_choice(options_table_entry(oe), value, | ||||||
|  | 		    &cause); | ||||||
|  | 		if (cause != NULL) { | ||||||
|  | 			cmdq_error(item, "popup-border-lines %s", cause); | ||||||
|  | 			free(cause); | ||||||
|  | 			return (CMD_RETURN_ERROR); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	value = args_get(args, 'd'); | 	value = args_get(args, 'd'); | ||||||
| 	if (value != NULL) | 	if (value != NULL) | ||||||
| 		cwd = format_single_from_target(item, value); | 		cwd = format_single_from_target(item, value); | ||||||
| @@ -409,17 +432,34 @@ cmd_display_popup_exec(struct cmd *self, struct cmdq_item *item) | |||||||
| 	} else | 	} else | ||||||
| 		args_to_vector(args, &argc, &argv); | 		args_to_vector(args, &argc, &argv); | ||||||
|  |  | ||||||
|  | 	if (args_has(args, 'e') >= 1) { | ||||||
|  | 		env = environ_create(); | ||||||
|  | 		av = args_first_value(args, 'e'); | ||||||
|  | 		while (av != NULL) { | ||||||
|  | 			environ_put(env, av->string, 0); | ||||||
|  | 			av = args_next_value(av); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if (args_has(args, 'T')) | ||||||
|  | 		title = format_single_from_target(item, args_get(args, 'T')); | ||||||
|  | 	else | ||||||
|  | 		title = xstrdup(""); | ||||||
| 	if (args_has(args, 'E') > 1) | 	if (args_has(args, 'E') > 1) | ||||||
| 		flags |= POPUP_CLOSEEXITZERO; | 		flags |= POPUP_CLOSEEXITZERO; | ||||||
| 	else if (args_has(args, 'E')) | 	else if (args_has(args, 'E')) | ||||||
| 		flags |= POPUP_CLOSEEXIT; | 		flags |= POPUP_CLOSEEXIT; | ||||||
| 	if (args_has(args, 'B')) | 	if (popup_display(flags, lines, item, px, py, w, h, env, shellcmd, argc, | ||||||
| 		flags |= POPUP_NOBORDER; | 	    argv, cwd, title, tc, s, style, border_style, NULL, NULL) != 0) { | ||||||
| 	if (popup_display(flags, item, px, py, w, h, shellcmd, argc, argv, cwd, |  | ||||||
| 	    tc, s, NULL, NULL) != 0) { |  | ||||||
| 		cmd_free_argv(argc, argv); | 		cmd_free_argv(argc, argv); | ||||||
|  | 		if (env != NULL) | ||||||
|  | 			environ_free(env); | ||||||
|  | 		free(title); | ||||||
| 		return (CMD_RETURN_NORMAL); | 		return (CMD_RETURN_NORMAL); | ||||||
| 	} | 	} | ||||||
|  | 	if (env != NULL) | ||||||
|  | 		environ_free(env); | ||||||
|  | 	free(title); | ||||||
| 	cmd_free_argv(argc, argv); | 	cmd_free_argv(argc, argv); | ||||||
| 	return (CMD_RETURN_WAIT); | 	return (CMD_RETURN_WAIT); | ||||||
| } | } | ||||||
|   | |||||||
| @@ -118,7 +118,7 @@ cmd_if_shell_exec(struct cmd *self, struct cmdq_item *item) | |||||||
| 	if (cdata->client != NULL) | 	if (cdata->client != NULL) | ||||||
| 		cdata->client->references++; | 		cdata->client->references++; | ||||||
|  |  | ||||||
| 	if (job_run(shellcmd, 0, NULL, s, | 	if (job_run(shellcmd, 0, NULL, NULL, s, | ||||||
| 	    server_client_get_cwd(cmdq_get_client(item), s), NULL, | 	    server_client_get_cwd(cmdq_get_client(item), s), NULL, | ||||||
| 	    cmd_if_shell_callback, cmd_if_shell_free, cdata, 0, -1, | 	    cmd_if_shell_callback, cmd_if_shell_free, cdata, 0, -1, | ||||||
| 	    -1) == NULL) { | 	    -1) == NULL) { | ||||||
|   | |||||||
| @@ -130,7 +130,7 @@ cmd_pipe_pane_exec(struct cmd *self, struct cmdq_item *item) | |||||||
| 		sigprocmask(SIG_SETMASK, &oldset, NULL); | 		sigprocmask(SIG_SETMASK, &oldset, NULL); | ||||||
| 		close(pipe_fd[0]); | 		close(pipe_fd[0]); | ||||||
|  |  | ||||||
| 		null_fd = open(_PATH_DEVNULL, O_WRONLY, 0); | 		null_fd = open(_PATH_DEVNULL, O_WRONLY); | ||||||
| 		if (out) { | 		if (out) { | ||||||
| 			if (dup2(pipe_fd[1], STDIN_FILENO) == -1) | 			if (dup2(pipe_fd[1], STDIN_FILENO) == -1) | ||||||
| 				_exit(1); | 				_exit(1); | ||||||
|   | |||||||
| @@ -188,7 +188,7 @@ cmd_run_shell_timer(__unused int fd, __unused short events, void* arg) | |||||||
| 			cmd_run_shell_free(cdata); | 			cmd_run_shell_free(cdata); | ||||||
| 			return; | 			return; | ||||||
| 		} | 		} | ||||||
| 		if (job_run(cmd, 0, NULL, cdata->s, cdata->cwd, NULL, | 		if (job_run(cmd, 0, NULL, NULL, cdata->s, cdata->cwd, NULL, | ||||||
| 		    cmd_run_shell_callback, cmd_run_shell_free, cdata, | 		    cmd_run_shell_callback, cmd_run_shell_free, cdata, | ||||||
| 		    cdata->flags, -1, -1) == NULL) | 		    cdata->flags, -1, -1) == NULL) | ||||||
| 			cmd_run_shell_free(cdata); | 			cmd_run_shell_free(cdata); | ||||||
|   | |||||||
| @@ -203,6 +203,8 @@ cmd_send_keys_exec(struct cmd *self, struct cmdq_item *item) | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if (count == 0) { | 	if (count == 0) { | ||||||
|  | 		if (args_has(args, 'N') || args_has(args, 'R')) | ||||||
|  | 			return (CMD_RETURN_NORMAL); | ||||||
| 		for (; np != 0; np--) | 		for (; np != 0; np--) | ||||||
| 			cmd_send_keys_inject_key(item, NULL, event->key); | 			cmd_send_keys_inject_key(item, NULL, event->key); | ||||||
| 		return (CMD_RETURN_NORMAL); | 		return (CMD_RETURN_NORMAL); | ||||||
|   | |||||||
| @@ -126,6 +126,12 @@ cmd_show_options_exec(struct cmd *self, struct cmdq_item *item) | |||||||
| 		parent = 0; | 		parent = 0; | ||||||
| 	if (o != NULL) | 	if (o != NULL) | ||||||
| 		cmd_show_options_print(self, item, o, idx, parent); | 		cmd_show_options_print(self, item, o, idx, parent); | ||||||
|  | 	else if (*name == '@') { | ||||||
|  | 		if (args_has(args, 'q')) | ||||||
|  | 			goto fail; | ||||||
|  | 		cmdq_error(item, "invalid option: %s", argument); | ||||||
|  | 		goto fail; | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	free(name); | 	free(name); | ||||||
| 	free(argument); | 	free(argument); | ||||||
|   | |||||||
							
								
								
									
										15
									
								
								colour.c
									
									
									
									
									
								
							
							
						
						
									
										15
									
								
								colour.c
									
									
									
									
									
								
							| @@ -105,6 +105,21 @@ colour_split_rgb(int c, u_char *r, u_char *g, u_char *b) | |||||||
| 	*b = c & 0xff; | 	*b = c & 0xff; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | /* Force colour to RGB if not already. */ | ||||||
|  | int | ||||||
|  | colour_force_rgb(int c) | ||||||
|  | { | ||||||
|  | 	if (c & COLOUR_FLAG_RGB) | ||||||
|  | 		return (c); | ||||||
|  | 	if (c & COLOUR_FLAG_256) | ||||||
|  | 		return (colour_256toRGB(c)); | ||||||
|  | 	if (c >= 0 && c <= 7) | ||||||
|  | 		return (colour_256toRGB(c)); | ||||||
|  | 	if (c >= 90 && c <= 97) | ||||||
|  | 		return (colour_256toRGB(8 + c - 90)); | ||||||
|  | 	return (-1); | ||||||
|  | } | ||||||
|  |  | ||||||
| /* Convert colour to a string. */ | /* Convert colour to a string. */ | ||||||
| const char * | const char * | ||||||
| colour_tostring(int c) | colour_tostring(int c) | ||||||
|   | |||||||
| @@ -677,7 +677,8 @@ format_draw_many(struct screen_write_ctx *ctx, struct style *sy, char ch, | |||||||
| /* Draw a format to a screen. */ | /* Draw a format to a screen. */ | ||||||
| void | void | ||||||
| format_draw(struct screen_write_ctx *octx, const struct grid_cell *base, | format_draw(struct screen_write_ctx *octx, const struct grid_cell *base, | ||||||
|     u_int available, const char *expanded, struct style_ranges *srs) |     u_int available, const char *expanded, struct style_ranges *srs, | ||||||
|  |     int default_colours) | ||||||
| { | { | ||||||
| 	enum { LEFT, | 	enum { LEFT, | ||||||
| 	       CENTRE, | 	       CENTRE, | ||||||
| @@ -819,6 +820,10 @@ format_draw(struct screen_write_ctx *octx, const struct grid_cell *base, | |||||||
| 		log_debug("%s: style '%s' -> '%s'", __func__, tmp, | 		log_debug("%s: style '%s' -> '%s'", __func__, tmp, | ||||||
| 		    style_tostring(&sy)); | 		    style_tostring(&sy)); | ||||||
| 		free(tmp); | 		free(tmp); | ||||||
|  | 		if (default_colours) { | ||||||
|  | 			sy.gc.bg = base->bg; | ||||||
|  | 			sy.gc.fg = base->fg; | ||||||
|  | 		} | ||||||
|  |  | ||||||
| 		/* If this style has a fill colour, store it for later. */ | 		/* If this style has a fill colour, store it for later. */ | ||||||
| 		if (sy.fill != 8) | 		if (sy.fill != 8) | ||||||
|   | |||||||
							
								
								
									
										26
									
								
								format.c
									
									
									
									
									
								
							
							
						
						
									
										26
									
								
								format.c
									
									
									
									
									
								
							| @@ -101,6 +101,7 @@ format_job_cmp(struct format_job *fj1, struct format_job *fj2) | |||||||
| #define FORMAT_WINDOW_NAME 0x4000 | #define FORMAT_WINDOW_NAME 0x4000 | ||||||
| #define FORMAT_SESSION_NAME 0x8000 | #define FORMAT_SESSION_NAME 0x8000 | ||||||
| #define FORMAT_CHARACTER 0x10000 | #define FORMAT_CHARACTER 0x10000 | ||||||
|  | #define FORMAT_COLOUR 0x20000 | ||||||
|  |  | ||||||
| /* Limit on recursion. */ | /* Limit on recursion. */ | ||||||
| #define FORMAT_LOOP_LIMIT 100 | #define FORMAT_LOOP_LIMIT 100 | ||||||
| @@ -390,7 +391,7 @@ format_job_get(struct format_expand_state *es, const char *cmd) | |||||||
| 	if (force && fj->job != NULL) | 	if (force && fj->job != NULL) | ||||||
| 	       job_free(fj->job); | 	       job_free(fj->job); | ||||||
| 	if (force || (fj->job == NULL && fj->last != t)) { | 	if (force || (fj->job == NULL && fj->last != t)) { | ||||||
| 		fj->job = job_run(expanded, 0, NULL, NULL, | 		fj->job = job_run(expanded, 0, NULL, NULL, NULL, | ||||||
| 		    server_client_get_cwd(ft->client, NULL), format_job_update, | 		    server_client_get_cwd(ft->client, NULL), format_job_update, | ||||||
| 		    format_job_complete, NULL, fj, JOB_NOWAIT, -1, -1); | 		    format_job_complete, NULL, fj, JOB_NOWAIT, -1, -1); | ||||||
| 		if (fj->job == NULL) { | 		if (fj->job == NULL) { | ||||||
| @@ -3555,7 +3556,7 @@ format_build_modifiers(struct format_expand_state *es, const char **s, | |||||||
|  |  | ||||||
| 	/* | 	/* | ||||||
| 	 * Modifiers are a ; separated list of the forms: | 	 * Modifiers are a ; separated list of the forms: | ||||||
| 	 *      l,m,C,a,b,d,n,t,w,q,E,T,S,W,P,<,> | 	 *      l,m,C,a,b,c,d,n,t,w,q,E,T,S,W,P,<,> | ||||||
| 	 *	=a | 	 *	=a | ||||||
| 	 *	=/a | 	 *	=/a | ||||||
| 	 *      =/a/ | 	 *      =/a/ | ||||||
| @@ -3572,7 +3573,7 @@ format_build_modifiers(struct format_expand_state *es, const char **s, | |||||||
| 			cp++; | 			cp++; | ||||||
|  |  | ||||||
| 		/* Check single character modifiers with no arguments. */ | 		/* Check single character modifiers with no arguments. */ | ||||||
| 		if (strchr("labdnwETSWP<>", cp[0]) != NULL && | 		if (strchr("labcdnwETSWP<>", cp[0]) != NULL && | ||||||
| 		    format_is_end(cp[1])) { | 		    format_is_end(cp[1])) { | ||||||
| 			format_add_modifier(&list, count, cp, 1, NULL, 0); | 			format_add_modifier(&list, count, cp, 1, NULL, 0); | ||||||
| 			cp++; | 			cp++; | ||||||
| @@ -4052,10 +4053,10 @@ format_replace(struct format_expand_state *es, const char *key, size_t keylen, | |||||||
| 	const char			 *errstr, *copy, *cp, *marker = NULL; | 	const char			 *errstr, *copy, *cp, *marker = NULL; | ||||||
| 	const char			 *time_format = NULL; | 	const char			 *time_format = NULL; | ||||||
| 	char				 *copy0, *condition, *found, *new; | 	char				 *copy0, *condition, *found, *new; | ||||||
| 	char				 *value, *left, *right, c; | 	char				 *value, *left, *right; | ||||||
| 	size_t				  valuelen; | 	size_t				  valuelen; | ||||||
| 	int				  modifiers = 0, limit = 0, width = 0; | 	int				  modifiers = 0, limit = 0, width = 0; | ||||||
| 	int				  j; | 	int				  j, c; | ||||||
| 	struct format_modifier		 *list, *cmp = NULL, *search = NULL; | 	struct format_modifier		 *list, *cmp = NULL, *search = NULL; | ||||||
| 	struct format_modifier		**sub = NULL, *mexp = NULL, *fm; | 	struct format_modifier		**sub = NULL, *mexp = NULL, *fm; | ||||||
| 	u_int				  i, count, nsub = 0; | 	u_int				  i, count, nsub = 0; | ||||||
| @@ -4126,6 +4127,9 @@ format_replace(struct format_expand_state *es, const char *key, size_t keylen, | |||||||
| 			case 'b': | 			case 'b': | ||||||
| 				modifiers |= FORMAT_BASENAME; | 				modifiers |= FORMAT_BASENAME; | ||||||
| 				break; | 				break; | ||||||
|  | 			case 'c': | ||||||
|  | 				modifiers |= FORMAT_COLOUR; | ||||||
|  | 				break; | ||||||
| 			case 'd': | 			case 'd': | ||||||
| 				modifiers |= FORMAT_DIRNAME; | 				modifiers |= FORMAT_DIRNAME; | ||||||
| 				break; | 				break; | ||||||
| @@ -4201,6 +4205,18 @@ format_replace(struct format_expand_state *es, const char *key, size_t keylen, | |||||||
| 		goto done; | 		goto done; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	/* Is this a colour? */ | ||||||
|  | 	if (modifiers & FORMAT_COLOUR) { | ||||||
|  | 		new = format_expand1(es, copy); | ||||||
|  | 		c = colour_fromstring(new); | ||||||
|  | 		if (c == -1 || (c = colour_force_rgb(c)) == -1) | ||||||
|  | 			value = xstrdup(""); | ||||||
|  | 		else | ||||||
|  | 			xasprintf(&value, "%06x", c & 0xffffff); | ||||||
|  | 		free(new); | ||||||
|  | 		goto done; | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	/* Is this a loop, comparison or condition? */ | 	/* Is this a loop, comparison or condition? */ | ||||||
| 	if (modifiers & FORMAT_SESSIONS) { | 	if (modifiers & FORMAT_SESSIONS) { | ||||||
| 		value = format_loop_sessions(es, copy); | 		value = format_loop_sessions(es, copy); | ||||||
|   | |||||||
							
								
								
									
										76
									
								
								input.c
									
									
									
									
									
								
							
							
						
						
									
										76
									
								
								input.c
									
									
									
									
									
								
							| @@ -137,10 +137,12 @@ static void	input_reset_cell(struct input_ctx *); | |||||||
| static void	input_osc_4(struct input_ctx *, const char *); | static void	input_osc_4(struct input_ctx *, const char *); | ||||||
| static void	input_osc_10(struct input_ctx *, const char *); | static void	input_osc_10(struct input_ctx *, const char *); | ||||||
| static void	input_osc_11(struct input_ctx *, const char *); | static void	input_osc_11(struct input_ctx *, const char *); | ||||||
|  | static void	input_osc_12(struct input_ctx *, const char *); | ||||||
| static void	input_osc_52(struct input_ctx *, const char *); | static void	input_osc_52(struct input_ctx *, const char *); | ||||||
| static void	input_osc_104(struct input_ctx *, const char *); | static void	input_osc_104(struct input_ctx *, const char *); | ||||||
| static void	input_osc_110(struct input_ctx *, const char *); | static void	input_osc_110(struct input_ctx *, const char *); | ||||||
| static void	input_osc_111(struct input_ctx *, const char *); | static void	input_osc_111(struct input_ctx *, const char *); | ||||||
|  | static void	input_osc_112(struct input_ctx *, const char *); | ||||||
|  |  | ||||||
| /* Transition entry/exit handlers. */ | /* Transition entry/exit handlers. */ | ||||||
| static void	input_clear(struct input_ctx *); | static void	input_clear(struct input_ctx *); | ||||||
| @@ -1617,7 +1619,7 @@ input_csi_dispatch(struct input_ctx *ictx) | |||||||
| 	case INPUT_CSI_DECSCUSR: | 	case INPUT_CSI_DECSCUSR: | ||||||
| 		n = input_get(ictx, 0, 0, 0); | 		n = input_get(ictx, 0, 0, 0); | ||||||
| 		if (n != -1) | 		if (n != -1) | ||||||
| 			screen_set_cursor_style(s, n); | 			screen_set_cursor_style(n, &s->cstyle, &s->mode); | ||||||
| 		break; | 		break; | ||||||
| 	case INPUT_CSI_XDA: | 	case INPUT_CSI_XDA: | ||||||
| 		n = input_get(ictx, 0, 0, 0); | 		n = input_get(ictx, 0, 0, 0); | ||||||
| @@ -1683,6 +1685,7 @@ input_csi_dispatch_rm_private(struct input_ctx *ictx) | |||||||
| 			break; | 			break; | ||||||
| 		case 12: | 		case 12: | ||||||
| 			screen_write_mode_clear(sctx, MODE_CURSOR_BLINKING); | 			screen_write_mode_clear(sctx, MODE_CURSOR_BLINKING); | ||||||
|  | 			screen_write_mode_set(sctx, MODE_CURSOR_BLINKING_SET); | ||||||
| 			break; | 			break; | ||||||
| 		case 25:	/* TCEM */ | 		case 25:	/* TCEM */ | ||||||
| 			screen_write_mode_clear(sctx, MODE_CURSOR); | 			screen_write_mode_clear(sctx, MODE_CURSOR); | ||||||
| @@ -1772,6 +1775,7 @@ input_csi_dispatch_sm_private(struct input_ctx *ictx) | |||||||
| 			break; | 			break; | ||||||
| 		case 12: | 		case 12: | ||||||
| 			screen_write_mode_set(sctx, MODE_CURSOR_BLINKING); | 			screen_write_mode_set(sctx, MODE_CURSOR_BLINKING); | ||||||
|  | 			screen_write_mode_set(sctx, MODE_CURSOR_BLINKING_SET); | ||||||
| 			break; | 			break; | ||||||
| 		case 25:	/* TCEM */ | 		case 25:	/* TCEM */ | ||||||
| 			screen_write_mode_set(sctx, MODE_CURSOR); | 			screen_write_mode_set(sctx, MODE_CURSOR); | ||||||
| @@ -2322,8 +2326,7 @@ input_exit_osc(struct input_ctx *ictx) | |||||||
| 		input_osc_11(ictx, p); | 		input_osc_11(ictx, p); | ||||||
| 		break; | 		break; | ||||||
| 	case 12: | 	case 12: | ||||||
| 		if (utf8_isvalid(p) && *p != '?') /* ? is colour request */ | 		input_osc_12(ictx, p); | ||||||
| 			screen_set_cursor_colour(sctx->s, p); |  | ||||||
| 		break; | 		break; | ||||||
| 	case 52: | 	case 52: | ||||||
| 		input_osc_52(ictx, p); | 		input_osc_52(ictx, p); | ||||||
| @@ -2338,8 +2341,7 @@ input_exit_osc(struct input_ctx *ictx) | |||||||
| 		input_osc_111(ictx, p); | 		input_osc_111(ictx, p); | ||||||
| 		break; | 		break; | ||||||
| 	case 112: | 	case 112: | ||||||
| 		if (*p == '\0') /* no arguments allowed */ | 		input_osc_112(ictx, p); | ||||||
| 			screen_set_cursor_colour(sctx->s, ""); |  | ||||||
| 		break; | 		break; | ||||||
| 	default: | 	default: | ||||||
| 		log_debug("%s: unknown '%u'", __func__, option); | 		log_debug("%s: unknown '%u'", __func__, option); | ||||||
| @@ -2392,6 +2394,7 @@ static void | |||||||
| input_exit_rename(struct input_ctx *ictx) | input_exit_rename(struct input_ctx *ictx) | ||||||
| { | { | ||||||
| 	struct window_pane	*wp = ictx->wp; | 	struct window_pane	*wp = ictx->wp; | ||||||
|  | 	struct window		*w; | ||||||
| 	struct options_entry	*o; | 	struct options_entry	*o; | ||||||
|  |  | ||||||
| 	if (wp == NULL) | 	if (wp == NULL) | ||||||
| @@ -2404,17 +2407,20 @@ input_exit_rename(struct input_ctx *ictx) | |||||||
|  |  | ||||||
| 	if (!utf8_isvalid(ictx->input_buf)) | 	if (!utf8_isvalid(ictx->input_buf)) | ||||||
| 		return; | 		return; | ||||||
|  | 	w = wp->window; | ||||||
|  |  | ||||||
| 	if (ictx->input_len == 0) { | 	if (ictx->input_len == 0) { | ||||||
| 		o = options_get_only(wp->window->options, "automatic-rename"); | 		o = options_get_only(w->options, "automatic-rename"); | ||||||
| 		if (o != NULL) | 		if (o != NULL) | ||||||
| 			options_remove_or_default(o, -1, NULL); | 			options_remove_or_default(o, -1, NULL); | ||||||
| 		return; | 		if (!options_get_number(w->options, "automatic-rename")) | ||||||
|  | 			window_set_name(w, ""); | ||||||
|  | 	} else { | ||||||
|  | 		options_set_number(w->options, "automatic-rename", 0); | ||||||
|  | 		window_set_name(w, ictx->input_buf); | ||||||
| 	} | 	} | ||||||
| 	window_set_name(wp->window, ictx->input_buf); | 	server_redraw_window_borders(w); | ||||||
| 	options_set_number(wp->window->options, "automatic-rename", 0); | 	server_status_window(w); | ||||||
| 	server_redraw_window_borders(wp->window); |  | ||||||
| 	server_status_window(wp->window); |  | ||||||
| } | } | ||||||
|  |  | ||||||
| /* Open UTF-8 character. */ | /* Open UTF-8 character. */ | ||||||
| @@ -2501,7 +2507,9 @@ input_osc_colour_reply(struct input_ctx *ictx, u_int n, int c) | |||||||
|     u_char	 r, g, b; |     u_char	 r, g, b; | ||||||
|     const char	*end; |     const char	*end; | ||||||
|  |  | ||||||
|     if (c == 8 || (~c & COLOUR_FLAG_RGB)) |     if (c != -1) | ||||||
|  | 	    c = colour_force_rgb(c); | ||||||
|  |     if (c == -1) | ||||||
| 	    return; | 	    return; | ||||||
|     colour_split_rgb(c, &r, &g, &b); |     colour_split_rgb(c, &r, &g, &b); | ||||||
|  |  | ||||||
| @@ -2509,7 +2517,8 @@ input_osc_colour_reply(struct input_ctx *ictx, u_int n, int c) | |||||||
| 	    end = "\007"; | 	    end = "\007"; | ||||||
|     else |     else | ||||||
| 	    end = "\033\\"; | 	    end = "\033\\"; | ||||||
|     input_reply(ictx, "\033]%u;rgb:%02hhx/%02hhx/%02hhx%s", n, r, g, b, end); |     input_reply(ictx, "\033]%u;rgb:%02hhx%02hhx/%02hhx%02hhx/%02hhx%02hhx%s", | ||||||
|  | 	n, r, r, g, g, b, b, end); | ||||||
| } | } | ||||||
|  |  | ||||||
| /* Handle the OSC 4 sequence for setting (multiple) palette entries. */ | /* Handle the OSC 4 sequence for setting (multiple) palette entries. */ | ||||||
| @@ -2533,6 +2542,12 @@ input_osc_4(struct input_ctx *ictx, const char *p) | |||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		s = strsep(&next, ";"); | 		s = strsep(&next, ";"); | ||||||
|  | 		if (strcmp(s, "?") == 0) { | ||||||
|  | 			c = colour_palette_get(ictx->palette, idx); | ||||||
|  | 			if (c != -1) | ||||||
|  | 				input_osc_colour_reply(ictx, 4, c); | ||||||
|  | 			continue; | ||||||
|  | 		} | ||||||
| 		if ((c = input_osc_parse_colour(s)) == -1) { | 		if ((c = input_osc_parse_colour(s)) == -1) { | ||||||
| 			s = next; | 			s = next; | ||||||
| 			continue; | 			continue; | ||||||
| @@ -2576,7 +2591,7 @@ input_osc_10(struct input_ctx *ictx, const char *p) | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| /* Handle the OSC 110 sequence for resetting background colour. */ | /* Handle the OSC 110 sequence for resetting foreground colour. */ | ||||||
| static void | static void | ||||||
| input_osc_110(struct input_ctx *ictx, const char *p) | input_osc_110(struct input_ctx *ictx, const char *p) | ||||||
| { | { | ||||||
| @@ -2636,6 +2651,39 @@ input_osc_111(struct input_ctx *ictx, const char *p) | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | /* Handle the OSC 12 sequence for setting and querying cursor colour. */ | ||||||
|  | static void | ||||||
|  | input_osc_12(struct input_ctx *ictx, const char *p) | ||||||
|  | { | ||||||
|  | 	struct window_pane	*wp = ictx->wp; | ||||||
|  | 	int			 c; | ||||||
|  |  | ||||||
|  | 	if (strcmp(p, "?") == 0) { | ||||||
|  | 		if (wp != NULL) { | ||||||
|  | 			c = ictx->ctx.s->ccolour; | ||||||
|  | 			if (c == -1) | ||||||
|  | 				c = ictx->ctx.s->default_ccolour; | ||||||
|  | 			input_osc_colour_reply(ictx, 12, c); | ||||||
|  | 		} | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if ((c = input_osc_parse_colour(p)) == -1) { | ||||||
|  | 		log_debug("bad OSC 12: %s", p); | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  | 	screen_set_cursor_colour(ictx->ctx.s, c); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* Handle the OSC 112 sequence for resetting cursor colour. */ | ||||||
|  | static void | ||||||
|  | input_osc_112(struct input_ctx *ictx, const char *p) | ||||||
|  | { | ||||||
|  | 	if (*p == '\0') /* no arguments allowed */ | ||||||
|  | 		screen_set_cursor_colour(ictx->ctx.s, -1); | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
| /* Handle the OSC 52 sequence for setting the clipboard. */ | /* Handle the OSC 52 sequence for setting the clipboard. */ | ||||||
| static void | static void | ||||||
| input_osc_52(struct input_ctx *ictx, const char *p) | input_osc_52(struct input_ctx *ictx, const char *p) | ||||||
|   | |||||||
							
								
								
									
										7
									
								
								job.c
									
									
									
									
									
								
							
							
						
						
									
										7
									
								
								job.c
									
									
									
									
									
								
							| @@ -69,7 +69,7 @@ static LIST_HEAD(joblist, job) all_jobs = LIST_HEAD_INITIALIZER(all_jobs); | |||||||
|  |  | ||||||
| /* Start a job running. */ | /* Start a job running. */ | ||||||
| struct job * | struct job * | ||||||
| job_run(const char *cmd, int argc, char **argv, struct session *s, | job_run(const char *cmd, int argc, char **argv, struct environ *e, struct session *s, | ||||||
|     const char *cwd, job_update_cb updatecb, job_complete_cb completecb, |     const char *cwd, job_update_cb updatecb, job_complete_cb completecb, | ||||||
|     job_free_cb freecb, void *data, int flags, int sx, int sy) |     job_free_cb freecb, void *data, int flags, int sx, int sy) | ||||||
| { | { | ||||||
| @@ -87,6 +87,9 @@ job_run(const char *cmd, int argc, char **argv, struct session *s, | |||||||
| 	 * if-shell to decide on default-terminal based on outside TERM. | 	 * if-shell to decide on default-terminal based on outside TERM. | ||||||
| 	 */ | 	 */ | ||||||
| 	env = environ_for_session(s, !cfg_finished); | 	env = environ_for_session(s, !cfg_finished); | ||||||
|  | 	if (e != NULL) { | ||||||
|  | 		environ_copy(e, env); | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	sigfillset(&set); | 	sigfillset(&set); | ||||||
| 	sigprocmask(SIG_BLOCK, &set, &oldset); | 	sigprocmask(SIG_BLOCK, &set, &oldset); | ||||||
| @@ -137,7 +140,7 @@ job_run(const char *cmd, int argc, char **argv, struct session *s, | |||||||
| 				close(out[1]); | 				close(out[1]); | ||||||
| 			close(out[0]); | 			close(out[0]); | ||||||
|  |  | ||||||
| 			nullfd = open(_PATH_DEVNULL, O_RDWR, 0); | 			nullfd = open(_PATH_DEVNULL, O_RDWR); | ||||||
| 			if (nullfd == -1) | 			if (nullfd == -1) | ||||||
| 				fatal("open failed"); | 				fatal("open failed"); | ||||||
| 			if (dup2(nullfd, STDERR_FILENO) == -1) | 			if (dup2(nullfd, STDERR_FILENO) == -1) | ||||||
|   | |||||||
							
								
								
									
										49
									
								
								menu.c
									
									
									
									
									
								
							
							
						
						
									
										49
									
								
								menu.c
									
									
									
									
									
								
							| @@ -55,10 +55,11 @@ menu_add_item(struct menu *menu, const struct menu_item *item, | |||||||
|     struct cmdq_item *qitem, struct client *c, struct cmd_find_state *fs) |     struct cmdq_item *qitem, struct client *c, struct cmd_find_state *fs) | ||||||
| { | { | ||||||
| 	struct menu_item	*new_item; | 	struct menu_item	*new_item; | ||||||
| 	const char		*key, *cmd; | 	const char		*key = NULL, *cmd, *suffix = ""; | ||||||
| 	char			*s, *name; | 	char			*s, *name; | ||||||
| 	u_int			 width; | 	u_int			 width, max_width; | ||||||
| 	int			 line; | 	int			 line; | ||||||
|  | 	size_t			 keylen, slen; | ||||||
|  |  | ||||||
| 	line = (item == NULL || item->name == NULL || *item->name == '\0'); | 	line = (item == NULL || item->name == NULL || *item->name == '\0'); | ||||||
| 	if (line && menu->count == 0) | 	if (line && menu->count == 0) | ||||||
| @@ -80,11 +81,34 @@ menu_add_item(struct menu *menu, const struct menu_item *item, | |||||||
| 		menu->count--; | 		menu->count--; | ||||||
| 		return; | 		return; | ||||||
| 	} | 	} | ||||||
|  | 	max_width = c->tty.sx - 4; | ||||||
|  |  | ||||||
|  | 	slen = strlen(s); | ||||||
| 	if (*s != '-' && item->key != KEYC_UNKNOWN && item->key != KEYC_NONE) { | 	if (*s != '-' && item->key != KEYC_UNKNOWN && item->key != KEYC_NONE) { | ||||||
| 		key = key_string_lookup_key(item->key, 0); | 		key = key_string_lookup_key(item->key, 0); | ||||||
| 		xasprintf(&name, "%s#[default] #[align=right](%s)", s, key); | 		keylen = strlen(key) + 3; /* 3 = space and two brackets */ | ||||||
| 	} else |  | ||||||
| 		xasprintf(&name, "%s", s); | 		/* | ||||||
|  | 		 * Add the key if it is shorter than a quarter of the available | ||||||
|  | 		 * space or there is space for the entire item text and the | ||||||
|  | 		 * key. | ||||||
|  | 		 */ | ||||||
|  | 		if (keylen <= max_width / 4) | ||||||
|  | 			max_width -= keylen; | ||||||
|  | 		else if (keylen >= max_width || slen >= max_width - keylen) | ||||||
|  | 			key = NULL; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if (slen > max_width) { | ||||||
|  | 		max_width--; | ||||||
|  | 		suffix = ">"; | ||||||
|  | 	} | ||||||
|  | 	if (key != NULL) | ||||||
|  | 		xasprintf(&name, "%.*s%s#[default] #[align=right](%s)", | ||||||
|  | 		    (int)max_width, s, suffix, key); | ||||||
|  | 	else | ||||||
|  | 		xasprintf(&name, "%.*s%s", (int)max_width, s, suffix); | ||||||
|  |  | ||||||
| 	new_item->name = name; | 	new_item->name = name; | ||||||
| 	free(s); | 	free(s); | ||||||
|  |  | ||||||
| @@ -100,6 +124,8 @@ menu_add_item(struct menu *menu, const struct menu_item *item, | |||||||
| 	new_item->key = item->key; | 	new_item->key = item->key; | ||||||
|  |  | ||||||
| 	width = format_width(new_item->name); | 	width = format_width(new_item->name); | ||||||
|  | 	if (*new_item->name == '-') | ||||||
|  | 		width--; | ||||||
| 	if (width > menu->width) | 	if (width > menu->width) | ||||||
| 		menu->width = width; | 		menu->width = width; | ||||||
| } | } | ||||||
| @@ -140,17 +166,16 @@ menu_mode_cb(__unused struct client *c, void *data, __unused u_int *cx, | |||||||
| 	return (&md->s); | 	return (&md->s); | ||||||
| } | } | ||||||
|  |  | ||||||
| int | /* Return parts of the input range which are not obstructed by the menu. */ | ||||||
| menu_check_cb(__unused struct client *c, void *data, u_int px, u_int py) | void | ||||||
|  | menu_check_cb(__unused struct client *c, void *data, u_int px, u_int py, | ||||||
|  |     u_int nx, struct overlay_ranges *r) | ||||||
| { | { | ||||||
| 	struct menu_data	*md = data; | 	struct menu_data	*md = data; | ||||||
| 	struct menu		*menu = md->menu; | 	struct menu		*menu = md->menu; | ||||||
|  |  | ||||||
| 	if (px < md->px || px > md->px + menu->width + 3) | 	server_client_overlay_range(md->px, md->py, menu->width + 4, | ||||||
| 		return (1); | 	    menu->count + 2, px, py, nx, r); | ||||||
| 	if (py < md->py || py > md->py + menu->count + 1) |  | ||||||
| 		return (1); |  | ||||||
| 	return (0); |  | ||||||
| } | } | ||||||
|  |  | ||||||
| void | void | ||||||
|   | |||||||
							
								
								
									
										18
									
								
								mode-tree.c
									
									
									
									
									
								
							
							
						
						
									
										18
									
								
								mode-tree.c
									
									
									
									
									
								
							| @@ -716,14 +716,14 @@ mode_tree_draw(struct mode_tree_data *mtd) | |||||||
| 			screen_write_nputs(&ctx, w, &gc0, "%s", text); | 			screen_write_nputs(&ctx, w, &gc0, "%s", text); | ||||||
| 			if (mti->text != NULL) { | 			if (mti->text != NULL) { | ||||||
| 				format_draw(&ctx, &gc0, w - width, mti->text, | 				format_draw(&ctx, &gc0, w - width, mti->text, | ||||||
| 				    NULL); | 				    NULL, 0); | ||||||
| 			} | 			} | ||||||
| 		} else { | 		} else { | ||||||
| 			screen_write_clearendofline(&ctx, gc.bg); | 			screen_write_clearendofline(&ctx, gc.bg); | ||||||
| 			screen_write_nputs(&ctx, w, &gc, "%s", text); | 			screen_write_nputs(&ctx, w, &gc, "%s", text); | ||||||
| 			if (mti->text != NULL) { | 			if (mti->text != NULL) { | ||||||
| 				format_draw(&ctx, &gc, w - width, mti->text, | 				format_draw(&ctx, &gc, w - width, mti->text, | ||||||
| 				    NULL); | 				    NULL, 0); | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 		free(text); | 		free(text); | ||||||
| @@ -736,10 +736,8 @@ mode_tree_draw(struct mode_tree_data *mtd) | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	sy = screen_size_y(s); | 	sy = screen_size_y(s); | ||||||
| 	if (!mtd->preview || sy <= 4 || h <= 4 || sy - h <= 4 || w <= 4) { | 	if (!mtd->preview || sy <= 4 || h <= 4 || sy - h <= 4 || w <= 4) | ||||||
| 		screen_write_stop(&ctx); | 		goto done; | ||||||
| 		return; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	line = &mtd->line_list[mtd->current]; | 	line = &mtd->line_list[mtd->current]; | ||||||
| 	mti = line->item; | 	mti = line->item; | ||||||
| @@ -747,7 +745,7 @@ mode_tree_draw(struct mode_tree_data *mtd) | |||||||
| 		mti = mti->parent; | 		mti = mti->parent; | ||||||
|  |  | ||||||
| 	screen_write_cursormove(&ctx, 0, h, 0); | 	screen_write_cursormove(&ctx, 0, h, 0); | ||||||
| 	screen_write_box(&ctx, w, sy - h); | 	screen_write_box(&ctx, w, sy - h, BOX_LINES_DEFAULT, NULL, NULL); | ||||||
|  |  | ||||||
| 	if (mtd->sort_list != NULL) { | 	if (mtd->sort_list != NULL) { | ||||||
| 		xasprintf(&text, " %s (sort: %s%s)", mti->name, | 		xasprintf(&text, " %s (sort: %s%s)", mti->name, | ||||||
| @@ -783,6 +781,8 @@ mode_tree_draw(struct mode_tree_data *mtd) | |||||||
| 		mtd->drawcb(mtd->modedata, mti->itemdata, &ctx, box_x, box_y); | 		mtd->drawcb(mtd->modedata, mti->itemdata, &ctx, box_x, box_y); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | done: | ||||||
|  | 	screen_write_cursormove(&ctx, 0, mtd->current - mtd->offset, 0); | ||||||
| 	screen_write_stop(&ctx); | 	screen_write_stop(&ctx); | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -1055,7 +1055,6 @@ mode_tree_key(struct mode_tree_data *mtd, struct client *c, key_code *key, | |||||||
| 	case '\016': /* C-n */ | 	case '\016': /* C-n */ | ||||||
| 		mode_tree_down(mtd, 1); | 		mode_tree_down(mtd, 1); | ||||||
| 		break; | 		break; | ||||||
| 	case 'g': |  | ||||||
| 	case KEYC_PPAGE: | 	case KEYC_PPAGE: | ||||||
| 	case '\002': /* C-b */ | 	case '\002': /* C-b */ | ||||||
| 		for (i = 0; i < mtd->height; i++) { | 		for (i = 0; i < mtd->height; i++) { | ||||||
| @@ -1064,7 +1063,6 @@ mode_tree_key(struct mode_tree_data *mtd, struct client *c, key_code *key, | |||||||
| 			mode_tree_up(mtd, 1); | 			mode_tree_up(mtd, 1); | ||||||
| 		} | 		} | ||||||
| 		break; | 		break; | ||||||
| 	case 'G': |  | ||||||
| 	case KEYC_NPAGE: | 	case KEYC_NPAGE: | ||||||
| 	case '\006': /* C-f */ | 	case '\006': /* C-f */ | ||||||
| 		for (i = 0; i < mtd->height; i++) { | 		for (i = 0; i < mtd->height; i++) { | ||||||
| @@ -1073,10 +1071,12 @@ mode_tree_key(struct mode_tree_data *mtd, struct client *c, key_code *key, | |||||||
| 			mode_tree_down(mtd, 1); | 			mode_tree_down(mtd, 1); | ||||||
| 		} | 		} | ||||||
| 		break; | 		break; | ||||||
|  | 	case 'g': | ||||||
| 	case KEYC_HOME: | 	case KEYC_HOME: | ||||||
| 		mtd->current = 0; | 		mtd->current = 0; | ||||||
| 		mtd->offset = 0; | 		mtd->offset = 0; | ||||||
| 		break; | 		break; | ||||||
|  | 	case 'G': | ||||||
| 	case KEYC_END: | 	case KEYC_END: | ||||||
| 		mtd->current = mtd->line_size - 1; | 		mtd->current = mtd->line_size - 1; | ||||||
| 		if (mtd->current > mtd->height - 1) | 		if (mtd->current > mtd->height - 1) | ||||||
|   | |||||||
| @@ -56,12 +56,19 @@ static const char *options_table_bell_action_list[] = { | |||||||
| static const char *options_table_visual_bell_list[] = { | static const char *options_table_visual_bell_list[] = { | ||||||
| 	"off", "on", "both", NULL | 	"off", "on", "both", NULL | ||||||
| }; | }; | ||||||
|  | static const char *options_table_cursor_style_list[] = { | ||||||
|  | 	"default", "blinking-block", "block", "blinking-underline", "underline", | ||||||
|  | 	"blinking-bar", "bar", NULL | ||||||
|  | }; | ||||||
| static const char *options_table_pane_status_list[] = { | static const char *options_table_pane_status_list[] = { | ||||||
| 	"off", "top", "bottom", NULL | 	"off", "top", "bottom", NULL | ||||||
| }; | }; | ||||||
| static const char *options_table_pane_lines_list[] = { | static const char *options_table_pane_border_lines_list[] = { | ||||||
| 	"single", "double", "heavy", "simple", "number", NULL | 	"single", "double", "heavy", "simple", "number", NULL | ||||||
| }; | }; | ||||||
|  | static const char *options_table_popup_border_lines_list[] = { | ||||||
|  | 	"single", "double", "heavy", "simple", "rounded", "padded", "none", NULL | ||||||
|  | }; | ||||||
| static const char *options_table_set_clipboard_list[] = { | static const char *options_table_set_clipboard_list[] = { | ||||||
| 	"off", "external", "on", NULL | 	"off", "external", "on", NULL | ||||||
| }; | }; | ||||||
| @@ -184,6 +191,7 @@ const struct options_name_map options_other_names[] = { | |||||||
| 	{ "display-panes-color", "display-panes-colour" }, | 	{ "display-panes-color", "display-panes-colour" }, | ||||||
| 	{ "display-panes-active-color", "display-panes-active-colour" }, | 	{ "display-panes-active-color", "display-panes-active-colour" }, | ||||||
| 	{ "clock-mode-color", "clock-mode-colour" }, | 	{ "clock-mode-color", "clock-mode-colour" }, | ||||||
|  | 	{ "cursor-color", "cursor-colour" }, | ||||||
| 	{ "pane-colors", "pane-colours" }, | 	{ "pane-colors", "pane-colours" }, | ||||||
| 	{ NULL, NULL } | 	{ NULL, NULL } | ||||||
| }; | }; | ||||||
| @@ -231,6 +239,21 @@ const struct options_table_entry options_table[] = { | |||||||
| 		  "If empty, no command is run." | 		  "If empty, no command is run." | ||||||
| 	}, | 	}, | ||||||
|  |  | ||||||
|  | 	{ .name = "cursor-colour", | ||||||
|  | 	  .type = OPTIONS_TABLE_COLOUR, | ||||||
|  | 	  .scope = OPTIONS_TABLE_WINDOW|OPTIONS_TABLE_PANE, | ||||||
|  | 	  .default_num = -1, | ||||||
|  | 	  .text = "Colour of the cursor." | ||||||
|  | 	}, | ||||||
|  |  | ||||||
|  | 	{ .name = "cursor-style", | ||||||
|  | 	  .type = OPTIONS_TABLE_CHOICE, | ||||||
|  | 	  .scope = OPTIONS_TABLE_WINDOW|OPTIONS_TABLE_PANE, | ||||||
|  | 	  .choices = options_table_cursor_style_list, | ||||||
|  | 	  .default_num = 0, | ||||||
|  | 	  .text = "Style of the cursor." | ||||||
|  | 	}, | ||||||
|  |  | ||||||
| 	{ .name = "default-terminal", | 	{ .name = "default-terminal", | ||||||
| 	  .type = OPTIONS_TABLE_STRING, | 	  .type = OPTIONS_TABLE_STRING, | ||||||
| 	  .scope = OPTIONS_TABLE_SERVER, | 	  .scope = OPTIONS_TABLE_SERVER, | ||||||
| @@ -950,7 +973,7 @@ const struct options_table_entry options_table[] = { | |||||||
| 	{ .name = "pane-border-lines", | 	{ .name = "pane-border-lines", | ||||||
| 	  .type = OPTIONS_TABLE_CHOICE, | 	  .type = OPTIONS_TABLE_CHOICE, | ||||||
| 	  .scope = OPTIONS_TABLE_WINDOW, | 	  .scope = OPTIONS_TABLE_WINDOW, | ||||||
| 	  .choices = options_table_pane_lines_list, | 	  .choices = options_table_pane_border_lines_list, | ||||||
| 	  .default_num = PANE_LINES_SINGLE, | 	  .default_num = PANE_LINES_SINGLE, | ||||||
| 	  .text = "Type of characters used to draw pane border lines. Some of " | 	  .text = "Type of characters used to draw pane border lines. Some of " | ||||||
| 	          "these are only supported on terminals with UTF-8 support." | 	          "these are only supported on terminals with UTF-8 support." | ||||||
| @@ -981,6 +1004,33 @@ const struct options_table_entry options_table[] = { | |||||||
| 	  .text = "The default colour palette for colours zero to 255." | 	  .text = "The default colour palette for colours zero to 255." | ||||||
| 	}, | 	}, | ||||||
|  |  | ||||||
|  | 	{ .name = "popup-style", | ||||||
|  | 	  .type = OPTIONS_TABLE_STRING, | ||||||
|  | 	  .scope = OPTIONS_TABLE_WINDOW, | ||||||
|  | 	  .default_str = "default", | ||||||
|  | 	  .flags = OPTIONS_TABLE_IS_STYLE, | ||||||
|  | 	  .separator = ",", | ||||||
|  | 	  .text = "Default style of popups." | ||||||
|  | 	}, | ||||||
|  |  | ||||||
|  | 	{ .name = "popup-border-style", | ||||||
|  | 	  .type = OPTIONS_TABLE_STRING, | ||||||
|  | 	  .scope = OPTIONS_TABLE_WINDOW, | ||||||
|  | 	  .default_str = "default", | ||||||
|  | 	  .flags = OPTIONS_TABLE_IS_STYLE, | ||||||
|  | 	  .separator = ",", | ||||||
|  | 	  .text = "Default style of popup borders." | ||||||
|  | 	}, | ||||||
|  |  | ||||||
|  | 	{ .name = "popup-border-lines", | ||||||
|  | 	  .type = OPTIONS_TABLE_CHOICE, | ||||||
|  | 	  .scope = OPTIONS_TABLE_WINDOW, | ||||||
|  | 	  .choices = options_table_popup_border_lines_list, | ||||||
|  | 	  .default_num = BOX_LINES_SINGLE, | ||||||
|  | 	  .text = "Type of characters used to draw popup border lines. Some of " | ||||||
|  | 	          "these are only supported on terminals with UTF-8 support." | ||||||
|  | 	}, | ||||||
|  |  | ||||||
| 	{ .name = "remain-on-exit", | 	{ .name = "remain-on-exit", | ||||||
| 	  .type = OPTIONS_TABLE_CHOICE, | 	  .type = OPTIONS_TABLE_CHOICE, | ||||||
| 	  .scope = OPTIONS_TABLE_WINDOW|OPTIONS_TABLE_PANE, | 	  .scope = OPTIONS_TABLE_WINDOW|OPTIONS_TABLE_PANE, | ||||||
|   | |||||||
							
								
								
									
										50
									
								
								options.c
									
									
									
									
									
								
							
							
						
						
									
										50
									
								
								options.c
									
									
									
									
									
								
							| @@ -989,28 +989,39 @@ options_from_string_flag(struct options *oo, const char *name, | |||||||
| 	return (0); | 	return (0); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | int | ||||||
|  | options_find_choice(const struct options_table_entry *oe, const char *value, | ||||||
|  |     char **cause) | ||||||
|  | { | ||||||
|  | 	const char	**cp; | ||||||
|  | 	int		  n = 0, choice = -1; | ||||||
|  |  | ||||||
|  | 	for (cp = oe->choices; *cp != NULL; cp++) { | ||||||
|  | 		if (strcmp(*cp, value) == 0) | ||||||
|  | 			choice = n; | ||||||
|  | 		n++; | ||||||
|  | 	} | ||||||
|  | 	if (choice == -1) { | ||||||
|  | 		xasprintf(cause, "unknown value: %s", value); | ||||||
|  | 		return (-1); | ||||||
|  | 	} | ||||||
|  | 	return (choice); | ||||||
|  | } | ||||||
|  |  | ||||||
| static int | static int | ||||||
| options_from_string_choice(const struct options_table_entry *oe, | options_from_string_choice(const struct options_table_entry *oe, | ||||||
|     struct options *oo, const char *name, const char *value, char **cause) |     struct options *oo, const char *name, const char *value, char **cause) | ||||||
| { | { | ||||||
| 	const char	**cp; | 	int	choice = -1; | ||||||
| 	int		  n, choice = -1; |  | ||||||
|  |  | ||||||
| 	if (value == NULL) { | 	if (value == NULL) { | ||||||
| 		choice = options_get_number(oo, name); | 		choice = options_get_number(oo, name); | ||||||
| 		if (choice < 2) | 		if (choice < 2) | ||||||
| 			choice = !choice; | 			choice = !choice; | ||||||
| 	} else { | 	} else { | ||||||
| 		n = 0; | 		choice = options_find_choice(oe, value, cause); | ||||||
| 		for (cp = oe->choices; *cp != NULL; cp++) { | 		if (choice < 0) | ||||||
| 			if (strcmp(*cp, value) == 0) |  | ||||||
| 				choice = n; |  | ||||||
| 			n++; |  | ||||||
| 		} |  | ||||||
| 		if (choice == -1) { |  | ||||||
| 			xasprintf(cause, "unknown value: %s", value); |  | ||||||
| 			return (-1); | 			return (-1); | ||||||
| 		} |  | ||||||
| 	} | 	} | ||||||
| 	options_set_number(oo, name, choice); | 	options_set_number(oo, name, choice); | ||||||
| 	return (0); | 	return (0); | ||||||
| @@ -1095,15 +1106,30 @@ options_push_changes(const char *name) | |||||||
| 	struct session		*s; | 	struct session		*s; | ||||||
| 	struct window		*w; | 	struct window		*w; | ||||||
| 	struct window_pane	*wp; | 	struct window_pane	*wp; | ||||||
|  | 	int			 c; | ||||||
|  |  | ||||||
| 	if (strcmp(name, "automatic-rename") == 0) { | 	if (strcmp(name, "automatic-rename") == 0) { | ||||||
| 		RB_FOREACH(w, windows, &windows) { | 		RB_FOREACH(w, windows, &windows) { | ||||||
| 			if (w->active == NULL) | 			if (w->active == NULL) | ||||||
| 				continue; | 				continue; | ||||||
| 			if (options_get_number(w->options, "automatic-rename")) | 			if (options_get_number(w->options, name)) | ||||||
| 				w->active->flags |= PANE_CHANGED; | 				w->active->flags |= PANE_CHANGED; | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  | 	if (strcmp(name, "cursor-colour") == 0) { | ||||||
|  | 		RB_FOREACH(wp, window_pane_tree, &all_window_panes) { | ||||||
|  | 			c = options_get_number(wp->options, name); | ||||||
|  | 			wp->screen->default_ccolour = c; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	if (strcmp(name, "cursor-style") == 0) { | ||||||
|  | 		RB_FOREACH(wp, window_pane_tree, &all_window_panes) { | ||||||
|  | 			wp->screen->default_mode = 0; | ||||||
|  | 			screen_set_cursor_style(options_get_number(wp->options, | ||||||
|  | 			    name), &wp->screen->default_cstyle, | ||||||
|  | 			    &wp->screen->default_mode); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
| 	if (strcmp(name, "key-table") == 0) { | 	if (strcmp(name, "key-table") == 0) { | ||||||
| 		TAILQ_FOREACH(loop, &clients, entry) | 		TAILQ_FOREACH(loop, &clients, entry) | ||||||
| 			server_client_set_key_table(loop, NULL); | 			server_client_set_key_table(loop, NULL); | ||||||
|   | |||||||
| @@ -18,6 +18,7 @@ | |||||||
|  |  | ||||||
| #include <sys/param.h>	/* MAXCOMLEN */ | #include <sys/param.h>	/* MAXCOMLEN */ | ||||||
| #include <sys/types.h> | #include <sys/types.h> | ||||||
|  | #include <sys/signal.h> | ||||||
| #include <sys/proc.h> | #include <sys/proc.h> | ||||||
| #include <sys/sysctl.h> | #include <sys/sysctl.h> | ||||||
| #include <sys/stat.h> | #include <sys/stat.h> | ||||||
|   | |||||||
							
								
								
									
										142
									
								
								popup.c
									
									
									
									
									
								
							
							
						
						
									
										142
									
								
								popup.c
									
									
									
									
									
								
							| @@ -30,9 +30,15 @@ struct popup_data { | |||||||
| 	struct client		 *c; | 	struct client		 *c; | ||||||
| 	struct cmdq_item	 *item; | 	struct cmdq_item	 *item; | ||||||
| 	int			  flags; | 	int			  flags; | ||||||
|  | 	char			 *title; | ||||||
|  |  | ||||||
|  | 	struct grid_cell	  border_cell; | ||||||
|  | 	enum box_lines		  border_lines; | ||||||
|  |  | ||||||
| 	struct screen		  s; | 	struct screen		  s; | ||||||
|  | 	struct grid_cell	  defaults; | ||||||
| 	struct colour_palette	  palette; | 	struct colour_palette	  palette; | ||||||
|  |  | ||||||
| 	struct job		 *job; | 	struct job		 *job; | ||||||
| 	struct input_ctx	 *ictx; | 	struct input_ctx	 *ictx; | ||||||
| 	int			  status; | 	int			  status; | ||||||
| @@ -116,7 +122,7 @@ popup_set_client_cb(struct tty_ctx *ttyctx, struct client *c) | |||||||
| 	ttyctx->wsx = c->tty.sx; | 	ttyctx->wsx = c->tty.sx; | ||||||
| 	ttyctx->wsy = c->tty.sy; | 	ttyctx->wsy = c->tty.sy; | ||||||
|  |  | ||||||
| 	if (pd->flags & POPUP_NOBORDER) { | 	if (pd->border_lines == BOX_LINES_NONE) { | ||||||
| 		ttyctx->xoff = ttyctx->rxoff = pd->px; | 		ttyctx->xoff = ttyctx->rxoff = pd->px; | ||||||
| 		ttyctx->yoff = ttyctx->ryoff = pd->py; | 		ttyctx->yoff = ttyctx->ryoff = pd->py; | ||||||
| 	} else { | 	} else { | ||||||
| @@ -132,6 +138,7 @@ popup_init_ctx_cb(struct screen_write_ctx *ctx, struct tty_ctx *ttyctx) | |||||||
| { | { | ||||||
| 	struct popup_data	*pd = ctx->arg; | 	struct popup_data	*pd = ctx->arg; | ||||||
|  |  | ||||||
|  | 	memcpy(&ttyctx->defaults, &pd->defaults, sizeof ttyctx->defaults); | ||||||
| 	ttyctx->palette = &pd->palette; | 	ttyctx->palette = &pd->palette; | ||||||
| 	ttyctx->redraw_cb = popup_redraw_cb; | 	ttyctx->redraw_cb = popup_redraw_cb; | ||||||
| 	ttyctx->set_client_cb = popup_set_client_cb; | 	ttyctx->set_client_cb = popup_set_client_cb; | ||||||
| @@ -146,7 +153,7 @@ popup_mode_cb(__unused struct client *c, void *data, u_int *cx, u_int *cy) | |||||||
| 	if (pd->md != NULL) | 	if (pd->md != NULL) | ||||||
| 		return (menu_mode_cb(c, pd->md, cx, cy)); | 		return (menu_mode_cb(c, pd->md, cx, cy)); | ||||||
|  |  | ||||||
| 	if (pd->flags & POPUP_NOBORDER) { | 	if (pd->border_lines == BOX_LINES_NONE) { | ||||||
| 		*cx = pd->px + pd->s.cx; | 		*cx = pd->px + pd->s.cx; | ||||||
| 		*cy = pd->py + pd->s.cy; | 		*cy = pd->py + pd->s.cy; | ||||||
| 	} else { | 	} else { | ||||||
| @@ -156,18 +163,49 @@ popup_mode_cb(__unused struct client *c, void *data, u_int *cx, u_int *cy) | |||||||
| 	return (&pd->s); | 	return (&pd->s); | ||||||
| } | } | ||||||
|  |  | ||||||
| static int | /* Return parts of the input range which are not obstructed by the popup. */ | ||||||
| popup_check_cb(struct client *c, void *data, u_int px, u_int py) | static void | ||||||
|  | popup_check_cb(struct client* c, void *data, u_int px, u_int py, u_int nx, | ||||||
|  |     struct overlay_ranges *r) | ||||||
| { | { | ||||||
| 	struct popup_data	*pd = data; | 	struct popup_data	*pd = data; | ||||||
|  | 	struct overlay_ranges	 or[2]; | ||||||
|  | 	u_int			 i, j, k = 0; | ||||||
|  |  | ||||||
| 	if (pd->md != NULL && menu_check_cb(c, pd->md, px, py) == 0) | 	if (pd->md != NULL) { | ||||||
| 		return (0); | 		/* Check each returned range for the menu against the popup. */ | ||||||
| 	if (px < pd->px || px > pd->px + pd->sx - 1) | 		menu_check_cb(c, pd->md, px, py, nx, r); | ||||||
| 		return (1); | 		for (i = 0; i < 2; i++) { | ||||||
| 	if (py < pd->py || py > pd->py + pd->sy - 1) | 			server_client_overlay_range(pd->px, pd->py, pd->sx, | ||||||
| 		return (1); | 			    pd->sy, r->px[i], py, r->nx[i], &or[i]); | ||||||
| 	return (0); | 		} | ||||||
|  |  | ||||||
|  | 		/* | ||||||
|  | 		 * or has up to OVERLAY_MAX_RANGES non-overlapping ranges, | ||||||
|  | 		 * ordered from left to right. Collect them in the output. | ||||||
|  | 		 */ | ||||||
|  | 		for (i = 0; i < 2; i++) { | ||||||
|  | 			/* Each or[i] only has 2 ranges. */ | ||||||
|  | 			for (j = 0; j < 2; j++) { | ||||||
|  | 				if (or[i].nx[j] > 0) { | ||||||
|  | 					r->px[k] = or[i].px[j]; | ||||||
|  | 					r->nx[k] = or[i].nx[j]; | ||||||
|  | 					k++; | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		/* Zero remaining ranges if any. */ | ||||||
|  | 		for (i = k; i < OVERLAY_MAX_RANGES; i++) { | ||||||
|  | 			r->px[i] = 0; | ||||||
|  | 			r->nx[i] = 0; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	server_client_overlay_range(pd->px, pd->py, pd->sx, pd->sy, px, py, nx, | ||||||
|  | 	    r); | ||||||
| } | } | ||||||
|  |  | ||||||
| static void | static void | ||||||
| @@ -179,26 +217,29 @@ popup_draw_cb(struct client *c, void *data, struct screen_redraw_ctx *rctx) | |||||||
| 	struct screen_write_ctx	 ctx; | 	struct screen_write_ctx	 ctx; | ||||||
| 	u_int			 i, px = pd->px, py = pd->py; | 	u_int			 i, px = pd->px, py = pd->py; | ||||||
| 	struct colour_palette	*palette = &pd->palette; | 	struct colour_palette	*palette = &pd->palette; | ||||||
| 	struct grid_cell	 gc; | 	struct grid_cell	 defaults; | ||||||
|  |  | ||||||
| 	screen_init(&s, pd->sx, pd->sy, 0); | 	screen_init(&s, pd->sx, pd->sy, 0); | ||||||
| 	screen_write_start(&ctx, &s); | 	screen_write_start(&ctx, &s); | ||||||
| 	screen_write_clearscreen(&ctx, 8); | 	screen_write_clearscreen(&ctx, 8); | ||||||
|  |  | ||||||
| 	if (pd->flags & POPUP_NOBORDER) { | 	if (pd->border_lines == BOX_LINES_NONE) { | ||||||
| 		screen_write_cursormove(&ctx, 0, 0, 0); | 		screen_write_cursormove(&ctx, 0, 0, 0); | ||||||
| 		screen_write_fast_copy(&ctx, &pd->s, 0, 0, pd->sx, pd->sy); | 		screen_write_fast_copy(&ctx, &pd->s, 0, 0, pd->sx, pd->sy); | ||||||
| 	} else if (pd->sx > 2 && pd->sy > 2) { | 	} else if (pd->sx > 2 && pd->sy > 2) { | ||||||
| 		screen_write_box(&ctx, pd->sx, pd->sy); | 		screen_write_box(&ctx, pd->sx, pd->sy, pd->border_lines, | ||||||
|  | 		    &pd->border_cell, pd->title); | ||||||
| 		screen_write_cursormove(&ctx, 1, 1, 0); | 		screen_write_cursormove(&ctx, 1, 1, 0); | ||||||
| 		screen_write_fast_copy(&ctx, &pd->s, 0, 0, pd->sx - 2, | 		screen_write_fast_copy(&ctx, &pd->s, 0, 0, pd->sx - 2, | ||||||
| 		    pd->sy - 2); | 		    pd->sy - 2); | ||||||
| 	} | 	} | ||||||
| 	screen_write_stop(&ctx); | 	screen_write_stop(&ctx); | ||||||
|  |  | ||||||
| 	memcpy(&gc, &grid_default_cell, sizeof gc); | 	memcpy(&defaults, &pd->defaults, sizeof defaults); | ||||||
| 	gc.fg = pd->palette.fg; | 	if (defaults.fg == 8) | ||||||
| 	gc.bg = pd->palette.bg; | 		defaults.fg = palette->fg; | ||||||
|  | 	if (defaults.bg == 8) | ||||||
|  | 		defaults.bg = palette->bg; | ||||||
|  |  | ||||||
| 	if (pd->md != NULL) { | 	if (pd->md != NULL) { | ||||||
| 		c->overlay_check = menu_check_cb; | 		c->overlay_check = menu_check_cb; | ||||||
| @@ -207,8 +248,10 @@ popup_draw_cb(struct client *c, void *data, struct screen_redraw_ctx *rctx) | |||||||
| 		c->overlay_check = NULL; | 		c->overlay_check = NULL; | ||||||
| 		c->overlay_data = NULL; | 		c->overlay_data = NULL; | ||||||
| 	} | 	} | ||||||
| 	for (i = 0; i < pd->sy; i++) | 	for (i = 0; i < pd->sy; i++) { | ||||||
| 		tty_draw_line(tty, &s, 0, i, pd->sx, px, py + i, &gc, palette); | 		tty_draw_line(tty, &s, 0, i, pd->sx, px, py + i, &defaults, | ||||||
|  | 		    palette); | ||||||
|  | 	} | ||||||
| 	if (pd->md != NULL) { | 	if (pd->md != NULL) { | ||||||
| 		c->overlay_check = NULL; | 		c->overlay_check = NULL; | ||||||
| 		c->overlay_data = NULL; | 		c->overlay_data = NULL; | ||||||
| @@ -245,6 +288,7 @@ popup_free_cb(struct client *c, void *data) | |||||||
| 	screen_free(&pd->s); | 	screen_free(&pd->s); | ||||||
| 	colour_palette_free(&pd->palette); | 	colour_palette_free(&pd->palette); | ||||||
|  |  | ||||||
|  | 	free(pd->title); | ||||||
| 	free(pd); | 	free(pd); | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -278,7 +322,7 @@ popup_resize_cb(__unused struct client *c, void *data) | |||||||
| 		pd->px = pd->ppx; | 		pd->px = pd->ppx; | ||||||
|  |  | ||||||
| 	/* Avoid zero size screens. */ | 	/* Avoid zero size screens. */ | ||||||
| 	if (pd->flags & POPUP_NOBORDER) { | 	if (pd->border_lines == BOX_LINES_NONE) { | ||||||
| 		screen_resize(&pd->s, pd->sx, pd->sy, 0); | 		screen_resize(&pd->s, pd->sx, pd->sy, 0); | ||||||
| 		if (pd->job != NULL) | 		if (pd->job != NULL) | ||||||
| 			job_resize(pd->job, pd->sx, pd->sy ); | 			job_resize(pd->job, pd->sx, pd->sy ); | ||||||
| @@ -404,7 +448,7 @@ popup_handle_drag(struct client *c, struct popup_data *pd, | |||||||
| 		pd->ppy = py; | 		pd->ppy = py; | ||||||
| 		server_redraw_client(c); | 		server_redraw_client(c); | ||||||
| 	} else if (pd->dragging == SIZE) { | 	} else if (pd->dragging == SIZE) { | ||||||
| 		if (pd->flags & POPUP_NOBORDER) { | 		if (pd->border_lines == BOX_LINES_NONE) { | ||||||
| 			if (m->x < pd->px + 1) | 			if (m->x < pd->px + 1) | ||||||
| 				return; | 				return; | ||||||
| 			if (m->y < pd->py + 1) | 			if (m->y < pd->py + 1) | ||||||
| @@ -420,7 +464,7 @@ popup_handle_drag(struct client *c, struct popup_data *pd, | |||||||
| 		pd->psx = pd->sx; | 		pd->psx = pd->sx; | ||||||
| 		pd->psy = pd->sy; | 		pd->psy = pd->sy; | ||||||
|  |  | ||||||
| 		if (pd->flags & POPUP_NOBORDER) { | 		if (pd->border_lines == BOX_LINES_NONE) { | ||||||
| 			screen_resize(&pd->s, pd->sx, pd->sy, 0); | 			screen_resize(&pd->s, pd->sx, pd->sy, 0); | ||||||
| 			if (pd->job != NULL) | 			if (pd->job != NULL) | ||||||
| 				job_resize(pd->job, pd->sx, pd->sy); | 				job_resize(pd->job, pd->sx, pd->sy); | ||||||
| @@ -468,7 +512,7 @@ popup_key_cb(struct client *c, void *data, struct key_event *event) | |||||||
| 				goto menu; | 				goto menu; | ||||||
| 			return (0); | 			return (0); | ||||||
| 		} | 		} | ||||||
| 		if (~pd->flags & POPUP_NOBORDER) { | 		if (pd->border_lines != BOX_LINES_NONE) { | ||||||
| 			if (m->x == pd->px) | 			if (m->x == pd->px) | ||||||
| 				border = LEFT; | 				border = LEFT; | ||||||
| 			else if (m->x == pd->px + pd->sx - 1) | 			else if (m->x == pd->px + pd->sx - 1) | ||||||
| @@ -502,7 +546,7 @@ popup_key_cb(struct client *c, void *data, struct key_event *event) | |||||||
| 	if (pd->job != NULL) { | 	if (pd->job != NULL) { | ||||||
| 		if (KEYC_IS_MOUSE(event->key)) { | 		if (KEYC_IS_MOUSE(event->key)) { | ||||||
| 			/* Must be inside, checked already. */ | 			/* Must be inside, checked already. */ | ||||||
| 			if (pd->flags & POPUP_NOBORDER) { | 			if (pd->border_lines == BOX_LINES_NONE) { | ||||||
| 				px = m->x - pd->px; | 				px = m->x - pd->px; | ||||||
| 				py = m->y - pd->py; | 				py = m->y - pd->py; | ||||||
| 			} else { | 			} else { | ||||||
| @@ -588,14 +632,25 @@ popup_job_complete_cb(struct job *job) | |||||||
| } | } | ||||||
|  |  | ||||||
| int | int | ||||||
| popup_display(int flags, struct cmdq_item *item, u_int px, u_int py, u_int sx, | popup_display(int flags, enum box_lines lines, struct cmdq_item *item, u_int px, | ||||||
|     u_int sy, const char *shellcmd, int argc, char **argv, const char *cwd, |     u_int py, u_int sx, u_int sy, struct environ *env, const char *shellcmd, | ||||||
|     struct client *c, struct session *s, popup_close_cb cb, void *arg) |     int argc, char **argv, const char *cwd, const char *title, struct client *c, | ||||||
|  |     struct session *s, const char* style, const char* border_style, | ||||||
|  |     popup_close_cb cb, void *arg) | ||||||
| { | { | ||||||
| 	struct popup_data	*pd; | 	struct popup_data	*pd; | ||||||
| 	u_int			 jx, jy; | 	u_int			 jx, jy; | ||||||
|  | 	struct options		*o; | ||||||
|  | 	struct style		 sytmp; | ||||||
|  |  | ||||||
| 	if (flags & POPUP_NOBORDER) { | 	if (s != NULL) | ||||||
|  | 		o = s->curw->window->options; | ||||||
|  | 	else | ||||||
|  | 		o = c->session->curw->window->options; | ||||||
|  |  | ||||||
|  | 	if (lines == BOX_LINES_DEFAULT) | ||||||
|  | 		lines = options_get_number(o, "popup-border-lines"); | ||||||
|  | 	if (lines == BOX_LINES_NONE) { | ||||||
| 		if (sx < 1 || sy < 1) | 		if (sx < 1 || sy < 1) | ||||||
| 			return (-1); | 			return (-1); | ||||||
| 		jx = sx; | 		jx = sx; | ||||||
| @@ -612,6 +667,7 @@ popup_display(int flags, struct cmdq_item *item, u_int px, u_int py, u_int sx, | |||||||
| 	pd = xcalloc(1, sizeof *pd); | 	pd = xcalloc(1, sizeof *pd); | ||||||
| 	pd->item = item; | 	pd->item = item; | ||||||
| 	pd->flags = flags; | 	pd->flags = flags; | ||||||
|  | 	pd->title = xstrdup(title); | ||||||
|  |  | ||||||
| 	pd->c = c; | 	pd->c = c; | ||||||
| 	pd->c->references++; | 	pd->c->references++; | ||||||
| @@ -620,10 +676,33 @@ popup_display(int flags, struct cmdq_item *item, u_int px, u_int py, u_int sx, | |||||||
| 	pd->arg = arg; | 	pd->arg = arg; | ||||||
| 	pd->status = 128 + SIGHUP; | 	pd->status = 128 + SIGHUP; | ||||||
|  |  | ||||||
|  | 	pd->border_lines = lines; | ||||||
|  | 	memcpy(&pd->border_cell, &grid_default_cell, sizeof pd->border_cell); | ||||||
|  | 	style_apply(&pd->border_cell, o, "popup-border-style", NULL); | ||||||
|  | 	if (border_style != NULL) { | ||||||
|  | 		style_set(&sytmp, &grid_default_cell); | ||||||
|  | 		if (style_parse(&sytmp, &pd->border_cell, border_style) == 0) { | ||||||
|  | 			pd->border_cell.fg = sytmp.gc.fg; | ||||||
|  | 			pd->border_cell.bg = sytmp.gc.bg; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	pd->border_cell.attr = 0; | ||||||
|  |  | ||||||
| 	screen_init(&pd->s, sx - 2, sy - 2, 0); | 	screen_init(&pd->s, sx - 2, sy - 2, 0); | ||||||
| 	colour_palette_init(&pd->palette); | 	colour_palette_init(&pd->palette); | ||||||
| 	colour_palette_from_option(&pd->palette, global_w_options); | 	colour_palette_from_option(&pd->palette, global_w_options); | ||||||
|  |  | ||||||
|  | 	memcpy(&pd->defaults, &grid_default_cell, sizeof pd->defaults); | ||||||
|  | 	style_apply(&pd->defaults, o, "popup-style", NULL); | ||||||
|  | 	if (style != NULL) { | ||||||
|  | 		style_set(&sytmp, &grid_default_cell); | ||||||
|  | 		if (style_parse(&sytmp, &pd->defaults, style) == 0) { | ||||||
|  | 			pd->defaults.fg = sytmp.gc.fg; | ||||||
|  | 			pd->defaults.bg = sytmp.gc.bg; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	pd->defaults.attr = 0; | ||||||
|  |  | ||||||
| 	pd->px = px; | 	pd->px = px; | ||||||
| 	pd->py = py; | 	pd->py = py; | ||||||
| 	pd->sx = sx; | 	pd->sx = sx; | ||||||
| @@ -634,7 +713,7 @@ popup_display(int flags, struct cmdq_item *item, u_int px, u_int py, u_int sx, | |||||||
| 	pd->psx = sx; | 	pd->psx = sx; | ||||||
| 	pd->psy = sy; | 	pd->psy = sy; | ||||||
|  |  | ||||||
| 	pd->job = job_run(shellcmd, argc, argv, s, cwd, | 	pd->job = job_run(shellcmd, argc, argv, env, s, cwd, | ||||||
| 	    popup_job_update_cb, popup_job_complete_cb, NULL, pd, | 	    popup_job_update_cb, popup_job_complete_cb, NULL, pd, | ||||||
| 	    JOB_NOWAIT|JOB_PTY|JOB_KEEPWRITE, jx, jy); | 	    JOB_NOWAIT|JOB_PTY|JOB_KEEPWRITE, jx, jy); | ||||||
| 	pd->ictx = input_init(NULL, job_get_event(pd->job), &pd->palette); | 	pd->ictx = input_init(NULL, job_get_event(pd->job), &pd->palette); | ||||||
| @@ -723,8 +802,9 @@ popup_editor(struct client *c, const char *buf, size_t len, | |||||||
| 	py = (c->tty.sy / 2) - (sy / 2); | 	py = (c->tty.sy / 2) - (sy / 2); | ||||||
|  |  | ||||||
| 	xasprintf(&cmd, "%s %s", editor, path); | 	xasprintf(&cmd, "%s %s", editor, path); | ||||||
| 	if (popup_display(POPUP_INTERNAL|POPUP_CLOSEEXIT, NULL, px, py, sx, sy, | 	if (popup_display(POPUP_INTERNAL|POPUP_CLOSEEXIT, BOX_LINES_DEFAULT, | ||||||
| 	    cmd, 0, NULL, _PATH_TMP, c, NULL, popup_editor_close_cb, pe) != 0) { | 	    NULL, px, py, sx, sy, NULL, cmd, 0, NULL, _PATH_TMP, NULL, c, NULL, | ||||||
|  | 	    NULL, NULL, popup_editor_close_cb, pe) != 0) { | ||||||
| 		popup_editor_free(pe); | 		popup_editor_free(pe); | ||||||
| 		free(cmd); | 		free(cmd); | ||||||
| 		return (-1); | 		return (-1); | ||||||
|   | |||||||
							
								
								
									
										2
									
								
								resize.c
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								resize.c
									
									
									
									
									
								
							| @@ -348,6 +348,8 @@ recalculate_size_skip_client(struct client *loop, __unused int type, | |||||||
| 	 * is not the current window - this is used for aggressive-resize. | 	 * is not the current window - this is used for aggressive-resize. | ||||||
| 	 * Otherwise skip any session that doesn't contain the window. | 	 * Otherwise skip any session that doesn't contain the window. | ||||||
| 	 */ | 	 */ | ||||||
|  | 	if (loop->session->curw == NULL) | ||||||
|  | 		return (1); | ||||||
| 	if (current) | 	if (current) | ||||||
| 		return (loop->session->curw->window != w); | 		return (loop->session->curw->window != w); | ||||||
| 	return (session_has(loop->session, w) == 0); | 	return (session_has(loop->session, w) == 0); | ||||||
|   | |||||||
| @@ -31,57 +31,9 @@ static void	screen_redraw_draw_pane(struct screen_redraw_ctx *, | |||||||
| static void	screen_redraw_set_context(struct client *, | static void	screen_redraw_set_context(struct client *, | ||||||
| 		    struct screen_redraw_ctx *); | 		    struct screen_redraw_ctx *); | ||||||
|  |  | ||||||
| #define CELL_INSIDE 0 |  | ||||||
| #define CELL_TOPBOTTOM 1 |  | ||||||
| #define CELL_LEFTRIGHT 2 |  | ||||||
| #define CELL_TOPLEFT 3 |  | ||||||
| #define CELL_TOPRIGHT 4 |  | ||||||
| #define CELL_BOTTOMLEFT 5 |  | ||||||
| #define CELL_BOTTOMRIGHT 6 |  | ||||||
| #define CELL_TOPJOIN 7 |  | ||||||
| #define CELL_BOTTOMJOIN 8 |  | ||||||
| #define CELL_LEFTJOIN 9 |  | ||||||
| #define CELL_RIGHTJOIN 10 |  | ||||||
| #define CELL_JOIN 11 |  | ||||||
| #define CELL_OUTSIDE 12 |  | ||||||
|  |  | ||||||
| #define CELL_BORDERS " xqlkmjwvtun~" |  | ||||||
|  |  | ||||||
| #define START_ISOLATE "\342\201\246" | #define START_ISOLATE "\342\201\246" | ||||||
| #define END_ISOLATE   "\342\201\251" | #define END_ISOLATE   "\342\201\251" | ||||||
|  |  | ||||||
| static const struct utf8_data screen_redraw_double_borders[] = { |  | ||||||
| 	{ "", 0, 0, 0 }, |  | ||||||
| 	{ "\342\225\221", 0, 3, 1 }, /* U+2551 */ |  | ||||||
| 	{ "\342\225\220", 0, 3, 1 }, /* U+2550 */ |  | ||||||
| 	{ "\342\225\224", 0, 3, 1 }, /* U+2554 */ |  | ||||||
| 	{ "\342\225\227", 0, 3, 1 }, /* U+2557 */ |  | ||||||
| 	{ "\342\225\232", 0, 3, 1 }, /* U+255A */ |  | ||||||
| 	{ "\342\225\235", 0, 3, 1 }, /* U+255D */ |  | ||||||
| 	{ "\342\225\246", 0, 3, 1 }, /* U+2566 */ |  | ||||||
| 	{ "\342\225\251", 0, 3, 1 }, /* U+2569 */ |  | ||||||
| 	{ "\342\225\240", 0, 3, 1 }, /* U+2560 */ |  | ||||||
| 	{ "\342\225\243", 0, 3, 1 }, /* U+2563 */ |  | ||||||
| 	{ "\342\225\254", 0, 3, 1 }, /* U+256C */ |  | ||||||
| 	{ "\302\267",     0, 2, 1 }  /* U+00B7 */ |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| static const struct utf8_data screen_redraw_heavy_borders[] = { |  | ||||||
| 	{ "", 0, 0, 0 }, |  | ||||||
| 	{ "\342\224\203", 0, 3, 1 }, /* U+2503 */ |  | ||||||
| 	{ "\342\224\201", 0, 3, 1 }, /* U+2501 */ |  | ||||||
| 	{ "\342\224\223", 0, 3, 1 }, /* U+2513 */ |  | ||||||
| 	{ "\342\224\217", 0, 3, 1 }, /* U+250F */ |  | ||||||
| 	{ "\342\224\227", 0, 3, 1 }, /* U+2517 */ |  | ||||||
| 	{ "\342\224\233", 0, 3, 1 }, /* U+251B */ |  | ||||||
| 	{ "\342\224\263", 0, 3, 1 }, /* U+2533 */ |  | ||||||
| 	{ "\342\224\273", 0, 3, 1 }, /* U+253B */ |  | ||||||
| 	{ "\342\224\243", 0, 3, 1 }, /* U+2523 */ |  | ||||||
| 	{ "\342\224\253", 0, 3, 1 }, /* U+252B */ |  | ||||||
| 	{ "\342\225\213", 0, 3, 1 }, /* U+254B */ |  | ||||||
| 	{ "\302\267",     0, 2, 1 }  /* U+00B7 */ |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| enum screen_redraw_border_type { | enum screen_redraw_border_type { | ||||||
| 	SCREEN_REDRAW_OUTSIDE, | 	SCREEN_REDRAW_OUTSIDE, | ||||||
| 	SCREEN_REDRAW_INSIDE, | 	SCREEN_REDRAW_INSIDE, | ||||||
| @@ -90,8 +42,8 @@ enum screen_redraw_border_type { | |||||||
|  |  | ||||||
| /* Get cell border character. */ | /* Get cell border character. */ | ||||||
| static void | static void | ||||||
| screen_redraw_border_set(struct window_pane *wp, int pane_lines, int cell_type, | screen_redraw_border_set(struct window_pane *wp, enum pane_lines pane_lines, | ||||||
|     struct grid_cell *gc) |     int cell_type, struct grid_cell *gc) | ||||||
| { | { | ||||||
| 	u_int	idx; | 	u_int	idx; | ||||||
|  |  | ||||||
| @@ -110,15 +62,15 @@ screen_redraw_border_set(struct window_pane *wp, int pane_lines, int cell_type, | |||||||
| 		break; | 		break; | ||||||
| 	case PANE_LINES_DOUBLE: | 	case PANE_LINES_DOUBLE: | ||||||
| 		gc->attr &= ~GRID_ATTR_CHARSET; | 		gc->attr &= ~GRID_ATTR_CHARSET; | ||||||
| 		utf8_copy(&gc->data, &screen_redraw_double_borders[cell_type]); | 		utf8_copy(&gc->data, tty_acs_double_borders(cell_type)); | ||||||
| 		break; | 		break; | ||||||
| 	case PANE_LINES_HEAVY: | 	case PANE_LINES_HEAVY: | ||||||
| 		gc->attr &= ~GRID_ATTR_CHARSET; | 		gc->attr &= ~GRID_ATTR_CHARSET; | ||||||
| 		utf8_copy(&gc->data, &screen_redraw_heavy_borders[cell_type]); | 		utf8_copy(&gc->data, tty_acs_heavy_borders(cell_type)); | ||||||
| 		break; | 		break; | ||||||
| 	case PANE_LINES_SIMPLE: | 	case PANE_LINES_SIMPLE: | ||||||
| 		gc->attr &= ~GRID_ATTR_CHARSET; | 		gc->attr &= ~GRID_ATTR_CHARSET; | ||||||
| 		utf8_set(&gc->data, " |-+++++++++."[cell_type]); | 		utf8_set(&gc->data, SIMPLE_BORDERS[cell_type]); | ||||||
| 		break; | 		break; | ||||||
| 	default: | 	default: | ||||||
| 		gc->attr |= GRID_ATTR_CHARSET; | 		gc->attr |= GRID_ATTR_CHARSET; | ||||||
| @@ -402,7 +354,7 @@ screen_redraw_check_is(u_int px, u_int py, int pane_status, | |||||||
| /* Update pane status. */ | /* Update pane status. */ | ||||||
| static int | static int | ||||||
| screen_redraw_make_pane_status(struct client *c, struct window_pane *wp, | screen_redraw_make_pane_status(struct client *c, struct window_pane *wp, | ||||||
|     struct screen_redraw_ctx *rctx, int pane_lines) |     struct screen_redraw_ctx *rctx, enum pane_lines pane_lines) | ||||||
| { | { | ||||||
| 	struct window		*w = wp->window; | 	struct window		*w = wp->window; | ||||||
| 	struct grid_cell	 gc; | 	struct grid_cell	 gc; | ||||||
| @@ -448,7 +400,7 @@ screen_redraw_make_pane_status(struct client *c, struct window_pane *wp, | |||||||
| 	gc.attr &= ~GRID_ATTR_CHARSET; | 	gc.attr &= ~GRID_ATTR_CHARSET; | ||||||
|  |  | ||||||
| 	screen_write_cursormove(&ctx, 0, 0, 0); | 	screen_write_cursormove(&ctx, 0, 0, 0); | ||||||
| 	format_draw(&ctx, &gc, width, expanded, NULL); | 	format_draw(&ctx, &gc, width, expanded, NULL, 0); | ||||||
| 	screen_write_stop(&ctx); | 	screen_write_stop(&ctx); | ||||||
|  |  | ||||||
| 	free(expanded); | 	free(expanded); | ||||||
| @@ -527,11 +479,12 @@ screen_redraw_draw_pane_status(struct screen_redraw_ctx *ctx) | |||||||
| static int | static int | ||||||
| screen_redraw_update(struct client *c, int flags) | screen_redraw_update(struct client *c, int flags) | ||||||
| { | { | ||||||
| 	struct window		*w = c->session->curw->window; | 	struct window			*w = c->session->curw->window; | ||||||
| 	struct window_pane	*wp; | 	struct window_pane		*wp; | ||||||
| 	struct options		*wo = w->options; | 	struct options			*wo = w->options; | ||||||
| 	int			 redraw, lines; | 	int				 redraw; | ||||||
| 	struct screen_redraw_ctx ctx; | 	enum pane_lines			 lines; | ||||||
|  | 	struct screen_redraw_ctx	 ctx; | ||||||
|  |  | ||||||
| 	if (c->message_string != NULL) | 	if (c->message_string != NULL) | ||||||
| 		redraw = status_message_redraw(c); | 		redraw = status_message_redraw(c); | ||||||
| @@ -685,14 +638,17 @@ screen_redraw_draw_borders_cell(struct screen_redraw_ctx *ctx, u_int i, u_int j) | |||||||
| 	struct tty		*tty = &c->tty; | 	struct tty		*tty = &c->tty; | ||||||
| 	struct format_tree	*ft; | 	struct format_tree	*ft; | ||||||
| 	struct window_pane	*wp; | 	struct window_pane	*wp; | ||||||
| 	u_int			 cell_type, x = ctx->ox + i, y = ctx->oy + j; |  | ||||||
| 	int			 pane_status = ctx->pane_status, isolates; |  | ||||||
| 	struct grid_cell	 gc; | 	struct grid_cell	 gc; | ||||||
| 	const struct grid_cell	*tmp; | 	const struct grid_cell	*tmp; | ||||||
|  | 	struct overlay_ranges	 r; | ||||||
|  | 	u_int			 cell_type, x = ctx->ox + i, y = ctx->oy + j; | ||||||
|  | 	int			 pane_status = ctx->pane_status, isolates; | ||||||
|  |  | ||||||
| 	if (c->overlay_check != NULL && | 	if (c->overlay_check != NULL) { | ||||||
| 	    !c->overlay_check(c, c->overlay_data, x, y)) | 		c->overlay_check(c, c->overlay_data, x, y, 1, &r); | ||||||
| 		return; | 		if (r.nx[0] + r.nx[1] == 0) | ||||||
|  | 			return; | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	cell_type = screen_redraw_check_cell(c, x, y, pane_status, &wp); | 	cell_type = screen_redraw_check_cell(c, x, y, pane_status, &wp); | ||||||
| 	if (cell_type == CELL_INSIDE) | 	if (cell_type == CELL_INSIDE) | ||||||
|   | |||||||
| @@ -184,8 +184,10 @@ screen_write_initctx(struct screen_write_ctx *ctx, struct tty_ctx *ttyctx, | |||||||
| 	if (ctx->init_ctx_cb != NULL) { | 	if (ctx->init_ctx_cb != NULL) { | ||||||
| 		ctx->init_ctx_cb(ctx, ttyctx); | 		ctx->init_ctx_cb(ctx, ttyctx); | ||||||
| 		if (ttyctx->palette != NULL) { | 		if (ttyctx->palette != NULL) { | ||||||
| 			ttyctx->defaults.fg = ttyctx->palette->fg; | 			if (ttyctx->defaults.fg == 8) | ||||||
| 			ttyctx->defaults.bg = ttyctx->palette->bg; | 				ttyctx->defaults.fg = ttyctx->palette->fg; | ||||||
|  | 			if (ttyctx->defaults.bg == 8) | ||||||
|  | 				ttyctx->defaults.bg = ttyctx->palette->bg; | ||||||
| 		} | 		} | ||||||
| 	} else { | 	} else { | ||||||
| 		ttyctx->redraw_cb = screen_write_redraw_cb; | 		ttyctx->redraw_cb = screen_write_redraw_cb; | ||||||
| @@ -645,9 +647,8 @@ screen_write_menu(struct screen_write_ctx *ctx, struct menu *menu, | |||||||
|  |  | ||||||
| 	memcpy(&default_gc, &grid_default_cell, sizeof default_gc); | 	memcpy(&default_gc, &grid_default_cell, sizeof default_gc); | ||||||
|  |  | ||||||
| 	screen_write_box(ctx, menu->width + 4, menu->count + 2); | 	screen_write_box(ctx, menu->width + 4, menu->count + 2, | ||||||
| 	screen_write_cursormove(ctx, cx + 2, cy, 0); | 	    BOX_LINES_DEFAULT, &default_gc, menu->title); | ||||||
| 	format_draw(ctx, &default_gc, menu->width, menu->title, NULL); |  | ||||||
|  |  | ||||||
| 	for (i = 0; i < menu->count; i++) { | 	for (i = 0; i < menu->count; i++) { | ||||||
| 		name = menu->items[i].name; | 		name = menu->items[i].name; | ||||||
| @@ -664,10 +665,12 @@ screen_write_menu(struct screen_write_ctx *ctx, struct menu *menu, | |||||||
| 			if (*name == '-') { | 			if (*name == '-') { | ||||||
| 				name++; | 				name++; | ||||||
| 				default_gc.attr |= GRID_ATTR_DIM; | 				default_gc.attr |= GRID_ATTR_DIM; | ||||||
| 				format_draw(ctx, gc, menu->width, name, NULL); | 				format_draw(ctx, gc, menu->width, name, NULL, | ||||||
|  | 				    0); | ||||||
| 				default_gc.attr &= ~GRID_ATTR_DIM; | 				default_gc.attr &= ~GRID_ATTR_DIM; | ||||||
| 			} else | 			} else | ||||||
| 				format_draw(ctx, gc, menu->width, name, NULL); | 				format_draw(ctx, gc, menu->width, name, NULL, | ||||||
|  | 				    gc == choice_gc); | ||||||
| 			gc = &default_gc; | 			gc = &default_gc; | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| @@ -675,39 +678,95 @@ screen_write_menu(struct screen_write_ctx *ctx, struct menu *menu, | |||||||
| 	screen_write_set_cursor(ctx, cx, cy); | 	screen_write_set_cursor(ctx, cx, cy); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | static void | ||||||
|  | screen_write_box_border_set(enum box_lines box_lines, int cell_type, | ||||||
|  |     struct grid_cell *gc) | ||||||
|  | { | ||||||
|  | 	switch (box_lines) { | ||||||
|  |         case BOX_LINES_NONE: | ||||||
|  | 		break; | ||||||
|  |         case BOX_LINES_DOUBLE: | ||||||
|  |                 gc->attr &= ~GRID_ATTR_CHARSET; | ||||||
|  |                 utf8_copy(&gc->data, tty_acs_double_borders(cell_type)); | ||||||
|  | 		break; | ||||||
|  |         case BOX_LINES_HEAVY: | ||||||
|  |                 gc->attr &= ~GRID_ATTR_CHARSET; | ||||||
|  |                 utf8_copy(&gc->data, tty_acs_heavy_borders(cell_type)); | ||||||
|  | 		break; | ||||||
|  |         case BOX_LINES_ROUNDED: | ||||||
|  |                 gc->attr &= ~GRID_ATTR_CHARSET; | ||||||
|  |                 utf8_copy(&gc->data, tty_acs_rounded_borders(cell_type)); | ||||||
|  | 		break; | ||||||
|  |         case BOX_LINES_SIMPLE: | ||||||
|  |                 gc->attr &= ~GRID_ATTR_CHARSET; | ||||||
|  |                 utf8_set(&gc->data, SIMPLE_BORDERS[cell_type]); | ||||||
|  |                 break; | ||||||
|  |         case BOX_LINES_PADDED: | ||||||
|  |                 gc->attr &= ~GRID_ATTR_CHARSET; | ||||||
|  |                 utf8_set(&gc->data, PADDED_BORDERS[cell_type]); | ||||||
|  |                 break; | ||||||
|  | 	case BOX_LINES_SINGLE: | ||||||
|  | 	case BOX_LINES_DEFAULT: | ||||||
|  | 		gc->attr |= GRID_ATTR_CHARSET; | ||||||
|  | 		utf8_set(&gc->data, CELL_BORDERS[cell_type]); | ||||||
|  | 		break; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
| /* Draw a box on screen. */ | /* Draw a box on screen. */ | ||||||
| void | void | ||||||
| screen_write_box(struct screen_write_ctx *ctx, u_int nx, u_int ny) | screen_write_box(struct screen_write_ctx *ctx, u_int nx, u_int ny, | ||||||
|  |     enum box_lines lines, const struct grid_cell *gcp, const char *title) | ||||||
| { | { | ||||||
| 	struct screen		*s = ctx->s; | 	struct screen		*s = ctx->s; | ||||||
| 	struct grid_cell	 gc; | 	struct grid_cell         gc; | ||||||
| 	u_int			 cx, cy, i; | 	u_int			 cx, cy, i; | ||||||
|  |  | ||||||
| 	cx = s->cx; | 	cx = s->cx; | ||||||
| 	cy = s->cy; | 	cy = s->cy; | ||||||
|  |  | ||||||
| 	memcpy(&gc, &grid_default_cell, sizeof gc); | 	if (gcp != NULL) | ||||||
|  | 		memcpy(&gc, gcp, sizeof gc); | ||||||
|  | 	else | ||||||
|  | 		memcpy(&gc, &grid_default_cell, sizeof gc); | ||||||
|  |  | ||||||
| 	gc.attr |= GRID_ATTR_CHARSET; | 	gc.attr |= GRID_ATTR_CHARSET; | ||||||
| 	gc.flags |= GRID_FLAG_NOPALETTE; | 	gc.flags |= GRID_FLAG_NOPALETTE; | ||||||
|  |  | ||||||
| 	screen_write_putc(ctx, &gc, 'l'); | 	/* Draw top border */ | ||||||
|  | 	screen_write_box_border_set(lines, CELL_TOPLEFT, &gc); | ||||||
|  | 	screen_write_cell(ctx, &gc); | ||||||
|  | 	screen_write_box_border_set(lines, CELL_LEFTRIGHT, &gc); | ||||||
| 	for (i = 1; i < nx - 1; i++) | 	for (i = 1; i < nx - 1; i++) | ||||||
| 		screen_write_putc(ctx, &gc, 'q'); | 		screen_write_cell(ctx, &gc); | ||||||
| 	screen_write_putc(ctx, &gc, 'k'); | 	screen_write_box_border_set(lines, CELL_TOPRIGHT, &gc); | ||||||
|  | 	screen_write_cell(ctx, &gc); | ||||||
|  |  | ||||||
|  | 	/* Draw bottom border */ | ||||||
| 	screen_write_set_cursor(ctx, cx, cy + ny - 1); | 	screen_write_set_cursor(ctx, cx, cy + ny - 1); | ||||||
| 	screen_write_putc(ctx, &gc, 'm'); | 	screen_write_box_border_set(lines, CELL_BOTTOMLEFT, &gc); | ||||||
|  | 	screen_write_cell(ctx, &gc); | ||||||
|  | 	screen_write_box_border_set(lines, CELL_LEFTRIGHT, &gc); | ||||||
| 	for (i = 1; i < nx - 1; i++) | 	for (i = 1; i < nx - 1; i++) | ||||||
| 		screen_write_putc(ctx, &gc, 'q'); | 		screen_write_cell(ctx, &gc); | ||||||
| 	screen_write_putc(ctx, &gc, 'j'); | 	screen_write_box_border_set(lines, CELL_BOTTOMRIGHT, &gc); | ||||||
|  | 	screen_write_cell(ctx, &gc); | ||||||
|  |  | ||||||
|  | 	/* Draw sides */ | ||||||
|  | 	screen_write_box_border_set(lines, CELL_TOPBOTTOM, &gc); | ||||||
| 	for (i = 1; i < ny - 1; i++) { | 	for (i = 1; i < ny - 1; i++) { | ||||||
|  | 		/* left side */ | ||||||
| 		screen_write_set_cursor(ctx, cx, cy + i); | 		screen_write_set_cursor(ctx, cx, cy + i); | ||||||
| 		screen_write_putc(ctx, &gc, 'x'); | 		screen_write_cell(ctx, &gc); | ||||||
| 	} | 		/* right side */ | ||||||
| 	for (i = 1; i < ny - 1; i++) { |  | ||||||
| 		screen_write_set_cursor(ctx, cx + nx - 1, cy + i); | 		screen_write_set_cursor(ctx, cx + nx - 1, cy + i); | ||||||
| 		screen_write_putc(ctx, &gc, 'x'); | 		screen_write_cell(ctx, &gc); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if (title != NULL) { | ||||||
|  | 		gc.attr &= ~GRID_ATTR_CHARSET; | ||||||
|  | 		screen_write_cursormove(ctx, cx + 2, cy, 0); | ||||||
|  | 		format_draw(ctx, &gc, nx - 4, title, NULL, 0); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	screen_write_set_cursor(ctx, cx, cy); | 	screen_write_set_cursor(ctx, cx, cy); | ||||||
|   | |||||||
							
								
								
									
										43
									
								
								screen.c
									
									
									
									
									
								
							
							
						
						
									
										43
									
								
								screen.c
									
									
									
									
									
								
							| @@ -81,7 +81,10 @@ screen_init(struct screen *s, u_int sx, u_int sy, u_int hlimit) | |||||||
| 	s->path = NULL; | 	s->path = NULL; | ||||||
|  |  | ||||||
| 	s->cstyle = SCREEN_CURSOR_DEFAULT; | 	s->cstyle = SCREEN_CURSOR_DEFAULT; | ||||||
| 	s->ccolour = xstrdup(""); | 	s->default_cstyle = SCREEN_CURSOR_DEFAULT; | ||||||
|  | 	s->default_mode = 0; | ||||||
|  | 	s->ccolour = -1; | ||||||
|  | 	s->default_ccolour = -1; | ||||||
| 	s->tabs = NULL; | 	s->tabs = NULL; | ||||||
| 	s->sel = NULL; | 	s->sel = NULL; | ||||||
|  |  | ||||||
| @@ -127,7 +130,6 @@ screen_free(struct screen *s) | |||||||
| 	free(s->tabs); | 	free(s->tabs); | ||||||
| 	free(s->path); | 	free(s->path); | ||||||
| 	free(s->title); | 	free(s->title); | ||||||
| 	free(s->ccolour); |  | ||||||
|  |  | ||||||
| 	if (s->write_list != NULL) | 	if (s->write_list != NULL) | ||||||
| 		screen_write_free_list(s); | 		screen_write_free_list(s); | ||||||
| @@ -154,48 +156,47 @@ screen_reset_tabs(struct screen *s) | |||||||
| 		bit_set(s->tabs, i); | 		bit_set(s->tabs, i); | ||||||
| } | } | ||||||
|  |  | ||||||
| /* Set screen cursor style. */ | /* Set screen cursor style and mode. */ | ||||||
| void | void | ||||||
| screen_set_cursor_style(struct screen *s, u_int style) | screen_set_cursor_style(u_int style, enum screen_cursor_style *cstyle, | ||||||
|  |     int *mode) | ||||||
| { | { | ||||||
| 	log_debug("%s: new %u, was %u", __func__, style, s->cstyle); |  | ||||||
| 	switch (style) { | 	switch (style) { | ||||||
| 	case 0: | 	case 0: | ||||||
| 		s->cstyle = SCREEN_CURSOR_DEFAULT; | 		*cstyle = SCREEN_CURSOR_DEFAULT; | ||||||
| 		break; | 		break; | ||||||
| 	case 1: | 	case 1: | ||||||
| 		s->cstyle = SCREEN_CURSOR_BLOCK; | 		*cstyle = SCREEN_CURSOR_BLOCK; | ||||||
| 		s->mode |= MODE_CURSOR_BLINKING; | 		*mode |= MODE_CURSOR_BLINKING; | ||||||
| 		break; | 		break; | ||||||
| 	case 2: | 	case 2: | ||||||
| 		s->cstyle = SCREEN_CURSOR_BLOCK; | 		*cstyle = SCREEN_CURSOR_BLOCK; | ||||||
| 		s->mode &= ~MODE_CURSOR_BLINKING; | 		*mode &= ~MODE_CURSOR_BLINKING; | ||||||
| 		break; | 		break; | ||||||
| 	case 3: | 	case 3: | ||||||
| 		s->cstyle = SCREEN_CURSOR_UNDERLINE; | 		*cstyle = SCREEN_CURSOR_UNDERLINE; | ||||||
| 		s->mode |= MODE_CURSOR_BLINKING; | 		*mode |= MODE_CURSOR_BLINKING; | ||||||
| 		break; | 		break; | ||||||
| 	case 4: | 	case 4: | ||||||
| 		s->cstyle = SCREEN_CURSOR_UNDERLINE; | 		*cstyle = SCREEN_CURSOR_UNDERLINE; | ||||||
| 		s->mode &= ~MODE_CURSOR_BLINKING; | 		*mode &= ~MODE_CURSOR_BLINKING; | ||||||
| 		break; | 		break; | ||||||
| 	case 5: | 	case 5: | ||||||
| 		s->cstyle = SCREEN_CURSOR_BAR; | 		*cstyle = SCREEN_CURSOR_BAR; | ||||||
| 		s->mode |= MODE_CURSOR_BLINKING; | 		*mode |= MODE_CURSOR_BLINKING; | ||||||
| 		break; | 		break; | ||||||
| 	case 6: | 	case 6: | ||||||
| 		s->cstyle = SCREEN_CURSOR_BAR; | 		*cstyle = SCREEN_CURSOR_BAR; | ||||||
| 		s->mode &= ~MODE_CURSOR_BLINKING; | 		*mode &= ~MODE_CURSOR_BLINKING; | ||||||
| 		break; | 		break; | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| /* Set screen cursor colour. */ | /* Set screen cursor colour. */ | ||||||
| void | void | ||||||
| screen_set_cursor_colour(struct screen *s, const char *colour) | screen_set_cursor_colour(struct screen *s, int colour) | ||||||
| { | { | ||||||
| 	free(s->ccolour); | 	s->ccolour = colour; | ||||||
| 	s->ccolour = xstrdup(colour); |  | ||||||
| } | } | ||||||
|  |  | ||||||
| /* Set screen title. */ | /* Set screen title. */ | ||||||
|   | |||||||
| @@ -144,6 +144,54 @@ server_client_clear_overlay(struct client *c) | |||||||
| 	server_redraw_client(c); | 	server_redraw_client(c); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * Given overlay position and dimensions, return parts of the input range which | ||||||
|  |  * are visible. | ||||||
|  |  */ | ||||||
|  | void | ||||||
|  | server_client_overlay_range(u_int x, u_int y, u_int sx, u_int sy, u_int px, | ||||||
|  |     u_int py, u_int nx, struct overlay_ranges *r) | ||||||
|  | { | ||||||
|  | 	u_int	ox, onx; | ||||||
|  |  | ||||||
|  | 	/* Return up to 2 ranges. */ | ||||||
|  | 	r->px[2] = 0; | ||||||
|  | 	r->nx[2] = 0; | ||||||
|  |  | ||||||
|  | 	/* Trivial case of no overlap in the y direction. */ | ||||||
|  | 	if (py < y || py > y + sy - 1) { | ||||||
|  | 		r->px[0] = px; | ||||||
|  | 		r->nx[0] = nx; | ||||||
|  | 		r->px[1] = 0; | ||||||
|  | 		r->nx[1] = 0; | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	/* Visible bit to the left of the popup. */ | ||||||
|  | 	if (px < x) { | ||||||
|  | 		r->px[0] = px; | ||||||
|  | 		r->nx[0] = x - px; | ||||||
|  | 		if (r->nx[0] > nx) | ||||||
|  | 			r->nx[0] = nx; | ||||||
|  | 	} else { | ||||||
|  | 		r->px[0] = 0; | ||||||
|  | 		r->nx[0] = 0; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	/* Visible bit to the right of the popup. */ | ||||||
|  | 	ox = x + sx; | ||||||
|  | 	if (px > ox) | ||||||
|  | 		ox = px; | ||||||
|  | 	onx = px + nx; | ||||||
|  | 	if (onx > ox) { | ||||||
|  | 		r->px[1] = ox; | ||||||
|  | 		r->nx[1] = onx - ox; | ||||||
|  | 	} else { | ||||||
|  | 		r->px[1] = 0; | ||||||
|  | 		r->nx[1] = 0; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
| /* Check if this client is inside this server. */ | /* Check if this client is inside this server. */ | ||||||
| int | int | ||||||
| server_client_check_nested(struct client *c) | server_client_check_nested(struct client *c) | ||||||
| @@ -465,7 +513,7 @@ server_client_detach(struct client *c, enum msgtype msgtype) | |||||||
| { | { | ||||||
| 	struct session	*s = c->session; | 	struct session	*s = c->session; | ||||||
|  |  | ||||||
| 	if (s == NULL || (c->flags & CLIENT_UNATTACHEDFLAGS)) | 	if (s == NULL || (c->flags & CLIENT_NODETACHFLAGS)) | ||||||
| 		return; | 		return; | ||||||
|  |  | ||||||
| 	c->flags |= CLIENT_EXIT; | 	c->flags |= CLIENT_EXIT; | ||||||
| @@ -1655,7 +1703,7 @@ server_client_reset_state(struct client *c) | |||||||
| 	struct window_pane	*wp = server_client_get_pane(c), *loop; | 	struct window_pane	*wp = server_client_get_pane(c), *loop; | ||||||
| 	struct screen		*s = NULL; | 	struct screen		*s = NULL; | ||||||
| 	struct options		*oo = c->session->options; | 	struct options		*oo = c->session->options; | ||||||
| 	int			 mode = 0, cursor, flags; | 	int			 mode = 0, cursor, flags, n; | ||||||
| 	u_int			 cx = 0, cy = 0, ox, oy, sx, sy; | 	u_int			 cx = 0, cy = 0, ox, oy, sx, sy; | ||||||
|  |  | ||||||
| 	if (c->flags & (CLIENT_CONTROL|CLIENT_SUSPENDED)) | 	if (c->flags & (CLIENT_CONTROL|CLIENT_SUSPENDED)) | ||||||
| @@ -1683,7 +1731,20 @@ server_client_reset_state(struct client *c) | |||||||
| 	tty_margin_off(tty); | 	tty_margin_off(tty); | ||||||
|  |  | ||||||
| 	/* Move cursor to pane cursor and offset. */ | 	/* Move cursor to pane cursor and offset. */ | ||||||
| 	if (c->overlay_draw == NULL) { | 	if (c->prompt_string != NULL) { | ||||||
|  | 		n = options_get_number(c->session->options, "status-position"); | ||||||
|  | 		if (n == 0) | ||||||
|  | 			cy = 0; | ||||||
|  | 		else { | ||||||
|  | 			n = status_line_size(c); | ||||||
|  | 			if (n == 0) | ||||||
|  | 				cy = tty->sy - 1; | ||||||
|  | 			else | ||||||
|  | 				cy = tty->sy - n; | ||||||
|  | 		} | ||||||
|  | 		cx = c->prompt_cursor; | ||||||
|  | 		mode &= ~MODE_CURSOR; | ||||||
|  | 	} else if (c->overlay_draw == NULL) { | ||||||
| 		cursor = 0; | 		cursor = 0; | ||||||
| 		tty_window_offset(tty, &ox, &oy, &sx, &sy); | 		tty_window_offset(tty, &ox, &oy, &sx, &sy); | ||||||
| 		if (wp->xoff + s->cx >= ox && wp->xoff + s->cx <= ox + sx && | 		if (wp->xoff + s->cx >= ox && wp->xoff + s->cx <= ox + sx && | ||||||
|   | |||||||
							
								
								
									
										22
									
								
								status.c
									
									
									
									
									
								
							
							
						
						
									
										22
									
								
								status.c
									
									
									
									
									
								
							| @@ -439,7 +439,8 @@ status_redraw(struct client *c) | |||||||
| 			screen_write_cursormove(&ctx, 0, i, 0); | 			screen_write_cursormove(&ctx, 0, i, 0); | ||||||
|  |  | ||||||
| 			status_free_ranges(&sle->ranges); | 			status_free_ranges(&sle->ranges); | ||||||
| 			format_draw(&ctx, &gc, width, expanded, &sle->ranges); | 			format_draw(&ctx, &gc, width, expanded, &sle->ranges, | ||||||
|  | 			    0); | ||||||
|  |  | ||||||
| 			free(sle->expanded); | 			free(sle->expanded); | ||||||
| 			sle->expanded = expanded; | 			sle->expanded = expanded; | ||||||
| @@ -562,7 +563,7 @@ status_message_redraw(struct client *c) | |||||||
| 	if (c->message_ignore_styles) | 	if (c->message_ignore_styles) | ||||||
| 		screen_write_nputs(&ctx, len, &gc, "%s", c->message_string); | 		screen_write_nputs(&ctx, len, &gc, "%s", c->message_string); | ||||||
| 	else | 	else | ||||||
| 		format_draw(&ctx, &gc, c->tty.sx, c->message_string, NULL); | 		format_draw(&ctx, &gc, c->tty.sx, c->message_string, NULL, 0); | ||||||
| 	screen_write_stop(&ctx); | 	screen_write_stop(&ctx); | ||||||
|  |  | ||||||
| 	if (grid_compare(sl->active->grid, old_screen.grid) == 0) { | 	if (grid_compare(sl->active->grid, old_screen.grid) == 0) { | ||||||
| @@ -747,6 +748,7 @@ status_prompt_redraw(struct client *c) | |||||||
| 		offset = 0; | 		offset = 0; | ||||||
| 	if (pwidth > left) | 	if (pwidth > left) | ||||||
| 		pwidth = left; | 		pwidth = left; | ||||||
|  | 	c->prompt_cursor = start + c->prompt_index - offset; | ||||||
|  |  | ||||||
| 	width = 0; | 	width = 0; | ||||||
| 	for (i = 0; c->prompt_buffer[i].size != 0; i++) { | 	for (i = 0; c->prompt_buffer[i].size != 0; i++) { | ||||||
| @@ -809,14 +811,23 @@ status_prompt_translate_key(struct client *c, key_code key, key_code *new_key) | |||||||
| { | { | ||||||
| 	if (c->prompt_mode == PROMPT_ENTRY) { | 	if (c->prompt_mode == PROMPT_ENTRY) { | ||||||
| 		switch (key) { | 		switch (key) { | ||||||
|  | 		case '\001': /* C-a */ | ||||||
| 		case '\003': /* C-c */ | 		case '\003': /* C-c */ | ||||||
|  | 		case '\005': /* C-e */ | ||||||
| 		case '\007': /* C-g */ | 		case '\007': /* C-g */ | ||||||
| 		case '\010': /* C-h */ | 		case '\010': /* C-h */ | ||||||
| 		case '\011': /* Tab */ | 		case '\011': /* Tab */ | ||||||
|  | 		case '\013': /* C-k */ | ||||||
|  | 		case '\016': /* C-n */ | ||||||
|  | 		case '\020': /* C-p */ | ||||||
|  | 		case '\024': /* C-t */ | ||||||
| 		case '\025': /* C-u */ | 		case '\025': /* C-u */ | ||||||
| 		case '\027': /* C-w */ | 		case '\027': /* C-w */ | ||||||
|  | 		case '\031': /* C-y */ | ||||||
| 		case '\n': | 		case '\n': | ||||||
| 		case '\r': | 		case '\r': | ||||||
|  | 		case KEYC_LEFT|KEYC_CTRL: | ||||||
|  | 		case KEYC_RIGHT|KEYC_CTRL: | ||||||
| 		case KEYC_BSPACE: | 		case KEYC_BSPACE: | ||||||
| 		case KEYC_DC: | 		case KEYC_DC: | ||||||
| 		case KEYC_DOWN: | 		case KEYC_DOWN: | ||||||
| @@ -837,6 +848,9 @@ status_prompt_translate_key(struct client *c, key_code key, key_code *new_key) | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	switch (key) { | 	switch (key) { | ||||||
|  | 	case KEYC_BSPACE: | ||||||
|  | 		*new_key = KEYC_LEFT; | ||||||
|  | 		return (1); | ||||||
| 	case 'A': | 	case 'A': | ||||||
| 	case 'I': | 	case 'I': | ||||||
| 	case 'C': | 	case 'C': | ||||||
| @@ -882,7 +896,7 @@ status_prompt_translate_key(struct client *c, key_code key, key_code *new_key) | |||||||
| 		*new_key = 'B'|KEYC_VI; | 		*new_key = 'B'|KEYC_VI; | ||||||
| 		return (1); | 		return (1); | ||||||
| 	case 'd': | 	case 'd': | ||||||
| 		*new_key = '\025'; | 		*new_key = '\025'; /* C-u */ | ||||||
| 		return (1); | 		return (1); | ||||||
| 	case 'e': | 	case 'e': | ||||||
| 		*new_key = 'e'|KEYC_VI; | 		*new_key = 'e'|KEYC_VI; | ||||||
| @@ -1714,7 +1728,7 @@ status_prompt_complete_list_menu(struct client *c, char **list, u_int size, | |||||||
| 		item.name = list[i]; | 		item.name = list[i]; | ||||||
| 		item.key = '0' + (i - spm->start); | 		item.key = '0' + (i - spm->start); | ||||||
| 		item.command = NULL; | 		item.command = NULL; | ||||||
| 		menu_add_item(menu, &item, NULL, NULL, NULL); | 		menu_add_item(menu, &item, NULL, c, NULL); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if (options_get_number(c->session->options, "status-position") == 0) | 	if (options_get_number(c->session->options, "status-position") == 0) | ||||||
|   | |||||||
							
								
								
									
										109
									
								
								tmux.h
									
									
									
									
									
								
							
							
						
						
									
										109
									
								
								tmux.h
									
									
									
									
									
								
							| @@ -533,6 +533,7 @@ enum tty_code_code { | |||||||
| #define MODE_CRLF 0x4000 | #define MODE_CRLF 0x4000 | ||||||
| #define MODE_KEXTENDED 0x8000 | #define MODE_KEXTENDED 0x8000 | ||||||
| #define MODE_CURSOR_VERY_VISIBLE 0x10000 | #define MODE_CURSOR_VERY_VISIBLE 0x10000 | ||||||
|  | #define MODE_CURSOR_BLINKING_SET 0x20000 | ||||||
|  |  | ||||||
| #define ALL_MODES 0xffffff | #define ALL_MODES 0xffffff | ||||||
| #define ALL_MOUSE_MODES (MODE_MOUSE_STANDARD|MODE_MOUSE_BUTTON|MODE_MOUSE_ALL) | #define ALL_MOUSE_MODES (MODE_MOUSE_STANDARD|MODE_MOUSE_BUTTON|MODE_MOUSE_ALL) | ||||||
| @@ -616,6 +617,24 @@ struct colour_palette { | |||||||
| #define GRID_LINE_EXTENDED 0x2 | #define GRID_LINE_EXTENDED 0x2 | ||||||
| #define GRID_LINE_DEAD 0x4 | #define GRID_LINE_DEAD 0x4 | ||||||
|  |  | ||||||
|  | #define CELL_INSIDE 0 | ||||||
|  | #define CELL_TOPBOTTOM 1 | ||||||
|  | #define CELL_LEFTRIGHT 2 | ||||||
|  | #define CELL_TOPLEFT 3 | ||||||
|  | #define CELL_TOPRIGHT 4 | ||||||
|  | #define CELL_BOTTOMLEFT 5 | ||||||
|  | #define CELL_BOTTOMRIGHT 6 | ||||||
|  | #define CELL_TOPJOIN 7 | ||||||
|  | #define CELL_BOTTOMJOIN 8 | ||||||
|  | #define CELL_LEFTJOIN 9 | ||||||
|  | #define CELL_RIGHTJOIN 10 | ||||||
|  | #define CELL_JOIN 11 | ||||||
|  | #define CELL_OUTSIDE 12 | ||||||
|  |  | ||||||
|  | #define CELL_BORDERS " xqlkmjwvtun~" | ||||||
|  | #define SIMPLE_BORDERS " |-+++++++++." | ||||||
|  | #define PADDED_BORDERS "             " | ||||||
|  |  | ||||||
| /* Grid cell data. */ | /* Grid cell data. */ | ||||||
| struct grid_cell { | struct grid_cell { | ||||||
| 	struct utf8_data	data; | 	struct utf8_data	data; | ||||||
| @@ -779,11 +798,16 @@ struct screen { | |||||||
| 	u_int				 cy;	  /* cursor y */ | 	u_int				 cy;	  /* cursor y */ | ||||||
|  |  | ||||||
| 	enum screen_cursor_style	 cstyle;  /* cursor style */ | 	enum screen_cursor_style	 cstyle;  /* cursor style */ | ||||||
| 	char				*ccolour; /* cursor colour */ | 	enum screen_cursor_style	 default_cstyle; | ||||||
|  | 	int				 ccolour; /* cursor colour */ | ||||||
|  | 	int				 default_ccolour; | ||||||
|  |  | ||||||
| 	u_int				 rupper;  /* scroll region top */ | 	u_int				 rupper;  /* scroll region top */ | ||||||
| 	u_int				 rlower;  /* scroll region bottom */ | 	u_int				 rlower;  /* scroll region bottom */ | ||||||
|  |  | ||||||
|  | 	int				 mode; | ||||||
|  | 	int				 default_mode; | ||||||
|  |  | ||||||
| 	u_int				 saved_cx; | 	u_int				 saved_cx; | ||||||
| 	u_int				 saved_cy; | 	u_int				 saved_cy; | ||||||
| 	struct grid			*saved_grid; | 	struct grid			*saved_grid; | ||||||
| @@ -817,6 +841,27 @@ struct screen_write_ctx { | |||||||
| 	u_int				 bg; | 	u_int				 bg; | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | /* Box border lines option. */ | ||||||
|  | enum box_lines { | ||||||
|  | 	BOX_LINES_DEFAULT = -1, | ||||||
|  | 	BOX_LINES_SINGLE, | ||||||
|  | 	BOX_LINES_DOUBLE, | ||||||
|  | 	BOX_LINES_HEAVY, | ||||||
|  | 	BOX_LINES_SIMPLE, | ||||||
|  | 	BOX_LINES_ROUNDED, | ||||||
|  | 	BOX_LINES_PADDED, | ||||||
|  | 	BOX_LINES_NONE | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | /* Pane border lines option. */ | ||||||
|  | enum pane_lines { | ||||||
|  | 	PANE_LINES_SINGLE, | ||||||
|  | 	PANE_LINES_DOUBLE, | ||||||
|  | 	PANE_LINES_HEAVY, | ||||||
|  | 	PANE_LINES_SIMPLE, | ||||||
|  | 	PANE_LINES_NUMBER | ||||||
|  | }; | ||||||
|  |  | ||||||
| /* Screen redraw context. */ | /* Screen redraw context. */ | ||||||
| struct screen_redraw_ctx { | struct screen_redraw_ctx { | ||||||
| 	struct client	*c; | 	struct client	*c; | ||||||
| @@ -825,7 +870,7 @@ struct screen_redraw_ctx { | |||||||
| 	int		 statustop; | 	int		 statustop; | ||||||
|  |  | ||||||
| 	int		 pane_status; | 	int		 pane_status; | ||||||
| 	int		 pane_lines; | 	enum pane_lines	 pane_lines; | ||||||
|  |  | ||||||
| 	struct grid_cell no_pane_gc; | 	struct grid_cell no_pane_gc; | ||||||
| 	int		 no_pane_gc_set; | 	int		 no_pane_gc_set; | ||||||
| @@ -1079,13 +1124,6 @@ TAILQ_HEAD(winlink_stack, winlink); | |||||||
| #define PANE_STATUS_TOP 1 | #define PANE_STATUS_TOP 1 | ||||||
| #define PANE_STATUS_BOTTOM 2 | #define PANE_STATUS_BOTTOM 2 | ||||||
|  |  | ||||||
| /* Pane border lines option. */ |  | ||||||
| #define PANE_LINES_SINGLE 0 |  | ||||||
| #define PANE_LINES_DOUBLE 1 |  | ||||||
| #define PANE_LINES_HEAVY 2 |  | ||||||
| #define PANE_LINES_SIMPLE 3 |  | ||||||
| #define PANE_LINES_NUMBER 4 |  | ||||||
|  |  | ||||||
| /* Layout direction. */ | /* Layout direction. */ | ||||||
| enum layout_type { | enum layout_type { | ||||||
| 	LAYOUT_LEFTRIGHT, | 	LAYOUT_LEFTRIGHT, | ||||||
| @@ -1263,7 +1301,7 @@ struct tty { | |||||||
| 	u_int		 cx; | 	u_int		 cx; | ||||||
| 	u_int		 cy; | 	u_int		 cy; | ||||||
| 	enum screen_cursor_style cstyle; | 	enum screen_cursor_style cstyle; | ||||||
| 	char		*ccolour; | 	int		 ccolour; | ||||||
|  |  | ||||||
| 	int		 oflag; | 	int		 oflag; | ||||||
| 	u_int		 oox; | 	u_int		 oox; | ||||||
| @@ -1588,10 +1626,18 @@ struct client_window { | |||||||
| }; | }; | ||||||
| RB_HEAD(client_windows, client_window); | RB_HEAD(client_windows, client_window); | ||||||
|  |  | ||||||
|  | /* Visible areas not obstructed by overlays. */ | ||||||
|  | #define OVERLAY_MAX_RANGES 3 | ||||||
|  | struct overlay_ranges { | ||||||
|  | 	u_int	px[OVERLAY_MAX_RANGES]; | ||||||
|  | 	u_int	nx[OVERLAY_MAX_RANGES]; | ||||||
|  | }; | ||||||
|  |  | ||||||
| /* Client connection. */ | /* Client connection. */ | ||||||
| typedef int (*prompt_input_cb)(struct client *, void *, const char *, int); | typedef int (*prompt_input_cb)(struct client *, void *, const char *, int); | ||||||
| typedef void (*prompt_free_cb)(void *); | typedef void (*prompt_free_cb)(void *); | ||||||
| typedef int (*overlay_check_cb)(struct client *, void *, u_int, u_int); | typedef void (*overlay_check_cb)(struct client*, void *, u_int, u_int, u_int, | ||||||
|  | 	    struct overlay_ranges *); | ||||||
| typedef struct screen *(*overlay_mode_cb)(struct client *, void *, u_int *, | typedef struct screen *(*overlay_mode_cb)(struct client *, void *, u_int *, | ||||||
| 	    u_int *); | 	    u_int *); | ||||||
| typedef void (*overlay_draw_cb)(struct client *, void *, | typedef void (*overlay_draw_cb)(struct client *, void *, | ||||||
| @@ -1691,6 +1737,9 @@ struct client { | |||||||
| 	(CLIENT_DEAD|		\ | 	(CLIENT_DEAD|		\ | ||||||
| 	 CLIENT_SUSPENDED|	\ | 	 CLIENT_SUSPENDED|	\ | ||||||
| 	 CLIENT_EXIT) | 	 CLIENT_EXIT) | ||||||
|  | #define CLIENT_NODETACHFLAGS 	\ | ||||||
|  | 	(CLIENT_DEAD|		\ | ||||||
|  | 	 CLIENT_EXIT) | ||||||
| #define CLIENT_NOSIZEFLAGS	\ | #define CLIENT_NOSIZEFLAGS	\ | ||||||
| 	(CLIENT_DEAD|		\ | 	(CLIENT_DEAD|		\ | ||||||
| 	 CLIENT_SUSPENDED|	\ | 	 CLIENT_SUSPENDED|	\ | ||||||
| @@ -1732,6 +1781,7 @@ struct client { | |||||||
| #define PROMPT_KEY 0x10 | #define PROMPT_KEY 0x10 | ||||||
| 	int		 prompt_flags; | 	int		 prompt_flags; | ||||||
| 	enum prompt_type prompt_type; | 	enum prompt_type prompt_type; | ||||||
|  | 	int              prompt_cursor; | ||||||
|  |  | ||||||
| 	struct session	*session; | 	struct session	*session; | ||||||
| 	struct session	*last_session; | 	struct session	*last_session; | ||||||
| @@ -2013,7 +2063,7 @@ char		*format_grid_line(struct grid *, u_int); | |||||||
| /* format-draw.c */ | /* format-draw.c */ | ||||||
| void		 format_draw(struct screen_write_ctx *, | void		 format_draw(struct screen_write_ctx *, | ||||||
| 		     const struct grid_cell *, u_int, const char *, | 		     const struct grid_cell *, u_int, const char *, | ||||||
| 		     struct style_ranges *); | 		     struct style_ranges *, int); | ||||||
| u_int		 format_width(const char *); | u_int		 format_width(const char *); | ||||||
| char		*format_trim_left(const char *, u_int); | char		*format_trim_left(const char *, u_int); | ||||||
| char		*format_trim_right(const char *, u_int); | char		*format_trim_right(const char *, u_int); | ||||||
| @@ -2079,6 +2129,8 @@ struct style	*options_string_to_style(struct options *, const char *, | |||||||
| int		 options_from_string(struct options *, | int		 options_from_string(struct options *, | ||||||
| 		     const struct options_table_entry *, const char *, | 		     const struct options_table_entry *, const char *, | ||||||
| 		     const char *, int, char **); | 		     const char *, int, char **); | ||||||
|  | int	 	 options_find_choice(const struct options_table_entry *, | ||||||
|  | 		     const char *, char **); | ||||||
| void		 options_push_changes(const char *); | void		 options_push_changes(const char *); | ||||||
| int		 options_remove_or_default(struct options_entry *, int, | int		 options_remove_or_default(struct options_entry *, int, | ||||||
| 		     char **); | 		     char **); | ||||||
| @@ -2094,9 +2146,9 @@ typedef void (*job_free_cb) (void *); | |||||||
| #define JOB_NOWAIT 0x1 | #define JOB_NOWAIT 0x1 | ||||||
| #define JOB_KEEPWRITE 0x2 | #define JOB_KEEPWRITE 0x2 | ||||||
| #define JOB_PTY 0x4 | #define JOB_PTY 0x4 | ||||||
| struct job	*job_run(const char *, int, char **, struct session *, | struct job	*job_run(const char *, int, char **, struct environ *, | ||||||
| 		     const char *, job_update_cb, job_complete_cb, job_free_cb, | 		     struct session *, const char *, job_update_cb, | ||||||
| 		     void *, int, int, int); | 		     job_complete_cb, job_free_cb, void *, int, int, int); | ||||||
| void		 job_free(struct job *); | void		 job_free(struct job *); | ||||||
| int		 job_transfer(struct job *, pid_t *, char *, size_t); | int		 job_transfer(struct job *, pid_t *, char *, size_t); | ||||||
| void		 job_resize(struct job *, u_int, u_int); | void		 job_resize(struct job *, u_int, u_int); | ||||||
| @@ -2231,6 +2283,9 @@ void		 tty_default_features(int *, const char *, u_int); | |||||||
| int		 tty_acs_needed(struct tty *); | int		 tty_acs_needed(struct tty *); | ||||||
| const char	*tty_acs_get(struct tty *, u_char); | const char	*tty_acs_get(struct tty *, u_char); | ||||||
| int		 tty_acs_reverse_get(struct tty *, const char *, size_t); | int		 tty_acs_reverse_get(struct tty *, const char *, size_t); | ||||||
|  | const struct utf8_data *tty_acs_double_borders(int); | ||||||
|  | const struct utf8_data *tty_acs_heavy_borders(int); | ||||||
|  | const struct utf8_data *tty_acs_rounded_borders(int); | ||||||
|  |  | ||||||
| /* tty-keys.c */ | /* tty-keys.c */ | ||||||
| void		tty_keys_build(struct tty *); | void		tty_keys_build(struct tty *); | ||||||
| @@ -2485,6 +2540,8 @@ void	 server_client_set_overlay(struct client *, u_int, overlay_check_cb, | |||||||
| 	     overlay_mode_cb, overlay_draw_cb, overlay_key_cb, | 	     overlay_mode_cb, overlay_draw_cb, overlay_key_cb, | ||||||
| 	     overlay_free_cb, overlay_resize_cb, void *); | 	     overlay_free_cb, overlay_resize_cb, void *); | ||||||
| void	 server_client_clear_overlay(struct client *); | void	 server_client_clear_overlay(struct client *); | ||||||
|  | void	 server_client_overlay_range(u_int, u_int, u_int, u_int, u_int, u_int, | ||||||
|  | 	     u_int, struct overlay_ranges *); | ||||||
| void	 server_client_set_key_table(struct client *, const char *); | void	 server_client_set_key_table(struct client *, const char *); | ||||||
| const char *server_client_get_key_table(struct client *); | const char *server_client_get_key_table(struct client *); | ||||||
| int	 server_client_check_nested(struct client *); | int	 server_client_check_nested(struct client *); | ||||||
| @@ -2592,6 +2649,7 @@ int	 input_key_get_mouse(struct screen *, struct mouse_event *, u_int, | |||||||
| int	 colour_find_rgb(u_char, u_char, u_char); | int	 colour_find_rgb(u_char, u_char, u_char); | ||||||
| int	 colour_join_rgb(u_char, u_char, u_char); | int	 colour_join_rgb(u_char, u_char, u_char); | ||||||
| void	 colour_split_rgb(int, u_char *, u_char *, u_char *); | void	 colour_split_rgb(int, u_char *, u_char *, u_char *); | ||||||
|  | int	 colour_force_rgb(int); | ||||||
| const char *colour_tostring(int); | const char *colour_tostring(int); | ||||||
| int	 colour_fromstring(const char *s); | int	 colour_fromstring(const char *s); | ||||||
| int	 colour_256toRGB(int); | int	 colour_256toRGB(int); | ||||||
| @@ -2712,7 +2770,8 @@ void	 screen_write_hline(struct screen_write_ctx *, u_int, int, int); | |||||||
| void	 screen_write_vline(struct screen_write_ctx *, u_int, int, int); | void	 screen_write_vline(struct screen_write_ctx *, u_int, int, int); | ||||||
| void	 screen_write_menu(struct screen_write_ctx *, struct menu *, int, | void	 screen_write_menu(struct screen_write_ctx *, struct menu *, int, | ||||||
| 	     const struct grid_cell *); | 	     const struct grid_cell *); | ||||||
| void	 screen_write_box(struct screen_write_ctx *, u_int, u_int); | void	 screen_write_box(struct screen_write_ctx *, u_int, u_int, int, | ||||||
|  | 	     const struct grid_cell *, const char *); | ||||||
| void	 screen_write_preview(struct screen_write_ctx *, struct screen *, u_int, | void	 screen_write_preview(struct screen_write_ctx *, struct screen *, u_int, | ||||||
| 	     u_int); | 	     u_int); | ||||||
| void	 screen_write_backspace(struct screen_write_ctx *); | void	 screen_write_backspace(struct screen_write_ctx *); | ||||||
| @@ -2765,8 +2824,8 @@ void	 screen_init(struct screen *, u_int, u_int, u_int); | |||||||
| void	 screen_reinit(struct screen *); | void	 screen_reinit(struct screen *); | ||||||
| void	 screen_free(struct screen *); | void	 screen_free(struct screen *); | ||||||
| void	 screen_reset_tabs(struct screen *); | void	 screen_reset_tabs(struct screen *); | ||||||
| void	 screen_set_cursor_style(struct screen *, u_int); | void	 screen_set_cursor_style(u_int, enum screen_cursor_style *, int *); | ||||||
| void	 screen_set_cursor_colour(struct screen *, const char *); | void	 screen_set_cursor_colour(struct screen *, int); | ||||||
| int	 screen_set_title(struct screen *, const char *); | int	 screen_set_title(struct screen *, const char *); | ||||||
| void	 screen_set_path(struct screen *, const char *); | void	 screen_set_path(struct screen *, const char *); | ||||||
| void	 screen_push_title(struct screen *); | void	 screen_push_title(struct screen *); | ||||||
| @@ -3117,7 +3176,8 @@ int		 menu_display(struct menu *, int, struct cmdq_item *, u_int, | |||||||
| 		    u_int, struct client *, struct cmd_find_state *, | 		    u_int, struct client *, struct cmd_find_state *, | ||||||
| 		    menu_choice_cb, void *); | 		    menu_choice_cb, void *); | ||||||
| struct screen	*menu_mode_cb(struct client *, void *, u_int *, u_int *); | struct screen	*menu_mode_cb(struct client *, void *, u_int *, u_int *); | ||||||
| int		 menu_check_cb(struct client *, void *, u_int, u_int); | void		 menu_check_cb(struct client *, void *, u_int, u_int, u_int, | ||||||
|  | 		    struct overlay_ranges *); | ||||||
| void		 menu_draw_cb(struct client *, void *, | void		 menu_draw_cb(struct client *, void *, | ||||||
| 		    struct screen_redraw_ctx *); | 		    struct screen_redraw_ctx *); | ||||||
| void		 menu_free_cb(struct client *, void *); | void		 menu_free_cb(struct client *, void *); | ||||||
| @@ -3126,13 +3186,14 @@ int		 menu_key_cb(struct client *, void *, struct key_event *); | |||||||
| /* popup.c */ | /* popup.c */ | ||||||
| #define POPUP_CLOSEEXIT 0x1 | #define POPUP_CLOSEEXIT 0x1 | ||||||
| #define POPUP_CLOSEEXITZERO 0x2 | #define POPUP_CLOSEEXITZERO 0x2 | ||||||
| #define POPUP_NOBORDER 0x4 | #define POPUP_INTERNAL 0x4 | ||||||
| #define POPUP_INTERNAL 0x8 |  | ||||||
| typedef void (*popup_close_cb)(int, void *); | typedef void (*popup_close_cb)(int, void *); | ||||||
| typedef void (*popup_finish_edit_cb)(char *, size_t, void *); | typedef void (*popup_finish_edit_cb)(char *, size_t, void *); | ||||||
| int		 popup_display(int, struct cmdq_item *, u_int, u_int, u_int, | int		 popup_display(int, int, struct cmdq_item *, u_int, u_int, | ||||||
| 		    u_int, const char *, int, char **, const char *, | 		    u_int, u_int, struct environ *, const char *, int, char **, | ||||||
| 		    struct client *, struct session *, popup_close_cb, void *); | 		    const char *, const char *, struct client *, | ||||||
|  | 		    struct session *, const char *, const char *, | ||||||
|  | 		    popup_close_cb, void *); | ||||||
| int		 popup_editor(struct client *, const char *, size_t, | int		 popup_editor(struct client *, const char *, size_t, | ||||||
| 		    popup_finish_edit_cb, void *); | 		    popup_finish_edit_cb, void *); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -184,7 +184,7 @@ Oct Hex Name *	(* marks function used in DEC VT series or LA series terminals) | |||||||
| 230 98 X	Reserved for for future standard | 230 98 X	Reserved for for future standard | ||||||
| 231 99 Y	Reserved | 231 99 Y	Reserved | ||||||
| 232 9A Z     *	Reserved, but causes DEC terminals to respond with DA codes | 232 9A Z     *	Reserved, but causes DEC terminals to respond with DA codes | ||||||
| 233 9B [ CSI *	Control Sequence Introducer (described in a seperate table) | 233 9B [ CSI *	Control Sequence Introducer (described in a separate table) | ||||||
| 234 9C \ ST  *	String Terminator (VT125 exits graphics) | 234 9C \ ST  *	String Terminator (VT125 exits graphics) | ||||||
| 235 9D ] OSC	Operating System Command (reprograms intelligent terminal) | 235 9D ] OSC	Operating System Command (reprograms intelligent terminal) | ||||||
| 236 9E ^ PM	Privacy Message (password verification), terminated by ST | 236 9E ^ PM	Privacy Message (password verification), terminated by ST | ||||||
|   | |||||||
							
								
								
									
										76
									
								
								tty-acs.c
									
									
									
									
									
								
							
							
						
						
									
										76
									
								
								tty-acs.c
									
									
									
									
									
								
							| @@ -25,7 +25,7 @@ | |||||||
|  |  | ||||||
| /* Table mapping ACS entries to UTF-8. */ | /* Table mapping ACS entries to UTF-8. */ | ||||||
| struct tty_acs_entry { | struct tty_acs_entry { | ||||||
| 	u_char	 	 key; | 	u_char		 key; | ||||||
| 	const char	*string; | 	const char	*string; | ||||||
| }; | }; | ||||||
| static const struct tty_acs_entry tty_acs_table[] = { | static const struct tty_acs_entry tty_acs_table[] = { | ||||||
| @@ -61,7 +61,7 @@ static const struct tty_acs_entry tty_acs_table[] = { | |||||||
| 	{ 'x', "\342\224\202" },	/* vertical line */ | 	{ 'x', "\342\224\202" },	/* vertical line */ | ||||||
| 	{ 'y', "\342\211\244" },	/* less-than-or-equal-to */ | 	{ 'y', "\342\211\244" },	/* less-than-or-equal-to */ | ||||||
| 	{ 'z', "\342\211\245" },	/* greater-than-or-equal-to */ | 	{ 'z', "\342\211\245" },	/* greater-than-or-equal-to */ | ||||||
| 	{ '{', "\317\200" },   		/* greek pi */ | 	{ '{', "\317\200" },		/* greek pi */ | ||||||
| 	{ '|', "\342\211\240" },	/* not-equal */ | 	{ '|', "\342\211\240" },	/* not-equal */ | ||||||
| 	{ '}', "\302\243" },		/* UK pound sign */ | 	{ '}', "\302\243" },		/* UK pound sign */ | ||||||
| 	{ '~', "\302\267" }		/* bullet */ | 	{ '~', "\302\267" }		/* bullet */ | ||||||
| @@ -110,6 +110,78 @@ static const struct tty_acs_reverse_entry tty_acs_reverse3[] = { | |||||||
| 	{ "\342\225\254", 'n' }, | 	{ "\342\225\254", 'n' }, | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | /* UTF-8 double borders. */ | ||||||
|  | static const struct utf8_data tty_acs_double_borders_list[] = { | ||||||
|  | 	{ "", 0, 0, 0 }, | ||||||
|  | 	{ "\342\225\221", 0, 3, 1 }, /* U+2551 */ | ||||||
|  | 	{ "\342\225\220", 0, 3, 1 }, /* U+2550 */ | ||||||
|  | 	{ "\342\225\224", 0, 3, 1 }, /* U+2554 */ | ||||||
|  | 	{ "\342\225\227", 0, 3, 1 }, /* U+2557 */ | ||||||
|  | 	{ "\342\225\232", 0, 3, 1 }, /* U+255A */ | ||||||
|  | 	{ "\342\225\235", 0, 3, 1 }, /* U+255D */ | ||||||
|  | 	{ "\342\225\246", 0, 3, 1 }, /* U+2566 */ | ||||||
|  | 	{ "\342\225\251", 0, 3, 1 }, /* U+2569 */ | ||||||
|  | 	{ "\342\225\240", 0, 3, 1 }, /* U+2560 */ | ||||||
|  | 	{ "\342\225\243", 0, 3, 1 }, /* U+2563 */ | ||||||
|  | 	{ "\342\225\254", 0, 3, 1 }, /* U+256C */ | ||||||
|  | 	{ "\302\267",	  0, 2, 1 }  /* U+00B7 */ | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | /* UTF-8 heavy borders. */ | ||||||
|  | static const struct utf8_data tty_acs_heavy_borders_list[] = { | ||||||
|  | 	{ "", 0, 0, 0 }, | ||||||
|  | 	{ "\342\224\203", 0, 3, 1 }, /* U+2503 */ | ||||||
|  | 	{ "\342\224\201", 0, 3, 1 }, /* U+2501 */ | ||||||
|  | 	{ "\342\224\217", 0, 3, 1 }, /* U+250F */ | ||||||
|  | 	{ "\342\224\223", 0, 3, 1 }, /* U+2513 */ | ||||||
|  | 	{ "\342\224\227", 0, 3, 1 }, /* U+2517 */ | ||||||
|  | 	{ "\342\224\233", 0, 3, 1 }, /* U+251B */ | ||||||
|  | 	{ "\342\224\263", 0, 3, 1 }, /* U+2533 */ | ||||||
|  | 	{ "\342\224\273", 0, 3, 1 }, /* U+253B */ | ||||||
|  | 	{ "\342\224\243", 0, 3, 1 }, /* U+2523 */ | ||||||
|  | 	{ "\342\224\253", 0, 3, 1 }, /* U+252B */ | ||||||
|  | 	{ "\342\225\213", 0, 3, 1 }, /* U+254B */ | ||||||
|  | 	{ "\302\267",	  0, 2, 1 }  /* U+00B7 */ | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | /* UTF-8 rounded borders. */ | ||||||
|  | static const struct utf8_data tty_acs_rounded_borders_list[] = { | ||||||
|  | 	{ "", 0, 0, 0 }, | ||||||
|  | 	{ "\342\224\202", 0, 3, 1 }, /* U+2502 */ | ||||||
|  | 	{ "\342\224\200", 0, 3, 1 }, /* U+2500 */ | ||||||
|  | 	{ "\342\225\255", 0, 3, 1 }, /* U+256D */ | ||||||
|  | 	{ "\342\225\256", 0, 3, 1 }, /* U+256E */ | ||||||
|  | 	{ "\342\225\260", 0, 3, 1 }, /* U+2570 */ | ||||||
|  | 	{ "\342\225\257", 0, 3, 1 }, /* U+256F */ | ||||||
|  | 	{ "\342\224\263", 0, 3, 1 }, /* U+2533 */ | ||||||
|  | 	{ "\342\224\273", 0, 3, 1 }, /* U+253B */ | ||||||
|  | 	{ "\342\224\243", 0, 3, 1 }, /* U+2523 */ | ||||||
|  | 	{ "\342\224\253", 0, 3, 1 }, /* U+252B */ | ||||||
|  | 	{ "\342\225\213", 0, 3, 1 }, /* U+254B */ | ||||||
|  | 	{ "\302\267",	  0, 2, 1 }  /* U+00B7 */ | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | /* Get cell border character for double style. */ | ||||||
|  | const struct utf8_data * | ||||||
|  | tty_acs_double_borders(int cell_type) | ||||||
|  | { | ||||||
|  | 	return (&tty_acs_double_borders_list[cell_type]); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* Get cell border character for heavy style. */ | ||||||
|  | const struct utf8_data * | ||||||
|  | tty_acs_heavy_borders(int cell_type) | ||||||
|  | { | ||||||
|  | 	return (&tty_acs_heavy_borders_list[cell_type]); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* Get cell border character for rounded style. */ | ||||||
|  | const struct utf8_data * | ||||||
|  | tty_acs_rounded_borders(int cell_type) | ||||||
|  | { | ||||||
|  | 	return (&tty_acs_rounded_borders_list[cell_type]); | ||||||
|  | } | ||||||
|  |  | ||||||
| static int | static int | ||||||
| tty_acs_cmp(const void *key, const void *value) | tty_acs_cmp(const void *key, const void *value) | ||||||
| { | { | ||||||
|   | |||||||
| @@ -1204,6 +1204,9 @@ tty_keys_clipboard(__unused struct tty *tty, const char *buf, size_t len, | |||||||
| 	buf += 5; | 	buf += 5; | ||||||
| 	end -= 5; | 	end -= 5; | ||||||
|  |  | ||||||
|  | 	/* Adjust end so that it points to the start of the terminator. */ | ||||||
|  | 	end -= terminator - 1; | ||||||
|  |  | ||||||
| 	/* Get the second argument. */ | 	/* Get the second argument. */ | ||||||
| 	while (end != 0 && *buf != ';') { | 	while (end != 0 && *buf != ';') { | ||||||
| 		buf++; | 		buf++; | ||||||
|   | |||||||
							
								
								
									
										260
									
								
								tty.c
									
									
									
									
									
								
							
							
						
						
									
										260
									
								
								tty.c
									
									
									
									
									
								
							| @@ -38,7 +38,7 @@ static int	tty_client_ready(struct client *); | |||||||
|  |  | ||||||
| static void	tty_set_italics(struct tty *); | static void	tty_set_italics(struct tty *); | ||||||
| static int	tty_try_colour(struct tty *, int, const char *); | static int	tty_try_colour(struct tty *, int, const char *); | ||||||
| static void	tty_force_cursor_colour(struct tty *, const char *); | static void	tty_force_cursor_colour(struct tty *, int); | ||||||
| static void	tty_cursor_pane(struct tty *, const struct tty_ctx *, u_int, | static void	tty_cursor_pane(struct tty *, const struct tty_ctx *, u_int, | ||||||
| 		    u_int); | 		    u_int); | ||||||
| static void	tty_cursor_pane_unless_wrap(struct tty *, | static void	tty_cursor_pane_unless_wrap(struct tty *, | ||||||
| @@ -71,6 +71,8 @@ static void	tty_draw_pane(struct tty *, const struct tty_ctx *, u_int); | |||||||
| static void	tty_default_attributes(struct tty *, const struct grid_cell *, | static void	tty_default_attributes(struct tty *, const struct grid_cell *, | ||||||
| 		    struct colour_palette *, u_int); | 		    struct colour_palette *, u_int); | ||||||
| static int	tty_check_overlay(struct tty *, u_int, u_int); | static int	tty_check_overlay(struct tty *, u_int, u_int); | ||||||
|  | static void	tty_check_overlay_range(struct tty *, u_int, u_int, u_int, | ||||||
|  | 		    struct overlay_ranges *); | ||||||
|  |  | ||||||
| #define tty_use_margin(tty) \ | #define tty_use_margin(tty) \ | ||||||
| 	(tty->term->flags & TERM_DECSLRM) | 	(tty->term->flags & TERM_DECSLRM) | ||||||
| @@ -103,7 +105,7 @@ tty_init(struct tty *tty, struct client *c) | |||||||
| 	tty->client = c; | 	tty->client = c; | ||||||
|  |  | ||||||
| 	tty->cstyle = SCREEN_CURSOR_DEFAULT; | 	tty->cstyle = SCREEN_CURSOR_DEFAULT; | ||||||
| 	tty->ccolour = xstrdup(""); | 	tty->ccolour = -1; | ||||||
|  |  | ||||||
| 	if (tcgetattr(c->fd, &tty->tio) != 0) | 	if (tcgetattr(c->fd, &tty->tio) != 0) | ||||||
| 		return (-1); | 		return (-1); | ||||||
| @@ -305,7 +307,7 @@ tty_start_tty(struct tty *tty) | |||||||
| { | { | ||||||
| 	struct client	*c = tty->client; | 	struct client	*c = tty->client; | ||||||
| 	struct termios	 tio; | 	struct termios	 tio; | ||||||
| 	struct timeval	 tv = { .tv_sec = 1 }; | 	struct timeval	 tv = { .tv_sec = 3 }; | ||||||
|  |  | ||||||
| 	setblocking(c->fd, 0); | 	setblocking(c->fd, 0); | ||||||
| 	event_add(&tty->event_in, NULL); | 	event_add(&tty->event_in, NULL); | ||||||
| @@ -344,8 +346,8 @@ tty_start_tty(struct tty *tty) | |||||||
| 	tty->flags |= TTY_STARTED; | 	tty->flags |= TTY_STARTED; | ||||||
| 	tty_invalidate(tty); | 	tty_invalidate(tty); | ||||||
|  |  | ||||||
| 	if (*tty->ccolour != '\0') | 	if (tty->ccolour != -1) | ||||||
| 		tty_force_cursor_colour(tty, ""); | 		tty_force_cursor_colour(tty, -1); | ||||||
|  |  | ||||||
| 	tty->mouse_drag_flag = 0; | 	tty->mouse_drag_flag = 0; | ||||||
| 	tty->mouse_drag_update = NULL; | 	tty->mouse_drag_update = NULL; | ||||||
| @@ -409,7 +411,7 @@ tty_stop_tty(struct tty *tty) | |||||||
| 	} | 	} | ||||||
| 	if (tty->mode & MODE_BRACKETPASTE) | 	if (tty->mode & MODE_BRACKETPASTE) | ||||||
| 		tty_raw(tty, tty_term_string(tty->term, TTYC_DSBP)); | 		tty_raw(tty, tty_term_string(tty->term, TTYC_DSBP)); | ||||||
| 	if (*tty->ccolour != '\0') | 	if (tty->ccolour != -1) | ||||||
| 		tty_raw(tty, tty_term_string(tty->term, TTYC_CR)); | 		tty_raw(tty, tty_term_string(tty->term, TTYC_CR)); | ||||||
|  |  | ||||||
| 	tty_raw(tty, tty_term_string(tty->term, TTYC_CNORM)); | 	tty_raw(tty, tty_term_string(tty->term, TTYC_CNORM)); | ||||||
| @@ -454,7 +456,6 @@ void | |||||||
| tty_free(struct tty *tty) | tty_free(struct tty *tty) | ||||||
| { | { | ||||||
| 	tty_close(tty); | 	tty_close(tty); | ||||||
| 	free(tty->ccolour); |  | ||||||
| } | } | ||||||
|  |  | ||||||
| void | void | ||||||
| @@ -653,39 +654,66 @@ tty_set_title(struct tty *tty, const char *title) | |||||||
| } | } | ||||||
|  |  | ||||||
| static void | static void | ||||||
| tty_force_cursor_colour(struct tty *tty, const char *ccolour) | tty_force_cursor_colour(struct tty *tty, int c) | ||||||
| { | { | ||||||
| 	if (*ccolour == '\0') | 	u_char	r, g, b; | ||||||
|  | 	char	s[13] = ""; | ||||||
|  |  | ||||||
|  | 	if (c != -1) | ||||||
|  | 		c = colour_force_rgb(c); | ||||||
|  | 	if (c == tty->ccolour) | ||||||
|  | 		return; | ||||||
|  | 	if (c == -1) | ||||||
| 		tty_putcode(tty, TTYC_CR); | 		tty_putcode(tty, TTYC_CR); | ||||||
| 	else | 	else { | ||||||
| 		tty_putcode_ptr1(tty, TTYC_CS, ccolour); | 		colour_split_rgb(c, &r, &g, &b); | ||||||
| 	free(tty->ccolour); | 		xsnprintf(s, sizeof s, "rgb:%02hhx/%02hhx/%02hhx", r, g, b); | ||||||
| 	tty->ccolour = xstrdup(ccolour); | 		tty_putcode_ptr1(tty, TTYC_CS, s); | ||||||
|  | 	} | ||||||
|  | 	tty->ccolour = c; | ||||||
| } | } | ||||||
|  |  | ||||||
| static void | static int | ||||||
| tty_update_cursor(struct tty *tty, int mode, int changed, struct screen *s) | tty_update_cursor(struct tty *tty, int mode, struct screen *s) | ||||||
| { | { | ||||||
| 	enum screen_cursor_style cstyle; | 	enum screen_cursor_style	cstyle; | ||||||
|  | 	int				ccolour, changed, cmode = mode; | ||||||
|  |  | ||||||
| 	/* Set cursor colour if changed. */ | 	/* Set cursor colour if changed. */ | ||||||
| 	if (s != NULL && strcmp(s->ccolour, tty->ccolour) != 0) | 	if (s != NULL) { | ||||||
| 		tty_force_cursor_colour(tty, s->ccolour); | 		ccolour = s->ccolour; | ||||||
|  | 		if (s->ccolour == -1) | ||||||
|  | 			ccolour = s->default_ccolour; | ||||||
|  | 		tty_force_cursor_colour(tty, ccolour); | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	/* If cursor is off, set as invisible. */ | 	/* If cursor is off, set as invisible. */ | ||||||
| 	if (~mode & MODE_CURSOR) { | 	if (~cmode & MODE_CURSOR) { | ||||||
| 		if (changed & MODE_CURSOR) | 		if (tty->mode & MODE_CURSOR) | ||||||
| 			tty_putcode(tty, TTYC_CIVIS); | 			tty_putcode(tty, TTYC_CIVIS); | ||||||
| 		return; | 		return (cmode); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	/* Check if blinking or very visible flag changed or style changed. */ | 	/* Check if blinking or very visible flag changed or style changed. */ | ||||||
| 	if (s == NULL) | 	if (s == NULL) | ||||||
| 		cstyle = tty->cstyle; | 		cstyle = tty->cstyle; | ||||||
| 	else | 	else { | ||||||
| 		cstyle = s->cstyle; | 		cstyle = s->cstyle; | ||||||
|  | 		if (cstyle == SCREEN_CURSOR_DEFAULT) { | ||||||
|  | 			if (~cmode & MODE_CURSOR_BLINKING_SET) { | ||||||
|  | 				if (s->default_mode & MODE_CURSOR_BLINKING) | ||||||
|  | 					cmode |= MODE_CURSOR_BLINKING; | ||||||
|  | 				else | ||||||
|  | 					cmode &= ~MODE_CURSOR_BLINKING; | ||||||
|  | 			} | ||||||
|  | 			cstyle = s->default_cstyle; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	/* If nothing changed, do nothing. */ | ||||||
|  | 	changed = cmode ^ tty->mode; | ||||||
| 	if ((changed & CURSOR_MODES) == 0 && cstyle == tty->cstyle) | 	if ((changed & CURSOR_MODES) == 0 && cstyle == tty->cstyle) | ||||||
| 		return; | 		return (cmode); | ||||||
|  |  | ||||||
| 	/* | 	/* | ||||||
| 	 * Set cursor style. If an explicit style has been set with DECSCUSR, | 	 * Set cursor style. If an explicit style has been set with DECSCUSR, | ||||||
| @@ -703,49 +731,56 @@ tty_update_cursor(struct tty *tty, int mode, int changed, struct screen *s) | |||||||
| 			else | 			else | ||||||
| 				tty_putcode1(tty, TTYC_SS, 0); | 				tty_putcode1(tty, TTYC_SS, 0); | ||||||
| 		} | 		} | ||||||
| 		if (mode & (MODE_CURSOR_BLINKING|MODE_CURSOR_VERY_VISIBLE)) | 		if (cmode & (MODE_CURSOR_BLINKING|MODE_CURSOR_VERY_VISIBLE)) | ||||||
| 			tty_putcode(tty, TTYC_CVVIS); | 			tty_putcode(tty, TTYC_CVVIS); | ||||||
| 		break; | 		break; | ||||||
| 	case SCREEN_CURSOR_BLOCK: | 	case SCREEN_CURSOR_BLOCK: | ||||||
| 		if (tty_term_has(tty->term, TTYC_SS)) { | 		if (tty_term_has(tty->term, TTYC_SS)) { | ||||||
| 			if (mode & MODE_CURSOR_BLINKING) | 			if (cmode & MODE_CURSOR_BLINKING) | ||||||
| 				tty_putcode1(tty, TTYC_SS, 1); | 				tty_putcode1(tty, TTYC_SS, 1); | ||||||
| 			else | 			else | ||||||
| 				tty_putcode1(tty, TTYC_SS, 2); | 				tty_putcode1(tty, TTYC_SS, 2); | ||||||
| 		} else if (mode & MODE_CURSOR_BLINKING) | 		} else if (cmode & MODE_CURSOR_BLINKING) | ||||||
| 			tty_putcode(tty, TTYC_CVVIS); | 			tty_putcode(tty, TTYC_CVVIS); | ||||||
| 		break; | 		break; | ||||||
| 	case SCREEN_CURSOR_UNDERLINE: | 	case SCREEN_CURSOR_UNDERLINE: | ||||||
| 		if (tty_term_has(tty->term, TTYC_SS)) { | 		if (tty_term_has(tty->term, TTYC_SS)) { | ||||||
| 			if (mode & MODE_CURSOR_BLINKING) | 			if (cmode & MODE_CURSOR_BLINKING) | ||||||
| 				tty_putcode1(tty, TTYC_SS, 3); | 				tty_putcode1(tty, TTYC_SS, 3); | ||||||
| 			else | 			else | ||||||
| 				tty_putcode1(tty, TTYC_SS, 4); | 				tty_putcode1(tty, TTYC_SS, 4); | ||||||
| 		} else if (mode & MODE_CURSOR_BLINKING) | 		} else if (cmode & MODE_CURSOR_BLINKING) | ||||||
| 			tty_putcode(tty, TTYC_CVVIS); | 			tty_putcode(tty, TTYC_CVVIS); | ||||||
| 		break; | 		break; | ||||||
| 	case SCREEN_CURSOR_BAR: | 	case SCREEN_CURSOR_BAR: | ||||||
| 		if (tty_term_has(tty->term, TTYC_SS)) { | 		if (tty_term_has(tty->term, TTYC_SS)) { | ||||||
| 			if (mode & MODE_CURSOR_BLINKING) | 			if (cmode & MODE_CURSOR_BLINKING) | ||||||
| 				tty_putcode1(tty, TTYC_SS, 5); | 				tty_putcode1(tty, TTYC_SS, 5); | ||||||
| 			else | 			else | ||||||
| 				tty_putcode1(tty, TTYC_SS, 6); | 				tty_putcode1(tty, TTYC_SS, 6); | ||||||
| 		} else if (mode & MODE_CURSOR_BLINKING) | 		} else if (cmode & MODE_CURSOR_BLINKING) | ||||||
| 			tty_putcode(tty, TTYC_CVVIS); | 			tty_putcode(tty, TTYC_CVVIS); | ||||||
| 		break; | 		break; | ||||||
| 	} | 	} | ||||||
| 	tty->cstyle = cstyle; | 	tty->cstyle = cstyle; | ||||||
|  | 	return (cmode); | ||||||
|  } |  } | ||||||
|  |  | ||||||
| void | void | ||||||
| tty_update_mode(struct tty *tty, int mode, struct screen *s) | tty_update_mode(struct tty *tty, int mode, struct screen *s) | ||||||
| { | { | ||||||
|  | 	struct tty_term	*term = tty->term; | ||||||
| 	struct client	*c = tty->client; | 	struct client	*c = tty->client; | ||||||
| 	int		 changed; | 	int		 changed; | ||||||
|  |  | ||||||
| 	if (tty->flags & TTY_NOCURSOR) | 	if (tty->flags & TTY_NOCURSOR) | ||||||
| 		mode &= ~MODE_CURSOR; | 		mode &= ~MODE_CURSOR; | ||||||
|  |  | ||||||
|  | 	if (tty_update_cursor(tty, mode, s) & MODE_CURSOR_BLINKING) | ||||||
|  | 		mode |= MODE_CURSOR_BLINKING; | ||||||
|  | 	else | ||||||
|  | 		mode &= ~MODE_CURSOR_BLINKING; | ||||||
|  |  | ||||||
| 	changed = mode ^ tty->mode; | 	changed = mode ^ tty->mode; | ||||||
| 	if (log_get_level() != 0 && changed != 0) { | 	if (log_get_level() != 0 && changed != 0) { | ||||||
| 		log_debug("%s: current mode %s", c->name, | 		log_debug("%s: current mode %s", c->name, | ||||||
| @@ -754,9 +789,7 @@ tty_update_mode(struct tty *tty, int mode, struct screen *s) | |||||||
| 		    screen_mode_to_string(mode)); | 		    screen_mode_to_string(mode)); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	tty_update_cursor(tty, mode, changed, s); | 	if ((changed & ALL_MOUSE_MODES) && tty_term_has(term, TTYC_KMOUS)) { | ||||||
| 	if ((changed & ALL_MOUSE_MODES) && |  | ||||||
| 	    tty_term_has(tty->term, TTYC_KMOUS)) { |  | ||||||
| 		/* | 		/* | ||||||
| 		 * If the mouse modes have changed, clear any that are set and | 		 * If the mouse modes have changed, clear any that are set and | ||||||
| 		 * apply again. There are differences in how terminals track | 		 * apply again. There are differences in how terminals track | ||||||
| @@ -909,7 +942,9 @@ tty_update_window_offset(struct window *w) | |||||||
| 	struct client	*c; | 	struct client	*c; | ||||||
|  |  | ||||||
| 	TAILQ_FOREACH(c, &clients, entry) { | 	TAILQ_FOREACH(c, &clients, entry) { | ||||||
| 		if (c->session != NULL && c->session->curw->window == w) | 		if (c->session != NULL && | ||||||
|  | 		    c->session->curw != NULL && | ||||||
|  | 		    c->session->curw->window == w) | ||||||
| 			tty_update_client_offset(c); | 			tty_update_client_offset(c); | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| @@ -1051,8 +1086,9 @@ static void | |||||||
| tty_clear_line(struct tty *tty, const struct grid_cell *defaults, u_int py, | tty_clear_line(struct tty *tty, const struct grid_cell *defaults, u_int py, | ||||||
|     u_int px, u_int nx, u_int bg) |     u_int px, u_int nx, u_int bg) | ||||||
| { | { | ||||||
| 	struct client	*c = tty->client; | 	struct client		*c = tty->client; | ||||||
| 	u_int		 i; | 	struct overlay_ranges	 r; | ||||||
|  | 	u_int			 i; | ||||||
|  |  | ||||||
| 	log_debug("%s: %s, %u at %u,%u", __func__, c->name, nx, px, py); | 	log_debug("%s: %s, %u at %u,%u", __func__, c->name, nx, px, py); | ||||||
|  |  | ||||||
| @@ -1088,18 +1124,13 @@ tty_clear_line(struct tty *tty, const struct grid_cell *defaults, u_int py, | |||||||
| 	 * Couldn't use an escape sequence, use spaces. Clear only the visible | 	 * Couldn't use an escape sequence, use spaces. Clear only the visible | ||||||
| 	 * bit if there is an overlay. | 	 * bit if there is an overlay. | ||||||
| 	 */ | 	 */ | ||||||
| 	for (i = 0; i < nx; i++) { | 	tty_check_overlay_range(tty, px, py, nx, &r); | ||||||
| 		if (!tty_check_overlay(tty, px + i, py)) | 	for (i = 0; i < OVERLAY_MAX_RANGES; i++) { | ||||||
| 			break; | 		if (r.nx[i] == 0) | ||||||
|  | 			continue; | ||||||
|  | 		tty_cursor(tty, r.px[i], py); | ||||||
|  | 		tty_repeat_space(tty, r.nx[i]); | ||||||
| 	} | 	} | ||||||
| 	tty_cursor(tty, px, py); |  | ||||||
| 	tty_repeat_space(tty, i); |  | ||||||
| 	for (; i < nx; i++) { |  | ||||||
| 		if (tty_check_overlay(tty, px + i, py)) |  | ||||||
| 			break; |  | ||||||
| 	} |  | ||||||
| 	tty_cursor(tty, px + i, py); |  | ||||||
| 	tty_repeat_space(tty, nx - i); |  | ||||||
| } | } | ||||||
|  |  | ||||||
| /* Clear a line, adjusting to visible part of pane. */ | /* Clear a line, adjusting to visible part of pane. */ | ||||||
| @@ -1311,14 +1342,44 @@ tty_check_codeset(struct tty *tty, const struct grid_cell *gc) | |||||||
| 	return (&new); | 	return (&new); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * Check if a single character is obstructed by the overlay and return a | ||||||
|  |  * boolean. | ||||||
|  |  */ | ||||||
| static int | static int | ||||||
| tty_check_overlay(struct tty *tty, u_int px, u_int py) | tty_check_overlay(struct tty *tty, u_int px, u_int py) | ||||||
|  | { | ||||||
|  | 	struct overlay_ranges	r; | ||||||
|  |  | ||||||
|  | 	/* | ||||||
|  | 	 * A unit width range will always return nx[2] == 0 from a check, even | ||||||
|  | 	 * with multiple overlays, so it's sufficient to check just the first | ||||||
|  | 	 * two entries. | ||||||
|  | 	 */ | ||||||
|  | 	tty_check_overlay_range(tty, px, py, 1, &r); | ||||||
|  | 	if (r.nx[0] + r.nx[1] == 0) | ||||||
|  | 		return (0); | ||||||
|  | 	return (1); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* Return parts of the input range which are visible. */ | ||||||
|  | static void | ||||||
|  | tty_check_overlay_range(struct tty *tty, u_int px, u_int py, u_int nx, | ||||||
|  |     struct overlay_ranges *r) | ||||||
| { | { | ||||||
| 	struct client	*c = tty->client; | 	struct client	*c = tty->client; | ||||||
|  |  | ||||||
| 	if (c->overlay_check == NULL) | 	if (c->overlay_check == NULL) { | ||||||
| 		return (1); | 		r->px[0] = px; | ||||||
| 	return (c->overlay_check(c, c->overlay_data, px, py)); | 		r->nx[0] = nx; | ||||||
|  | 		r->px[1] = 0; | ||||||
|  | 		r->nx[1] = 0; | ||||||
|  | 		r->px[2] = 0; | ||||||
|  | 		r->nx[2] = 0; | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	c->overlay_check(c, c->overlay_data, px, py, nx, r); | ||||||
| } | } | ||||||
|  |  | ||||||
| void | void | ||||||
| @@ -1331,11 +1392,12 @@ tty_draw_line(struct tty *tty, struct screen *s, u_int px, u_int py, u_int nx, | |||||||
| 	const struct grid_cell	*gcp; | 	const struct grid_cell	*gcp; | ||||||
| 	struct grid_line	*gl; | 	struct grid_line	*gl; | ||||||
| 	struct client		*c = tty->client; | 	struct client		*c = tty->client; | ||||||
| 	u_int			 i, j, ux, sx, width, hidden; | 	struct overlay_ranges	 r; | ||||||
|  | 	u_int			 i, j, ux, sx, width, hidden, eux, nxx; | ||||||
|  | 	u_int			 cellsize; | ||||||
| 	int			 flags, cleared = 0, wrapped = 0; | 	int			 flags, cleared = 0, wrapped = 0; | ||||||
| 	char			 buf[512]; | 	char			 buf[512]; | ||||||
| 	size_t			 len; | 	size_t			 len; | ||||||
| 	u_int			 cellsize; |  | ||||||
|  |  | ||||||
| 	log_debug("%s: px=%u py=%u nx=%u atx=%u aty=%u", __func__, | 	log_debug("%s: px=%u py=%u nx=%u atx=%u aty=%u", __func__, | ||||||
| 	    px, py, nx, atx, aty); | 	    px, py, nx, atx, aty); | ||||||
| @@ -1435,29 +1497,31 @@ tty_draw_line(struct tty *tty, struct screen *s, u_int px, u_int py, u_int nx, | |||||||
| 		else | 		else | ||||||
| 			memcpy(&last, gcp, sizeof last); | 			memcpy(&last, gcp, sizeof last); | ||||||
|  |  | ||||||
|  | 		tty_check_overlay_range(tty, atx + ux, aty, gcp->data.width, | ||||||
|  | 		    &r); | ||||||
| 		hidden = 0; | 		hidden = 0; | ||||||
| 		for (j = 0; j < gcp->data.width; j++) { | 		for (j = 0; j < OVERLAY_MAX_RANGES; j++) | ||||||
| 			if (!tty_check_overlay(tty, atx + ux + j, aty)) | 			hidden += r.nx[j]; | ||||||
| 				hidden++; | 		hidden = gcp->data.width - hidden; | ||||||
| 		} |  | ||||||
| 		if (hidden != 0 && hidden == gcp->data.width) { | 		if (hidden != 0 && hidden == gcp->data.width) { | ||||||
| 			if (~gcp->flags & GRID_FLAG_PADDING) | 			if (~gcp->flags & GRID_FLAG_PADDING) | ||||||
| 				ux += gcp->data.width; | 				ux += gcp->data.width; | ||||||
| 		} else if (hidden != 0 || ux + gcp->data.width > nx) { | 		} else if (hidden != 0 || ux + gcp->data.width > nx) { | ||||||
| 			if (~gcp->flags & GRID_FLAG_PADDING) { | 			if (~gcp->flags & GRID_FLAG_PADDING) { | ||||||
| 				tty_attributes(tty, &last, defaults, palette); | 				tty_attributes(tty, &last, defaults, palette); | ||||||
| 				tty_cursor(tty, atx + ux, aty); | 				for (j = 0; j < OVERLAY_MAX_RANGES; j++) { | ||||||
| 				for (j = 0; j < gcp->data.width; j++) { | 					if (r.nx[j] == 0) | ||||||
| 					if (ux > nx) | 						continue; | ||||||
| 						break; | 					/* Effective width drawn so far. */ | ||||||
| 					if (tty_check_overlay(tty, atx + ux, | 					eux = r.px[j] - atx; | ||||||
| 					    aty)) | 					if (eux < nx) { | ||||||
| 						tty_putc(tty, ' '); | 						tty_cursor(tty, r.px[j], aty); | ||||||
| 					else { | 						nxx = nx - eux; | ||||||
| 						tty_cursor(tty, atx + ux + 1, | 						if (r.nx[j] > nxx) | ||||||
| 						    aty); | 							r.nx[j] = nxx; | ||||||
|  | 						tty_repeat_space(tty, r.nx[j]); | ||||||
|  | 						ux = eux + r.nx[j]; | ||||||
| 					} | 					} | ||||||
| 					ux++; |  | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 		} else if (gcp->attr & GRID_ATTR_CHARSET) { | 		} else if (gcp->attr & GRID_ATTR_CHARSET) { | ||||||
| @@ -1963,7 +2027,8 @@ tty_cmd_cell(struct tty *tty, const struct tty_ctx *ctx) | |||||||
| { | { | ||||||
| 	const struct grid_cell	*gcp = ctx->cell; | 	const struct grid_cell	*gcp = ctx->cell; | ||||||
| 	struct screen		*s = ctx->s; | 	struct screen		*s = ctx->s; | ||||||
| 	u_int			 i, px, py; | 	struct overlay_ranges	 r; | ||||||
|  | 	u_int			 px, py, i, vis = 0; | ||||||
|  |  | ||||||
| 	px = ctx->xoff + ctx->ocx - ctx->wox; | 	px = ctx->xoff + ctx->ocx - ctx->wox; | ||||||
| 	py = ctx->yoff + ctx->ocy - ctx->woy; | 	py = ctx->yoff + ctx->ocy - ctx->woy; | ||||||
| @@ -1973,13 +2038,13 @@ tty_cmd_cell(struct tty *tty, const struct tty_ctx *ctx) | |||||||
|  |  | ||||||
| 	/* Handle partially obstructed wide characters. */ | 	/* Handle partially obstructed wide characters. */ | ||||||
| 	if (gcp->data.width > 1) { | 	if (gcp->data.width > 1) { | ||||||
| 		for (i = 0; i < gcp->data.width; i++) { | 		tty_check_overlay_range(tty, px, py, gcp->data.width, &r); | ||||||
| 			if (!tty_check_overlay(tty, px + i, py)) { | 		for (i = 0; i < OVERLAY_MAX_RANGES; i++) | ||||||
| 				tty_draw_line(tty, s, s->cx, s->cy, | 			vis += r.nx[i]; | ||||||
| 				    gcp->data.width, px, py, &ctx->defaults, | 		if (vis < gcp->data.width) { | ||||||
| 				    ctx->palette); | 			tty_draw_line(tty, s, s->cx, s->cy, gcp->data.width, | ||||||
| 				return; | 			    px, py, &ctx->defaults, ctx->palette); | ||||||
| 			} | 			return; | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| @@ -1997,7 +2062,9 @@ tty_cmd_cell(struct tty *tty, const struct tty_ctx *ctx) | |||||||
| void | void | ||||||
| tty_cmd_cells(struct tty *tty, const struct tty_ctx *ctx) | tty_cmd_cells(struct tty *tty, const struct tty_ctx *ctx) | ||||||
| { | { | ||||||
| 	u_int	i, hide = 0; | 	struct overlay_ranges	 r; | ||||||
|  | 	u_int			 i, px, py, cx; | ||||||
|  | 	char			*cp = ctx->ptr; | ||||||
|  |  | ||||||
| 	if (!tty_is_visible(tty, ctx, ctx->ocx, ctx->ocy, ctx->num, 1)) | 	if (!tty_is_visible(tty, ctx, ctx->ocx, ctx->ocy, ctx->num, 1)) | ||||||
| 		return; | 		return; | ||||||
| @@ -2020,20 +2087,21 @@ tty_cmd_cells(struct tty *tty, const struct tty_ctx *ctx) | |||||||
|  |  | ||||||
| 	tty_margin_off(tty); | 	tty_margin_off(tty); | ||||||
| 	tty_cursor_pane_unless_wrap(tty, ctx, ctx->ocx, ctx->ocy); | 	tty_cursor_pane_unless_wrap(tty, ctx, ctx->ocx, ctx->ocy); | ||||||
|  |  | ||||||
| 	tty_attributes(tty, ctx->cell, &ctx->defaults, ctx->palette); | 	tty_attributes(tty, ctx->cell, &ctx->defaults, ctx->palette); | ||||||
| 	for (i = 0; i < ctx->num; i++) { |  | ||||||
| 		if (!tty_check_overlay(tty, tty->cx + i, tty->cy)) | 	/* Get tty position from pane position for overlay check. */ | ||||||
| 			break; | 	px = ctx->xoff + ctx->ocx - ctx->wox; | ||||||
|  | 	py = ctx->yoff + ctx->ocy - ctx->woy; | ||||||
|  |  | ||||||
|  | 	tty_check_overlay_range(tty, px, py, ctx->num, &r); | ||||||
|  | 	for (i = 0; i < OVERLAY_MAX_RANGES; i++) { | ||||||
|  | 		if (r.nx[i] == 0) | ||||||
|  | 			continue; | ||||||
|  | 		/* Convert back to pane position for printing. */ | ||||||
|  | 		cx = r.px[i] - ctx->xoff + ctx->wox; | ||||||
|  | 		tty_cursor_pane_unless_wrap(tty, ctx, cx, ctx->ocy); | ||||||
|  | 		tty_putn(tty, cp + r.px[i] - px, r.nx[i], r.nx[i]); | ||||||
| 	} | 	} | ||||||
| 	tty_putn(tty, ctx->ptr, i, i); |  | ||||||
| 	for (; i < ctx->num; i++) { |  | ||||||
| 		if (tty_check_overlay(tty, tty->cx + hide, tty->cy)) |  | ||||||
| 			break; |  | ||||||
| 		hide++; |  | ||||||
| 	} |  | ||||||
| 	tty_cursor(tty, tty->cx + hide, tty->cy); |  | ||||||
| 	tty_putn(tty, (char *)ctx->ptr + i, ctx->num - i, ctx->num - i); |  | ||||||
| } | } | ||||||
|  |  | ||||||
| void | void | ||||||
| @@ -2321,17 +2389,25 @@ tty_cursor(struct tty *tty, u_int cx, u_int cy) | |||||||
| 	if (tty->flags & TTY_BLOCK) | 	if (tty->flags & TTY_BLOCK) | ||||||
| 		return; | 		return; | ||||||
|  |  | ||||||
| 	if (cx > tty->sx - 1) |  | ||||||
| 		cx = tty->sx - 1; |  | ||||||
|  |  | ||||||
| 	thisx = tty->cx; | 	thisx = tty->cx; | ||||||
| 	thisy = tty->cy; | 	thisy = tty->cy; | ||||||
|  |  | ||||||
|  | 	/* | ||||||
|  | 	 * If in the automargin space, and want to be there, do not move. | ||||||
|  | 	 * Otherwise, force the cursor to be in range (and complain). | ||||||
|  | 	 */ | ||||||
|  | 	if (cx == thisx && cy == thisy && cx == tty->sx) | ||||||
|  | 		return; | ||||||
|  | 	if (cx > tty->sx - 1) { | ||||||
|  | 		log_debug("%s: x too big %u > %u", __func__, cx, tty->sx - 1); | ||||||
|  | 		cx = tty->sx - 1; | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	/* No change. */ | 	/* No change. */ | ||||||
| 	if (cx == thisx && cy == thisy) | 	if (cx == thisx && cy == thisy) | ||||||
| 		return; | 		return; | ||||||
|  |  | ||||||
| 	/* Very end of the line, just use absolute movement. */ | 	/* Currently at the very end of the line - use absolute movement. */ | ||||||
| 	if (thisx > tty->sx - 1) | 	if (thisx > tty->sx - 1) | ||||||
| 		goto absolute; | 		goto absolute; | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										15
									
								
								utf8.c
									
									
									
									
									
								
							
							
						
						
									
										15
									
								
								utf8.c
									
									
									
									
									
								
							| @@ -237,21 +237,6 @@ utf8_width(struct utf8_data *ud, int *width) | |||||||
| 	if (*width >= 0 && *width <= 0xff) | 	if (*width >= 0 && *width <= 0xff) | ||||||
| 		return (UTF8_DONE); | 		return (UTF8_DONE); | ||||||
| 	log_debug("UTF-8 %.*s, wcwidth() %d", (int)ud->size, ud->data, *width); | 	log_debug("UTF-8 %.*s, wcwidth() %d", (int)ud->size, ud->data, *width); | ||||||
|  |  | ||||||
| #ifndef __OpenBSD__ |  | ||||||
| 	/* |  | ||||||
| 	 * Many platforms (particularly and inevitably OS X) have no width for |  | ||||||
| 	 * relatively common characters (wcwidth() returns -1); assume width 1 |  | ||||||
| 	 * in this case. This will be wrong for genuinely nonprintable |  | ||||||
| 	 * characters, but they should be rare. We may pass through stuff that |  | ||||||
| 	 * ideally we would block, but this is no worse than sending the same |  | ||||||
| 	 * to the terminal without tmux. |  | ||||||
| 	 */ |  | ||||||
| 	if (*width < 0) { |  | ||||||
| 		*width = 1; |  | ||||||
| 		return (UTF8_DONE); |  | ||||||
| 	} |  | ||||||
| #endif |  | ||||||
| 	return (UTF8_ERROR); | 	return (UTF8_ERROR); | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -4531,8 +4531,8 @@ window_copy_pipe_run(struct window_mode_entry *wme, struct session *s, | |||||||
| 	if (cmd == NULL || *cmd == '\0') | 	if (cmd == NULL || *cmd == '\0') | ||||||
| 		cmd = options_get_string(global_options, "copy-command"); | 		cmd = options_get_string(global_options, "copy-command"); | ||||||
| 	if (cmd != NULL && *cmd != '\0') { | 	if (cmd != NULL && *cmd != '\0') { | ||||||
| 		job = job_run(cmd, 0, NULL, s, NULL, NULL, NULL, NULL, NULL, | 		job = job_run(cmd, 0, NULL, NULL, s, NULL, NULL, NULL, NULL, | ||||||
| 		    JOB_NOWAIT, -1, -1); | 		    NULL, JOB_NOWAIT, -1, -1); | ||||||
| 		bufferevent_write(job_get_event(job), buf, *len); | 		bufferevent_write(job_get_event(job), buf, *len); | ||||||
| 	} | 	} | ||||||
| 	return (buf); | 	return (buf); | ||||||
|   | |||||||
| @@ -398,11 +398,11 @@ window_customize_build_options(struct window_customize_modedata *data, | |||||||
|  |  | ||||||
| 	for (i = 0; i < size; i++) { | 	for (i = 0; i < size; i++) { | ||||||
| 		if (oo2 != NULL) | 		if (oo2 != NULL) | ||||||
| 			o = options_get(oo0, list[i]); | 			o = options_get(oo2, list[i]); | ||||||
| 		if (o == NULL && oo1 != NULL) | 		if (o == NULL && oo1 != NULL) | ||||||
| 			o = options_get(oo1, list[i]); | 			o = options_get(oo1, list[i]); | ||||||
| 		if (o == NULL) | 		if (o == NULL) | ||||||
| 			o = options_get(oo2, list[i]); | 			o = options_get(oo0, list[i]); | ||||||
| 		if (options_owner(o) == oo2) | 		if (options_owner(o) == oo2) | ||||||
| 			scope = scope2; | 			scope = scope2; | ||||||
| 		else if (options_owner(o) == oo1) | 		else if (options_owner(o) == oo1) | ||||||
|   | |||||||
| @@ -519,7 +519,8 @@ window_tree_draw_label(struct screen_write_ctx *ctx, u_int px, u_int py, | |||||||
|  |  | ||||||
| 	if (ox > 1 && ox + len < sx - 1 && sy >= 3) { | 	if (ox > 1 && ox + len < sx - 1 && sy >= 3) { | ||||||
| 		screen_write_cursormove(ctx, px + ox - 1, py + oy - 1, 0); | 		screen_write_cursormove(ctx, px + ox - 1, py + oy - 1, 0); | ||||||
| 		screen_write_box(ctx, len + 2, 3); | 		screen_write_box(ctx, len + 2, 3, BOX_LINES_DEFAULT, NULL, | ||||||
|  | 		    NULL); | ||||||
| 	} | 	} | ||||||
| 	screen_write_cursormove(ctx, px + ox, py + oy, 0); | 	screen_write_cursormove(ctx, px + ox, py + oy, 0); | ||||||
| 	screen_write_puts(ctx, gc, "%s", label); | 	screen_write_puts(ctx, gc, "%s", label); | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Nicholas Marriott
					Nicholas Marriott