mirror of
				https://github.com/tmux/tmux.git
				synced 2025-10-26 12:27:15 +00:00 
			
		
		
		
	Major reorganisation of screen handling.
This commit is contained in:
		
							
								
								
									
										10
									
								
								CHANGES
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								CHANGES
									
									
									
									
									
								
							| @@ -1,3 +1,11 @@ | ||||
| 06 December 2007 | ||||
|  | ||||
| * Another major reorganisation, this time of screen handling. A new set of | ||||
|   functions, screen_write_*, are now used to write to a screen and a tty | ||||
|   simultaneously. These are used by the input parser to update the base | ||||
|   window screen and also by the different modes which now interpose their own | ||||
|   screen. | ||||
|  | ||||
| 30 November 2007 | ||||
|  | ||||
| * Support \ek...\e\ to set window name. | ||||
| @@ -289,4 +297,4 @@ | ||||
|   (including mutt, emacs). No status bar yet and no key remapping or other | ||||
|   customisation. | ||||
|  | ||||
| $Id: CHANGES,v 1.89 2007-11-30 11:08:34 nicm Exp $ | ||||
| $Id: CHANGES,v 1.90 2007-12-06 09:46:21 nicm Exp $ | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| # $Id: GNUmakefile,v 1.8 2007-11-25 22:08:13 nicm Exp $ | ||||
| # $Id: GNUmakefile,v 1.9 2007-12-06 09:46:21 nicm Exp $ | ||||
|  | ||||
| .PHONY: clean | ||||
|  | ||||
|   | ||||
							
								
								
									
										4
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								Makefile
									
									
									
									
									
								
							| @@ -1,4 +1,4 @@ | ||||
| # $Id: Makefile,v 1.51 2007-11-30 13:59:16 nicm Exp $ | ||||
| # $Id: Makefile,v 1.52 2007-12-06 09:46:21 nicm Exp $ | ||||
|  | ||||
| .SUFFIXES: .c .o .y .h | ||||
| .PHONY: clean update-index.html upload-index.html | ||||
| @@ -28,7 +28,7 @@ SRCS= tmux.c server.c server-msg.c server-fn.c buffer.c buffer-poll.c status.c \ | ||||
|       cmd-swap-window.c cmd-rename-session.c cmd-kill-session.c \ | ||||
|       cmd-switch-client.c cmd-has-session.c cmd-scroll-mode.c cmd-copy-mode.c \ | ||||
|       cmd-paste-buffer.c window-scroll.c window-more.c window-copy.c \ | ||||
|       tty.c tty-keys.c tty-write.c | ||||
|       tty.c tty-keys.c tty-write.c screen-write.c screen-redraw.c | ||||
|  | ||||
| CC?= cc | ||||
| INCDIRS+= -I. -I- -I/usr/local/include | ||||
|   | ||||
							
								
								
									
										16
									
								
								TODO
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								TODO
									
									
									
									
									
								
							| @@ -66,13 +66,27 @@ | ||||
|  | ||||
| -- For 0.2 -------------------------------------------------------------------- | ||||
| - window splitting? | ||||
| - restore term cap checks | ||||
| - restore term cap checks **** | ||||
| - anything which uses cmd_{send,recv}_string will break if the string is | ||||
|   split. string length should be part of the command size | ||||
| - echo \\033[35\;46m\\033[2J last line quirk (with C-b r) | ||||
| - quick intro section (tmux new/attach/detach) etc | ||||
| - is ACS the right way round?? | ||||
|  | ||||
| -------- | ||||
|  | ||||
| screen redraw. | ||||
|  | ||||
| ops: | ||||
| - redraw screen or section of screen to tty without altering it | ||||
| 	(screen-redraw.c, screen_redraw_ctx) | ||||
| 	(switching screen etc) | ||||
| - draw to screen and optionally tty | ||||
| 	(window output) | ||||
| 	(screen-write.c, screen_write_ctx) | ||||
| - copy line/column from one screen (inc history) at offset?? | ||||
| 	(scroll/copy mode) | ||||
|  | ||||
| -------- | ||||
| kmous -- \E[M | ||||
|  | ||||
|   | ||||
							
								
								
									
										2
									
								
								buffer.c
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								buffer.c
									
									
									
									
									
								
							| @@ -1,4 +1,4 @@ | ||||
| /* $Id: buffer.c,v 1.3 2007-11-27 19:23:33 nicm Exp $ */ | ||||
| /* $Id: buffer.c,v 1.4 2007-12-06 09:46:21 nicm Exp $ */ | ||||
|  | ||||
| /* | ||||
|  * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| /* $Id: client-msg.c,v 1.13 2007-11-27 20:03:08 nicm Exp $ */ | ||||
| /* $Id: client-msg.c,v 1.14 2007-12-06 09:46:21 nicm Exp $ */ | ||||
|  | ||||
| /* | ||||
|  * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> | ||||
|   | ||||
							
								
								
									
										2
									
								
								client.c
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								client.c
									
									
									
									
									
								
							| @@ -1,4 +1,4 @@ | ||||
| /* $Id: client.c,v 1.24 2007-12-01 11:10:33 nicm Exp $ */ | ||||
| /* $Id: client.c,v 1.25 2007-12-06 09:46:21 nicm Exp $ */ | ||||
|  | ||||
| /* | ||||
|  * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| /* $Id: cmd-attach-session.c,v 1.10 2007-11-27 19:23:33 nicm Exp $ */ | ||||
| /* $Id: cmd-attach-session.c,v 1.11 2007-12-06 09:46:21 nicm Exp $ */ | ||||
|  | ||||
| /* | ||||
|  * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| /* $Id: cmd-bind-key.c,v 1.7 2007-11-16 21:12:31 nicm Exp $ */ | ||||
| /* $Id: cmd-bind-key.c,v 1.8 2007-12-06 09:46:21 nicm Exp $ */ | ||||
|  | ||||
| /* | ||||
|  * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| /* $Id: cmd-copy-mode.c,v 1.2 2007-11-27 19:23:33 nicm Exp $ */ | ||||
| /* $Id: cmd-copy-mode.c,v 1.3 2007-12-06 09:46:21 nicm Exp $ */ | ||||
|  | ||||
| /* | ||||
|  * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| /* $Id: cmd-kill-session.c,v 1.4 2007-11-21 13:11:41 nicm Exp $ */ | ||||
| /* $Id: cmd-kill-session.c,v 1.5 2007-12-06 09:46:21 nicm Exp $ */ | ||||
|  | ||||
| /* | ||||
|  * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| /* $Id: cmd-kill-window.c,v 1.6 2007-11-16 21:12:31 nicm Exp $ */ | ||||
| /* $Id: cmd-kill-window.c,v 1.7 2007-12-06 09:46:21 nicm Exp $ */ | ||||
|  | ||||
| /* | ||||
|  * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| /* $Id: cmd-last-window.c,v 1.5 2007-11-16 21:12:31 nicm Exp $ */ | ||||
| /* $Id: cmd-last-window.c,v 1.6 2007-12-06 09:46:21 nicm Exp $ */ | ||||
|  | ||||
| /* | ||||
|  * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| /* $Id: cmd-link-window.c,v 1.8 2007-11-21 15:05:53 nicm Exp $ */ | ||||
| /* $Id: cmd-link-window.c,v 1.9 2007-12-06 09:46:21 nicm Exp $ */ | ||||
|  | ||||
| /* | ||||
|  * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| /* $Id: cmd-list-windows.c,v 1.14 2007-11-23 13:11:43 nicm Exp $ */ | ||||
| /* $Id: cmd-list-windows.c,v 1.15 2007-12-06 09:46:21 nicm Exp $ */ | ||||
|  | ||||
| /* | ||||
|  * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> | ||||
| @@ -51,18 +51,18 @@ cmd_list_windows_exec(unused void *ptr, struct cmd_ctx *ctx) | ||||
| 		w = wl->window; | ||||
|  | ||||
| 		size = 0; | ||||
| 		for (i = 0; i < w->screen.hsize; i++) | ||||
| 			size += w->screen.grid_size[i] * 3; | ||||
| 		size += w->screen.hsize * (sizeof *w->screen.grid_data); | ||||
| 		size += w->screen.hsize * (sizeof *w->screen.grid_attr); | ||||
| 		size += w->screen.hsize * (sizeof *w->screen.grid_colr); | ||||
| 		size += w->screen.hsize * (sizeof *w->screen.grid_size); | ||||
| 		for (i = 0; i < w->base.hsize; i++) | ||||
| 			size += w->base.grid_size[i] * 3; | ||||
| 		size += w->base.hsize * (sizeof *w->base.grid_data); | ||||
| 		size += w->base.hsize * (sizeof *w->base.grid_attr); | ||||
| 		size += w->base.hsize * (sizeof *w->base.grid_colr); | ||||
| 		size += w->base.hsize * (sizeof *w->base.grid_size); | ||||
|  | ||||
| 		ctx->print(ctx, | ||||
| 		    "%d: %s \"%s\" (%s) [%ux%u] [history %u/%u, %llu bytes]", | ||||
| 		    wl->idx, w->name, w->screen.title, ttyname(w->fd), | ||||
| 		    screen_size_x(&w->screen), screen_size_y(&w->screen), | ||||
| 		    w->screen.hsize, w->screen.hlimit, size); | ||||
| 		    wl->idx, w->name, w->base.title, ttyname(w->fd), | ||||
| 		    screen_size_x(&w->base), screen_size_y(&w->base), | ||||
| 		    w->base.hsize, w->base.hlimit, size); | ||||
| 	} | ||||
|  | ||||
| 	if (ctx->cmdclient != NULL) | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| /* $Id: cmd-new-session.c,v 1.18 2007-11-27 19:23:33 nicm Exp $ */ | ||||
| /* $Id: cmd-new-session.c,v 1.19 2007-12-06 09:46:21 nicm Exp $ */ | ||||
|  | ||||
| /* | ||||
|  * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| /* $Id: cmd-new-window.c,v 1.13 2007-11-16 21:12:31 nicm Exp $ */ | ||||
| /* $Id: cmd-new-window.c,v 1.14 2007-12-06 09:46:22 nicm Exp $ */ | ||||
|  | ||||
| /* | ||||
|  * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| /* $Id: cmd-next-window.c,v 1.5 2007-11-16 21:12:31 nicm Exp $ */ | ||||
| /* $Id: cmd-next-window.c,v 1.6 2007-12-06 09:46:22 nicm Exp $ */ | ||||
|  | ||||
| /* | ||||
|  * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| /* $Id: cmd-paste-buffer.c,v 1.1 2007-11-23 17:52:54 nicm Exp $ */ | ||||
| /* $Id: cmd-paste-buffer.c,v 1.2 2007-12-06 09:46:22 nicm Exp $ */ | ||||
|  | ||||
| /* | ||||
|  * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| /* $Id: cmd-previous-window.c,v 1.5 2007-11-16 21:12:31 nicm Exp $ */ | ||||
| /* $Id: cmd-previous-window.c,v 1.6 2007-12-06 09:46:22 nicm Exp $ */ | ||||
|  | ||||
| /* | ||||
|  * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| /* $Id: cmd-rename-session.c,v 1.3 2007-11-16 21:12:31 nicm Exp $ */ | ||||
| /* $Id: cmd-rename-session.c,v 1.4 2007-12-06 09:46:22 nicm Exp $ */ | ||||
|  | ||||
| /* | ||||
|  * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| /* $Id: cmd-rename-window.c,v 1.13 2007-11-16 21:12:31 nicm Exp $ */ | ||||
| /* $Id: cmd-rename-window.c,v 1.14 2007-12-06 09:46:22 nicm Exp $ */ | ||||
|  | ||||
| /* | ||||
|  * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| /* $Id: cmd-scroll-mode.c,v 1.4 2007-11-27 19:23:33 nicm Exp $ */ | ||||
| /* $Id: cmd-scroll-mode.c,v 1.5 2007-12-06 09:46:22 nicm Exp $ */ | ||||
|  | ||||
| /* | ||||
|  * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| /* $Id: cmd-select-window.c,v 1.10 2007-11-16 21:12:31 nicm Exp $ */ | ||||
| /* $Id: cmd-select-window.c,v 1.11 2007-12-06 09:46:22 nicm Exp $ */ | ||||
|  | ||||
| /* | ||||
|  * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| /* $Id: cmd-send-prefix.c,v 1.6 2007-11-21 13:11:41 nicm Exp $ */ | ||||
| /* $Id: cmd-send-prefix.c,v 1.7 2007-12-06 09:46:22 nicm Exp $ */ | ||||
|  | ||||
| /* | ||||
|  * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| /* $Id: cmd-set-option.c,v 1.14 2007-11-23 12:48:20 nicm Exp $ */ | ||||
| /* $Id: cmd-set-option.c,v 1.15 2007-12-06 09:46:22 nicm Exp $ */ | ||||
|  | ||||
| /* | ||||
|  * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| /* $Id: cmd-swap-window.c,v 1.3 2007-11-16 21:12:31 nicm Exp $ */ | ||||
| /* $Id: cmd-swap-window.c,v 1.4 2007-12-06 09:46:22 nicm Exp $ */ | ||||
|  | ||||
| /* | ||||
|  * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| /* $Id: cmd-switch-client.c,v 1.1 2007-11-16 21:31:03 nicm Exp $ */ | ||||
| /* $Id: cmd-switch-client.c,v 1.2 2007-12-06 09:46:22 nicm Exp $ */ | ||||
|  | ||||
| /* | ||||
|  * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| /* $Id: cmd-unbind-key.c,v 1.7 2007-11-16 21:12:31 nicm Exp $ */ | ||||
| /* $Id: cmd-unbind-key.c,v 1.8 2007-12-06 09:46:22 nicm Exp $ */ | ||||
|  | ||||
| /* | ||||
|  * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| /* $Id: cmd-unlink-window.c,v 1.4 2007-11-16 21:12:31 nicm Exp $ */ | ||||
| /* $Id: cmd-unlink-window.c,v 1.5 2007-12-06 09:46:22 nicm Exp $ */ | ||||
|  | ||||
| /* | ||||
|  * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> | ||||
|   | ||||
							
								
								
									
										2
									
								
								cmd.c
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								cmd.c
									
									
									
									
									
								
							| @@ -1,4 +1,4 @@ | ||||
| /* $Id: cmd.c,v 1.32 2007-11-23 17:52:54 nicm Exp $ */ | ||||
| /* $Id: cmd.c,v 1.33 2007-12-06 09:46:22 nicm Exp $ */ | ||||
|  | ||||
| /* | ||||
|  * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> | ||||
|   | ||||
							
								
								
									
										344
									
								
								input.c
									
									
									
									
									
								
							
							
						
						
									
										344
									
								
								input.c
									
									
									
									
									
								
							| @@ -1,4 +1,4 @@ | ||||
| /* $Id: input.c,v 1.43 2007-11-30 11:08:35 nicm Exp $ */ | ||||
| /* $Id: input.c,v 1.44 2007-12-06 09:46:22 nicm Exp $ */ | ||||
|  | ||||
| /* | ||||
|  * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> | ||||
| @@ -43,7 +43,6 @@ void	 input_abort_string(struct input_ctx *); | ||||
| int	 input_add_string(struct input_ctx *, u_char); | ||||
| char	*input_get_string(struct input_ctx *); | ||||
|  | ||||
| void	 input_write(struct input_ctx *, int, ...); | ||||
| void	 input_state(struct input_ctx *, void *); | ||||
|  | ||||
| void	 input_state_first(u_char, struct input_ctx *); | ||||
| @@ -85,13 +84,6 @@ void	 input_handle_sequence_decstbm(struct input_ctx *); | ||||
| void	 input_handle_sequence_sgr(struct input_ctx *); | ||||
| void	 input_handle_sequence_dsr(struct input_ctx *); | ||||
|  | ||||
| #define input_limit(v, lower, upper) do {	\ | ||||
| 	if (v < lower)				\ | ||||
| 		v = lower;			\ | ||||
| 	if (v > upper)				\ | ||||
| 		v = upper;			\ | ||||
| } while (0) | ||||
|  | ||||
| int | ||||
| input_new_argument(struct input_ctx *ictx) | ||||
| { | ||||
| @@ -183,19 +175,6 @@ input_get_string(struct input_ctx *ictx) | ||||
| 	return (s); | ||||
| } | ||||
|  | ||||
| void | ||||
| input_write(struct input_ctx *ictx, int cmd, ...) | ||||
| { | ||||
| 	va_list	ap; | ||||
|  | ||||
| 	if (ictx->w->screen.mode & (MODE_HIDDEN|MODE_BACKGROUND)) | ||||
| 		return; | ||||
|  | ||||
| 	va_start(ap, cmd); | ||||
| 	tty_vwrite_window(ictx->w, cmd, ap); | ||||
| 	va_end(ap); | ||||
| } | ||||
|  | ||||
| void | ||||
| input_state(struct input_ctx *ictx, void *state) | ||||
| { | ||||
| @@ -239,11 +218,18 @@ input_parse(struct window *w) | ||||
|  | ||||
| 	log_debug2("entry; buffer=%zu", ictx->len); | ||||
|  | ||||
| 	if (w->mode == NULL) | ||||
| 		screen_write_start(&ictx->ctx, &w->base, tty_write_window, w); | ||||
| 	else | ||||
| 		screen_write_start(&ictx->ctx, &w->base, NULL, NULL); | ||||
|  | ||||
| 	while (ictx->off < ictx->len) { | ||||
| 		ch = ictx->buf[ictx->off++]; | ||||
| 		ictx->state(ch, ictx); | ||||
| 	} | ||||
|  | ||||
| 	screen_write_stop(&ictx->ctx); | ||||
|  | ||||
| 	buffer_remove(w->in, ictx->len); | ||||
| } | ||||
|  | ||||
| @@ -345,13 +331,10 @@ input_state_title_second(u_char ch, struct input_ctx *ictx) | ||||
| void | ||||
| input_state_title_next(u_char ch, struct input_ctx *ictx) | ||||
| { | ||||
| 	struct screen	*s = &ictx->w->screen; | ||||
|  | ||||
| 	if (ch == '\007') { | ||||
| 		if (ictx->string_type == STRING_TITLE) { | ||||
| 			xfree(s->title); | ||||
| 			s->title = input_get_string(ictx); | ||||
| 			input_write(ictx, TTY_TITLE, s->title); | ||||
| 			screen_write_set_title( | ||||
| 			    &ictx->ctx, input_get_string(ictx)); | ||||
| 		} else | ||||
| 			input_abort_string(ictx); | ||||
| 		input_state(ictx, input_state_first); | ||||
| @@ -496,82 +479,63 @@ input_state_string_escape(u_char ch, struct input_ctx *ictx) | ||||
| void | ||||
| input_handle_character(u_char ch, struct input_ctx *ictx) | ||||
| { | ||||
| 	struct screen	*s = &ictx->w->screen; | ||||
|  | ||||
| 	log_debug2("-- ch %zu: %hhu (%c)", ictx->off, ch, ch); | ||||
|  | ||||
| 	if (s->cx == screen_size_x(s)) { | ||||
| 		input_write(ictx, TTY_CHARACTER, '\r'); | ||||
| 		input_write(ictx, TTY_CHARACTER, '\n'); | ||||
|  | ||||
| 		s->cx = 0; | ||||
| 		screen_display_cursor_down(s); | ||||
| 	} else if (!screen_in_x(s, s->cx) || !screen_in_y(s, s->cy)) | ||||
| 		return; | ||||
|  | ||||
| 	screen_display_cursor_set(s, ch); | ||||
| 	input_write(ictx, TTY_CHARACTER, ch); | ||||
|  | ||||
| 	s->cx++; | ||||
| 	screen_write_put_character(&ictx->ctx, ch); | ||||
| } | ||||
|  | ||||
| void | ||||
| input_handle_c0_control(u_char ch, struct input_ctx *ictx) | ||||
| { | ||||
| 	struct screen	*s = &ictx->w->screen; | ||||
| 	struct screen	*s = ictx->ctx.s; | ||||
|  | ||||
| 	log_debug2("-- c0 %zu: %hhu", ictx->off, ch); | ||||
|  | ||||
| 	switch (ch) { | ||||
| 	case '\0':	/* NUL */ | ||||
| 		return; | ||||
| 		break; | ||||
| 	case '\n':	/* LF */ | ||||
|  		screen_display_cursor_down(s); | ||||
| 		screen_write_cursor_down_scroll(&ictx->ctx); | ||||
| 		break; | ||||
| 	case '\r':	/* CR */ | ||||
| 		s->cx = 0; | ||||
| 		screen_write_move_cursor(&ictx->ctx, 0, s->cy); | ||||
| 		break; | ||||
| 	case '\007':	/* BELL */ | ||||
| 		ictx->w->flags |= WINDOW_BELL; | ||||
| 		return; | ||||
| 		break; | ||||
| 	case '\010': 	/* BS */ | ||||
| 		if (s->cx > 0) | ||||
| 			s->cx--; | ||||
| 		screen_write_cursor_left(&ictx->ctx, 1); | ||||
| 		break; | ||||
| 	case '\011': 	/* TAB */ | ||||
| 		s->cx = ((s->cx / 8) * 8) + 8; | ||||
| 		if (s->cx > screen_last_x(s)) { | ||||
| 			s->cx = 0; | ||||
| 			screen_display_cursor_down(s); | ||||
| 			screen_write_cursor_down(&ictx->ctx, 1); | ||||
| 		} | ||||
| 		input_write(ictx, TTY_CURSORMOVE, s->cy, s->cx); | ||||
| 		return; | ||||
| 		screen_write_move_cursor(&ictx->ctx, s->cx, s->cy); | ||||
| 		break; | ||||
| 	case '\016':	/* SO */ | ||||
| 		s->attr |= ATTR_CHARSET; | ||||
| 		input_write(ictx, TTY_ATTRIBUTES, s->attr, s->colr); | ||||
| 		return; | ||||
| 		screen_write_set_attributes(&ictx->ctx, s->attr, s->colr); | ||||
| 		break; | ||||
| 	case '\017':	/* SI */ | ||||
| 		s->attr &= ~ATTR_CHARSET; | ||||
| 		input_write(ictx, TTY_ATTRIBUTES, s->attr, s->colr); | ||||
| 		return; | ||||
| 		screen_write_set_attributes(&ictx->ctx, s->attr, s->colr); | ||||
| 		break; | ||||
| 	default: | ||||
| 		log_debug("unknown c0: %hhu", ch); | ||||
| 		return; | ||||
| 		break; | ||||
| 	} | ||||
| 	input_write(ictx, TTY_CHARACTER, ch); | ||||
| } | ||||
|  | ||||
| void | ||||
| input_handle_c1_control(u_char ch, struct input_ctx *ictx) | ||||
| { | ||||
| 	struct screen	*s = &ictx->w->screen; | ||||
|  | ||||
| 	log_debug2("-- c1 %zu: %hhu (%c)", ictx->off, ch, ch); | ||||
|  | ||||
| 	switch (ch) { | ||||
| 	case 'M':	/* RI */ | ||||
| 		screen_display_cursor_up(s); | ||||
| 		input_write(ictx, TTY_REVERSEINDEX); | ||||
| 		screen_write_cursor_up_scroll(&ictx->ctx); | ||||
| 		break; | ||||
| 	default: | ||||
| 		log_debug("unknown c1: %hhu", ch); | ||||
| @@ -582,16 +546,16 @@ input_handle_c1_control(u_char ch, struct input_ctx *ictx) | ||||
| void | ||||
| input_handle_private_two(u_char ch, struct input_ctx *ictx) | ||||
| { | ||||
| 	struct screen	*s = &ictx->w->screen; | ||||
| 	struct screen	*s = ictx->ctx.s; | ||||
|  | ||||
| 	log_debug2("-- p2 %zu: %hhu (%c)", ictx->off, ch, ch); | ||||
|  | ||||
| 	switch (ch) { | ||||
| 	case '=':	/* DECKPAM */ | ||||
| 		input_write(ictx, TTY_KKEYPADON); | ||||
| 		screen_write_set_mode(&ictx->ctx, MODE_KKEYPAD); | ||||
| 		break; | ||||
| 	case '>':	/* DECKPNM*/ | ||||
| 		input_write(ictx, TTY_KKEYPADOFF); | ||||
| 		screen_write_clear_mode(&ictx->ctx, MODE_KKEYPAD); | ||||
| 		break; | ||||
| 	case '7':	/* DECSC */ | ||||
| 		s->saved_cx = s->cx; | ||||
| @@ -607,8 +571,8 @@ input_handle_private_two(u_char ch, struct input_ctx *ictx) | ||||
| 		s->cy = s->saved_cy; | ||||
| 		s->attr = s->saved_attr; | ||||
| 		s->colr = s->saved_colr; | ||||
| 		input_write(ictx, TTY_ATTRIBUTES, s->attr, s->colr); | ||||
| 		input_write(ictx, TTY_CURSORMOVE, s->cy, s->cx); | ||||
| 		screen_write_set_attributes(&ictx->ctx, s->attr, s->colr); | ||||
| 		screen_write_move_cursor(&ictx->ctx, s->cx, s->cy); | ||||
| 		break; | ||||
| 	default: | ||||
| 		log_debug("unknown p2: %hhu", ch); | ||||
| @@ -659,7 +623,7 @@ input_handle_sequence(u_char ch, struct input_ctx *ictx) | ||||
| 		{ 'n', input_handle_sequence_dsr }, | ||||
| 		{ 'r', input_handle_sequence_decstbm }, | ||||
| 	}; | ||||
| 	struct screen	 *s = &ictx->w->screen; | ||||
| 	struct screen	 *s = ictx->ctx.s; | ||||
| 	u_int		  i; | ||||
| 	struct input_arg *iarg; | ||||
|  | ||||
| @@ -687,7 +651,6 @@ input_handle_sequence(u_char ch, struct input_ctx *ictx) | ||||
| void | ||||
| input_handle_sequence_cuu(struct input_ctx *ictx) | ||||
| { | ||||
| 	struct screen	*s = &ictx->w->screen; | ||||
| 	uint16_t	n; | ||||
|  | ||||
| 	if (ictx->private != '\0') | ||||
| @@ -697,20 +660,15 @@ input_handle_sequence_cuu(struct input_ctx *ictx) | ||||
| 		return; | ||||
| 	if (input_get_argument(ictx, 0, &n, 1) != 0) | ||||
| 		return; | ||||
| 	if (n == 0) | ||||
| 		n = 1; | ||||
|  | ||||
| 	if (n == 0 || n > s->cy) { | ||||
| 		log_debug3("cuu: out of range: %hu", n); | ||||
| 		return; | ||||
| 	} | ||||
|  | ||||
| 	s->cy -= n; | ||||
| 	input_write(ictx, TTY_CURSORUP, n); | ||||
| 	screen_write_cursor_up(&ictx->ctx, n); | ||||
| } | ||||
|  | ||||
| void | ||||
| input_handle_sequence_cud(struct input_ctx *ictx) | ||||
| { | ||||
| 	struct screen	*s = &ictx->w->screen; | ||||
| 	uint16_t	n; | ||||
|  | ||||
| 	if (ictx->private != '\0') | ||||
| @@ -720,19 +678,15 @@ input_handle_sequence_cud(struct input_ctx *ictx) | ||||
| 		return; | ||||
| 	if (input_get_argument(ictx, 0, &n, 1) != 0) | ||||
| 		return; | ||||
|  | ||||
| 	if (n == 0) | ||||
| 		return; | ||||
| 	input_limit(n, 1, screen_last_y(s) - s->cy); | ||||
| 		n = 1; | ||||
|  | ||||
| 	s->cy += n; | ||||
| 	input_write(ictx, TTY_CURSORDOWN, n); | ||||
| 	screen_write_cursor_down(&ictx->ctx, n); | ||||
| } | ||||
|  | ||||
| void | ||||
| input_handle_sequence_cuf(struct input_ctx *ictx) | ||||
| { | ||||
| 	struct screen	*s = &ictx->w->screen; | ||||
| 	uint16_t n; | ||||
|  | ||||
| 	if (ictx->private != '\0') | ||||
| @@ -742,19 +696,15 @@ input_handle_sequence_cuf(struct input_ctx *ictx) | ||||
| 		return; | ||||
| 	if (input_get_argument(ictx, 0, &n, 1) != 0) | ||||
| 		return; | ||||
|  | ||||
| 	if (n == 0) | ||||
| 		return; | ||||
| 	input_limit(n, 1, screen_last_x(s) - s->cx); | ||||
| 		n = 1; | ||||
|  | ||||
| 	s->cx += n; | ||||
| 	input_write(ictx, TTY_CURSORRIGHT, n); | ||||
| 	screen_write_cursor_right(&ictx->ctx, n); | ||||
| } | ||||
|  | ||||
| void | ||||
| input_handle_sequence_cub(struct input_ctx *ictx) | ||||
| { | ||||
| 	struct screen	*s = &ictx->w->screen; | ||||
| 	uint16_t	n; | ||||
|  | ||||
| 	if (ictx->private != '\0') | ||||
| @@ -764,20 +714,15 @@ input_handle_sequence_cub(struct input_ctx *ictx) | ||||
| 		return; | ||||
| 	if (input_get_argument(ictx, 0, &n, 1) != 0) | ||||
| 		return; | ||||
| 	if (n == 0) | ||||
| 		n = 1; | ||||
|  | ||||
| 	if (n == 0 || n > s->cx) { | ||||
| 		log_debug3("cub: out of range: %hu", n); | ||||
| 		return; | ||||
| 	} | ||||
|  | ||||
| 	s->cx -= n; | ||||
| 	input_write(ictx, TTY_CURSORLEFT, n); | ||||
| 	screen_write_cursor_left(&ictx->ctx, n); | ||||
| } | ||||
|  | ||||
| void | ||||
| input_handle_sequence_dch(struct input_ctx *ictx) | ||||
| { | ||||
| 	struct screen	*s = &ictx->w->screen; | ||||
| 	uint16_t	n; | ||||
|  | ||||
| 	if (ictx->private != '\0') | ||||
| @@ -787,19 +732,15 @@ input_handle_sequence_dch(struct input_ctx *ictx) | ||||
| 		return; | ||||
| 	if (input_get_argument(ictx, 0, &n, 1) != 0) | ||||
| 		return; | ||||
|  | ||||
| 	if (n == 0) | ||||
| 		return; | ||||
| 	input_limit(n, 1, screen_last_x(s) - s->cx); | ||||
| 		n = 1; | ||||
|  | ||||
| 	screen_display_delete_characters(s, s->cx, s->cy, n); | ||||
| 	input_write(ictx, TTY_DELETECHARACTER, n); | ||||
| 	screen_write_delete_characters(&ictx->ctx, n); | ||||
| } | ||||
|  | ||||
| void | ||||
| input_handle_sequence_dl(struct input_ctx *ictx) | ||||
| { | ||||
| 	struct screen	*s = &ictx->w->screen; | ||||
| 	uint16_t	n; | ||||
|  | ||||
| 	if (ictx->private != '\0') | ||||
| @@ -809,22 +750,15 @@ input_handle_sequence_dl(struct input_ctx *ictx) | ||||
| 		return; | ||||
| 	if (input_get_argument(ictx, 0, &n, 1) != 0) | ||||
| 		return; | ||||
|  | ||||
| 	if (n == 0) | ||||
| 		return; | ||||
| 	input_limit(n, 1, screen_last_y(s) - s->cy); | ||||
| 		n = 1; | ||||
|  | ||||
| 	if (s->cy < s->rupper || s->cy > s->rlower) | ||||
| 		screen_display_delete_lines(s, s->cy, n); | ||||
| 	else | ||||
| 		screen_display_delete_lines_region(s, s->cy, n); | ||||
| 	input_write(ictx, TTY_DELETELINE, n); | ||||
| 	screen_write_delete_lines(&ictx->ctx, n); | ||||
| } | ||||
|  | ||||
| void | ||||
| input_handle_sequence_ich(struct input_ctx *ictx) | ||||
| { | ||||
| 	struct screen	*s = &ictx->w->screen; | ||||
| 	uint16_t	n; | ||||
|  | ||||
| 	if (ictx->private != '\0') | ||||
| @@ -834,19 +768,15 @@ input_handle_sequence_ich(struct input_ctx *ictx) | ||||
| 		return; | ||||
| 	if (input_get_argument(ictx, 0, &n, 1) != 0) | ||||
| 		return; | ||||
|  | ||||
| 	if (n == 0) | ||||
| 		return; | ||||
| 	input_limit(n, 1, screen_last_x(s) - s->cx); | ||||
| 		n = 1; | ||||
|  | ||||
| 	screen_display_insert_characters(s, s->cx, s->cy, n); | ||||
| 	input_write(ictx, TTY_INSERTCHARACTER, n); | ||||
| 	screen_write_insert_characters(&ictx->ctx, n); | ||||
| } | ||||
|  | ||||
| void | ||||
| input_handle_sequence_il(struct input_ctx *ictx) | ||||
| { | ||||
| 	struct screen	*s = &ictx->w->screen; | ||||
| 	uint16_t	n; | ||||
|  | ||||
| 	if (ictx->private != '\0') | ||||
| @@ -856,22 +786,16 @@ input_handle_sequence_il(struct input_ctx *ictx) | ||||
| 		return; | ||||
| 	if (input_get_argument(ictx, 0, &n, 1) != 0) | ||||
| 		return; | ||||
|  | ||||
| 	if (n == 0) | ||||
| 		return; | ||||
| 	input_limit(n, 1, screen_last_y(s) - s->cy); | ||||
| 		n = 1; | ||||
|  | ||||
| 	if (s->cy < s->rupper || s->cy > s->rlower) | ||||
| 		screen_display_insert_lines(s, s->cy, n); | ||||
| 	else | ||||
| 		screen_display_insert_lines_region(s, s->cy, n); | ||||
| 	input_write(ictx, TTY_INSERTLINE, n); | ||||
| 	screen_write_insert_lines(&ictx->ctx, n); | ||||
| } | ||||
|  | ||||
| void | ||||
| input_handle_sequence_vpa(struct input_ctx *ictx) | ||||
| { | ||||
| 	struct screen	*s = &ictx->w->screen; | ||||
| 	struct screen  *s = ictx->ctx.s; | ||||
| 	uint16_t	n; | ||||
|  | ||||
| 	if (ictx->private != '\0') | ||||
| @@ -881,19 +805,16 @@ input_handle_sequence_vpa(struct input_ctx *ictx) | ||||
| 		return; | ||||
| 	if (input_get_argument(ictx, 0, &n, 1) != 0) | ||||
| 		return; | ||||
|  | ||||
| 	if (n == 0) | ||||
| 		return; | ||||
| 	input_limit(n, 1, screen_size_y(s)); | ||||
| 		n = 1; | ||||
|  | ||||
| 	s->cy = n - 1; | ||||
| 	input_write(ictx, TTY_CURSORMOVE, s->cy, s->cx); | ||||
| 	screen_write_move_cursor(&ictx->ctx, s->cx, n - 1); | ||||
| } | ||||
|  | ||||
| void | ||||
| input_handle_sequence_hpa(struct input_ctx *ictx) | ||||
| { | ||||
| 	struct screen	*s = &ictx->w->screen; | ||||
| 	struct screen  *s = ictx->ctx.s; | ||||
| 	uint16_t	n; | ||||
|  | ||||
| 	if (ictx->private != '\0') | ||||
| @@ -903,19 +824,15 @@ input_handle_sequence_hpa(struct input_ctx *ictx) | ||||
| 		return; | ||||
| 	if (input_get_argument(ictx, 0, &n, 1) != 0) | ||||
| 		return; | ||||
|  | ||||
| 	if (n == 0) | ||||
| 		return; | ||||
| 	input_limit(n, 1, screen_size_x(s)); | ||||
| 		n = 1; | ||||
|  | ||||
| 	s->cx = n - 1; | ||||
| 	input_write(ictx, TTY_CURSORMOVE, s->cy, s->cx); | ||||
| 	screen_write_move_cursor(&ictx->ctx, n - 1, s->cy); | ||||
| } | ||||
|  | ||||
| void | ||||
| input_handle_sequence_cup(struct input_ctx *ictx) | ||||
| { | ||||
| 	struct screen	*s = &ictx->w->screen; | ||||
| 	uint16_t	n, m; | ||||
|  | ||||
| 	if (ictx->private != '\0') | ||||
| @@ -927,21 +844,18 @@ input_handle_sequence_cup(struct input_ctx *ictx) | ||||
| 		return; | ||||
| 	if (input_get_argument(ictx, 1, &m, 1) != 0) | ||||
| 		return; | ||||
| 	if (n == 0) | ||||
| 		n = 1; | ||||
| 	if (m == 0) | ||||
| 		m = 1; | ||||
|  | ||||
| 	input_limit(n, 1, screen_size_y(s)); | ||||
| 	input_limit(m, 1, screen_size_x(s)); | ||||
|  | ||||
| 	s->cx = m - 1; | ||||
| 	s->cy = n - 1; | ||||
| 	input_write(ictx, TTY_CURSORMOVE, s->cy, s->cx); | ||||
| 	screen_write_move_cursor(&ictx->ctx, m - 1, n - 1); | ||||
| } | ||||
|  | ||||
| void | ||||
| input_handle_sequence_ed(struct input_ctx *ictx) | ||||
| { | ||||
| 	struct screen	*s = &ictx->w->screen; | ||||
| 	uint16_t	n; | ||||
| 	u_int		 i; | ||||
|  | ||||
| 	if (ictx->private != '\0') | ||||
| 		return; | ||||
| @@ -950,31 +864,15 @@ input_handle_sequence_ed(struct input_ctx *ictx) | ||||
| 		return; | ||||
| 	if (input_get_argument(ictx, 0, &n, 0) != 0) | ||||
| 		return; | ||||
|  | ||||
| 	if (n > 2) | ||||
| 		return; | ||||
|  | ||||
| 	switch (n) { | ||||
| 	case 0: | ||||
| 		screen_display_fill_cursor_eos( | ||||
| 		    s, SCREEN_DEFDATA, s->attr, s->colr); | ||||
|  | ||||
| 		input_write(ictx, TTY_CLEARENDOFLINE); | ||||
| 		for (i = s->cy + 1; i < screen_size_y(s); i++) { | ||||
| 			input_write(ictx, TTY_CURSORMOVE, i, 0); | ||||
| 			input_write(ictx, TTY_CLEARENDOFLINE); | ||||
| 		} | ||||
| 		input_write(ictx, TTY_CURSORMOVE, s->cy, s->cx); | ||||
| 		screen_write_fill_end_of_screen(&ictx->ctx); | ||||
| 		break; | ||||
| 	case 2: | ||||
| 		screen_display_fill_lines( | ||||
| 		    s, 0, screen_size_y(s), SCREEN_DEFDATA, s->attr, s->colr); | ||||
|  | ||||
| 		for (i = 0; i < screen_size_y(s); i++) { | ||||
| 			input_write(ictx, TTY_CURSORMOVE, i, 0); | ||||
| 			input_write(ictx, TTY_CLEARENDOFLINE); | ||||
| 		} | ||||
| 		input_write(ictx, TTY_CURSORMOVE, s->cy, s->cx); | ||||
| 		screen_write_fill_screen(&ictx->ctx); | ||||
| 		break; | ||||
| 	} | ||||
| } | ||||
| @@ -982,7 +880,6 @@ input_handle_sequence_ed(struct input_ctx *ictx) | ||||
| void | ||||
| input_handle_sequence_el(struct input_ctx *ictx) | ||||
| { | ||||
| 	struct screen	*s = &ictx->w->screen; | ||||
| 	uint16_t	n; | ||||
|  | ||||
| 	if (ictx->private != '\0') | ||||
| @@ -992,25 +889,18 @@ input_handle_sequence_el(struct input_ctx *ictx) | ||||
| 		return; | ||||
| 	if (input_get_argument(ictx, 0, &n, 0) != 0) | ||||
| 		return; | ||||
|  | ||||
| 	if (n > 2) | ||||
| 		return; | ||||
|  | ||||
| 	switch (n) { | ||||
| 	case 0: | ||||
| 		screen_display_fill_cursor_eol( | ||||
| 		    s, SCREEN_DEFDATA, s->attr, s->colr); | ||||
| 		input_write(ictx, TTY_CLEARENDOFLINE); | ||||
| 		screen_write_fill_end_of_line(&ictx->ctx); | ||||
| 		break; | ||||
| 	case 1: | ||||
| 		screen_display_fill_cursor_bol( | ||||
| 		    s, SCREEN_DEFDATA, s->attr, s->colr); | ||||
| 		input_write(ictx, TTY_CLEARSTARTOFLINE); | ||||
| 		screen_write_fill_start_of_line(&ictx->ctx); | ||||
| 		break; | ||||
| 	case 2: | ||||
| 		screen_display_fill_line( | ||||
| 		    s, s->cy, SCREEN_DEFDATA, s->attr, s->colr); | ||||
| 		input_write(ictx, TTY_CLEARLINE); | ||||
| 		screen_write_fill_line(&ictx->ctx); | ||||
| 		break; | ||||
| 	} | ||||
| } | ||||
| @@ -1018,7 +908,6 @@ input_handle_sequence_el(struct input_ctx *ictx) | ||||
| void | ||||
| input_handle_sequence_sm(struct input_ctx *ictx) | ||||
| { | ||||
| 	struct screen	*s = &ictx->w->screen; | ||||
| 	uint16_t	n; | ||||
|  | ||||
| 	if (ARRAY_LENGTH(&ictx->args) > 1) | ||||
| @@ -1029,16 +918,13 @@ input_handle_sequence_sm(struct input_ctx *ictx) | ||||
| 	if (ictx->private == '?') { | ||||
| 		switch (n) { | ||||
| 		case 1:		/* GATM */ | ||||
| 			s->mode |= MODE_KCURSOR; | ||||
| 			input_write(ictx, TTY_KCURSORON); | ||||
| 			screen_write_set_mode(&ictx->ctx, MODE_KCURSOR); | ||||
| 			break; | ||||
| 		case 25:	/* TCEM */ | ||||
| 			s->mode |= MODE_CURSOR; | ||||
| 			input_write(ictx, TTY_CURSORON); | ||||
| 			screen_write_set_mode(&ictx->ctx, MODE_CURSOR); | ||||
| 			break; | ||||
| 		case 1000: | ||||
| 			s->mode |= MODE_MOUSE; | ||||
| 			input_write(ictx, TTY_MOUSEON); | ||||
| 			screen_write_set_mode(&ictx->ctx, MODE_MOUSE); | ||||
| 			break; | ||||
| 		default: | ||||
| 			log_debug("unknown SM [%hhu]: %u", ictx->private, n); | ||||
| @@ -1047,8 +933,7 @@ input_handle_sequence_sm(struct input_ctx *ictx) | ||||
| 	} else { | ||||
| 		switch (n) { | ||||
| 		case 4:		/* IRM */ | ||||
| 			s->mode |= MODE_INSERT; | ||||
| 			input_write(ictx, TTY_INSERTON); | ||||
| 			screen_write_set_mode(&ictx->ctx, MODE_INSERT); | ||||
| 			break; | ||||
| 		case 34: | ||||
| 			/* Cursor high visibility not supported. */ | ||||
| @@ -1063,7 +948,6 @@ input_handle_sequence_sm(struct input_ctx *ictx) | ||||
| void | ||||
| input_handle_sequence_rm(struct input_ctx *ictx) | ||||
| { | ||||
| 	struct screen	*s = &ictx->w->screen; | ||||
| 	uint16_t	 n; | ||||
|  | ||||
| 	if (ARRAY_LENGTH(&ictx->args) > 1) | ||||
| @@ -1074,16 +958,13 @@ input_handle_sequence_rm(struct input_ctx *ictx) | ||||
| 	if (ictx->private == '?') { | ||||
| 		switch (n) { | ||||
| 		case 1:		/* GATM */ | ||||
| 			s->mode &= ~MODE_KCURSOR; | ||||
| 			input_write(ictx, TTY_KCURSOROFF); | ||||
| 			screen_write_clear_mode(&ictx->ctx, MODE_KCURSOR); | ||||
| 			break; | ||||
| 		case 25:	/* TCEM */ | ||||
| 			s->mode &= ~MODE_CURSOR; | ||||
| 			input_write(ictx, TTY_CURSOROFF); | ||||
| 			screen_write_clear_mode(&ictx->ctx, MODE_CURSOR); | ||||
| 			break; | ||||
| 		case 1000: | ||||
| 			s->mode &= ~MODE_MOUSE; | ||||
| 			input_write(ictx, TTY_MOUSEOFF); | ||||
| 			screen_write_clear_mode(&ictx->ctx, MODE_MOUSE); | ||||
| 			break; | ||||
| 		default: | ||||
| 			log_debug("unknown RM [%hhu]: %u", ictx->private, n); | ||||
| @@ -1092,8 +973,7 @@ input_handle_sequence_rm(struct input_ctx *ictx) | ||||
| 	} else if (ictx->private == '\0') { | ||||
| 		switch (n) { | ||||
| 		case 4:		/* IRM */ | ||||
| 			s->mode &= ~MODE_INSERT; | ||||
| 			input_write(ictx, TTY_INSERTOFF); | ||||
| 			screen_write_clear_mode(&ictx->ctx, MODE_INSERT); | ||||
| 			break; | ||||
| 		case 34: | ||||
| 			/* Cursor high visibility not supported. */ | ||||
| @@ -1108,7 +988,7 @@ input_handle_sequence_rm(struct input_ctx *ictx) | ||||
| void | ||||
| input_handle_sequence_dsr(struct input_ctx *ictx) | ||||
| { | ||||
| 	struct screen	*s = &ictx->w->screen; | ||||
| 	struct screen  *s = ictx->ctx.s; | ||||
| 	uint16_t	n; | ||||
| 	char		reply[32]; | ||||
|  | ||||
| @@ -1133,7 +1013,7 @@ input_handle_sequence_dsr(struct input_ctx *ictx) | ||||
| void | ||||
| input_handle_sequence_decstbm(struct input_ctx *ictx) | ||||
| { | ||||
| 	struct screen	*s = &ictx->w->screen; | ||||
| 	struct screen  *s = ictx->ctx.s; | ||||
| 	uint16_t	n, m; | ||||
|  | ||||
| 	if (ictx->private != '\0') | ||||
| @@ -1145,78 +1025,64 @@ input_handle_sequence_decstbm(struct input_ctx *ictx) | ||||
| 		return; | ||||
| 	if (input_get_argument(ictx, 1, &m, 0) != 0) | ||||
| 		return; | ||||
|  | ||||
| 	/* Special case: both zero restores to entire screen. */ | ||||
| 	/* XXX this will catch [0;0r and [;r etc too, is this right? */ | ||||
| 	if (n == 0 && m == 0) { | ||||
| 	if (n == 0) | ||||
| 		n = 1; | ||||
| 	if (m == 0) | ||||
| 		m = screen_size_y(s); | ||||
| 	} | ||||
|  | ||||
| 	input_limit(n, 1, screen_size_y(s)); | ||||
| 	input_limit(m, 1, screen_size_y(s)); | ||||
|  | ||||
| 	if (n > m) { | ||||
| 		log_debug3("decstbm: out of range: %hu,%hu", n, m); | ||||
| 		return; | ||||
| 	} | ||||
|  | ||||
| 	/* Cursor moves to top-left. */ | ||||
| 	s->cx = 0; | ||||
| 	s->cy = n - 1; | ||||
|  | ||||
| 	s->rupper = n - 1; | ||||
| 	s->rlower = m - 1; | ||||
| 	input_write(ictx, TTY_SCROLLREGION, s->rupper, s->rlower); | ||||
| 	screen_write_set_region(&ictx->ctx, n - 1, m - 1); | ||||
| } | ||||
|  | ||||
| void | ||||
| input_handle_sequence_sgr(struct input_ctx *ictx) | ||||
| { | ||||
| 	struct screen	*s = &ictx->w->screen; | ||||
| 	struct screen  *s = ictx->ctx.s; | ||||
| 	u_int		i, n; | ||||
| 	uint16_t	m; | ||||
| 	u_char		attr, colr; | ||||
|  | ||||
| 	n = ARRAY_LENGTH(&ictx->args); | ||||
| 	if (n == 0) { | ||||
| 		s->attr = 0; | ||||
| 		s->colr = SCREEN_DEFCOLR; | ||||
| 		attr = 0; | ||||
| 		colr = SCREEN_DEFCOLR; | ||||
| 	} else { | ||||
| 		attr = s->attr; | ||||
| 		colr = s->colr; | ||||
| 		for (i = 0; i < n; i++) { | ||||
| 			if (input_get_argument(ictx, i, &m, 0) != 0) | ||||
| 				return; | ||||
| 			switch (m) { | ||||
| 			case 0: | ||||
| 			case 10: | ||||
| 				s->attr &= ATTR_CHARSET; | ||||
| 				s->colr = SCREEN_DEFCOLR; | ||||
| 				attr &= ATTR_CHARSET; | ||||
| 				colr = SCREEN_DEFCOLR; | ||||
| 				break; | ||||
| 			case 1: | ||||
| 				s->attr |= ATTR_BRIGHT; | ||||
| 				attr |= ATTR_BRIGHT; | ||||
| 				break; | ||||
| 			case 2: | ||||
| 				s->attr |= ATTR_DIM; | ||||
| 				attr |= ATTR_DIM; | ||||
| 				break; | ||||
| 			case 3: | ||||
| 				s->attr |= ATTR_ITALICS; | ||||
| 				attr |= ATTR_ITALICS; | ||||
| 				break; | ||||
| 			case 4: | ||||
| 				s->attr |= ATTR_UNDERSCORE; | ||||
| 				attr |= ATTR_UNDERSCORE; | ||||
| 				break; | ||||
| 			case 5: | ||||
| 				s->attr |= ATTR_BLINK; | ||||
| 				attr |= ATTR_BLINK; | ||||
| 				break; | ||||
| 			case 7: | ||||
| 				s->attr |= ATTR_REVERSE; | ||||
| 				attr |= ATTR_REVERSE; | ||||
| 				break; | ||||
| 			case 8: | ||||
| 				s->attr |= ATTR_HIDDEN; | ||||
| 				attr |= ATTR_HIDDEN; | ||||
| 				break; | ||||
| 			case 23: | ||||
| 				s->attr &= ~ATTR_ITALICS; | ||||
| 				attr &= ~ATTR_ITALICS; | ||||
| 				break; | ||||
| 			case 24: | ||||
| 				s->attr &= ~ATTR_UNDERSCORE; | ||||
| 				attr &= ~ATTR_UNDERSCORE; | ||||
| 				break; | ||||
| 			case 30: | ||||
| 			case 31: | ||||
| @@ -1226,12 +1092,12 @@ input_handle_sequence_sgr(struct input_ctx *ictx) | ||||
| 			case 35: | ||||
| 			case 36: | ||||
| 			case 37: | ||||
| 				s->colr &= 0x0f; | ||||
| 				s->colr |= (m - 30) << 4; | ||||
| 				colr &= 0x0f; | ||||
| 				colr |= (m - 30) << 4; | ||||
| 				break; | ||||
| 			case 39: | ||||
| 				s->colr &= 0x0f; | ||||
| 				s->colr |= 0x80; | ||||
| 				colr &= 0x0f; | ||||
| 				colr |= 0x80; | ||||
| 				break; | ||||
| 			case 40: | ||||
| 			case 41: | ||||
| @@ -1241,15 +1107,15 @@ input_handle_sequence_sgr(struct input_ctx *ictx) | ||||
| 			case 45: | ||||
| 			case 46: | ||||
| 			case 47: | ||||
| 				s->colr &= 0xf0; | ||||
| 				s->colr |= m - 40; | ||||
| 				colr &= 0xf0; | ||||
| 				colr |= m - 40; | ||||
| 				break; | ||||
| 			case 49: | ||||
| 				s->colr &= 0xf0; | ||||
| 				s->colr |= 0x08; | ||||
| 				colr &= 0xf0; | ||||
| 				colr |= 0x08; | ||||
| 				break; | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	input_write(ictx, TTY_ATTRIBUTES, s->attr, s->colr); | ||||
| 	screen_write_set_attributes(&ictx->ctx, attr, colr); | ||||
| } | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| /* $Id: key-bindings.c,v 1.22 2007-11-27 19:23:33 nicm Exp $ */ | ||||
| /* $Id: key-bindings.c,v 1.23 2007-12-06 09:46:22 nicm Exp $ */ | ||||
|  | ||||
| /* | ||||
|  * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> | ||||
| @@ -168,6 +168,7 @@ key_bindings_print(struct cmd_ctx *ctx, const char *fmt, ...) | ||||
| 	if (w->mode == NULL) { | ||||
| 		w->mode = &window_more_mode; | ||||
| 		w->mode->init(w); | ||||
| 		server_redraw_window(w); | ||||
| 	} else if (w->mode != &window_more_mode) | ||||
| 		return; | ||||
|  | ||||
| @@ -202,7 +203,4 @@ key_bindings_dispatch(int key, struct client *c) | ||||
| 	ctx.flags = CMD_KEY; | ||||
|  | ||||
| 	cmd_exec(bd->cmd, &ctx); | ||||
| 	 | ||||
| 	if (c->session->curw->window->mode == &window_more_mode) | ||||
| 		server_redraw_window(c->session->curw->window); | ||||
| } | ||||
|   | ||||
							
								
								
									
										12
									
								
								resize.c
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								resize.c
									
									
									
									
									
								
							| @@ -1,4 +1,4 @@ | ||||
| /* $Id: resize.c,v 1.8 2007-12-02 23:00:22 nicm Exp $ */ | ||||
| /* $Id: resize.c,v 1.9 2007-12-06 09:46:22 nicm Exp $ */ | ||||
|  | ||||
| /* | ||||
|  * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> | ||||
| @@ -105,17 +105,17 @@ recalculate_sizes(void) | ||||
| 			} | ||||
| 		} | ||||
| 		if (ssx == UINT_MAX || ssy == UINT_MAX) { | ||||
| 			w->screen.mode |= MODE_HIDDEN; | ||||
| 			w->flags |= WINDOW_HIDDEN; | ||||
| 			continue; | ||||
| 		} | ||||
| 		w->screen.mode &= ~MODE_HIDDEN; | ||||
| 		w->flags &= ~WINDOW_HIDDEN; | ||||
|  | ||||
| 		if (screen_size_x(&w->screen) == ssx && | ||||
| 		    screen_size_y(&w->screen) == ssy) | ||||
| 		if (screen_size_x(&w->base) == ssx && | ||||
| 		    screen_size_y(&w->base) == ssy) | ||||
| 			continue; | ||||
|  | ||||
| 		log_debug("window size %u,%u (was %u,%u)", ssx, ssy, | ||||
| 		    screen_size_x(&w->screen), screen_size_y(&w->screen)); | ||||
| 		    screen_size_x(&w->base), screen_size_y(&w->base)); | ||||
|  | ||||
| 		server_clear_window(w); | ||||
| 		window_resize(w, ssx, ssy); | ||||
|   | ||||
							
								
								
									
										179
									
								
								screen-display.c
									
									
									
									
									
								
							
							
						
						
									
										179
									
								
								screen-display.c
									
									
									
									
									
								
							| @@ -1,4 +1,4 @@ | ||||
| /* $Id: screen-display.c,v 1.9 2007-11-26 22:22:18 nicm Exp $ */ | ||||
| /* $Id: screen-display.c,v 1.10 2007-12-06 09:46:22 nicm Exp $ */ | ||||
|  | ||||
| /* | ||||
|  * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> | ||||
| @@ -22,17 +22,20 @@ | ||||
|  | ||||
| #include "tmux.h" | ||||
|  | ||||
| /* | ||||
|  * Screen display modification functions. These alter the displayed portion | ||||
|  * of the screen. | ||||
|  */ | ||||
| /* Set a cell. */ | ||||
| void | ||||
| screen_display_set_cell( | ||||
|     struct screen *s, u_int px, u_int py, u_char data, u_char attr, u_char colr) | ||||
| { | ||||
| 	screen_set_cell(s, screen_x(s, px), screen_y(s, py), data, attr, colr); | ||||
| } | ||||
|  | ||||
| /* Create a region of lines. */ | ||||
| void | ||||
| screen_display_make_lines(struct screen *s, u_int py, u_int ny) | ||||
| { | ||||
| 	if (ny == 0 || !screen_in_y(s, py) || !screen_in_y(s, py + ny - 1)) | ||||
| 		fatalx("bad value"); | ||||
| 		return; | ||||
| 	screen_make_lines(s, screen_y(s, py), ny); | ||||
| } | ||||
|  | ||||
| @@ -41,7 +44,7 @@ void | ||||
| screen_display_free_lines(struct screen *s, u_int py, u_int ny) | ||||
| { | ||||
| 	if (ny == 0 || !screen_in_y(s, py) || !screen_in_y(s, py + ny - 1)) | ||||
| 		fatalx("bad value"); | ||||
| 		return; | ||||
| 	screen_free_lines(s, screen_y(s, py), ny); | ||||
| } | ||||
|  | ||||
| @@ -50,116 +53,25 @@ void | ||||
| screen_display_move_lines(struct screen *s, u_int dy, u_int py, u_int ny) | ||||
| { | ||||
| 	if (ny == 0 || !screen_in_y(s, py) || !screen_in_y(s, py + ny - 1)) | ||||
| 		fatalx("bad value"); | ||||
| 		return; | ||||
| 	if (!screen_in_y(s, dy) || !screen_in_y(s, dy + ny - 1) || dy == py) | ||||
| 		fatalx("bad value"); | ||||
| 		return; | ||||
| 	screen_move_lines(s, screen_y(s, dy), screen_y(s, py), ny); | ||||
| } | ||||
|  | ||||
| /* Fill a set of lines. */ | ||||
| /* Fill a set of cells. */ | ||||
| void | ||||
| screen_display_fill_lines( | ||||
|     struct screen *s, u_int py, u_int ny, u_char data, u_char attr, u_char colr) | ||||
| screen_display_fill_area(struct screen *s, u_int px, u_int py, | ||||
|     u_int nx, u_int ny, u_char data, u_char attr, u_char colr) | ||||
| { | ||||
| 	if (ny == 0 || !screen_in_y(s, py) || !screen_in_y(s, py + ny - 1)) | ||||
| 		fatalx("bad value"); | ||||
| 	screen_fill_lines(s, screen_y(s, py), ny, data, attr, colr); | ||||
| } | ||||
|  | ||||
| /* Fill a set of cellss. */ | ||||
| void | ||||
| screen_display_fill_cells(struct screen *s, | ||||
|     u_int px, u_int py, u_int nx, u_char data, u_char attr, u_char colr) | ||||
| { | ||||
| 	if (nx == 0 || !screen_in_x(s, px) || !screen_in_y(s, py)) | ||||
| 		fatalx("bad value"); | ||||
| 	screen_fill_cells( | ||||
| 	    s, screen_x(s, px), screen_y(s, py), nx, data, attr, colr); | ||||
| } | ||||
|  | ||||
| /* Fill entire screen. */ | ||||
| void | ||||
| screen_display_fill_screen( | ||||
|     struct screen *s, u_char data, u_char attr, u_char colr) | ||||
| { | ||||
| 	screen_display_fill_lines(s, 0, screen_size_y(s), data, attr, colr); | ||||
| } | ||||
|  | ||||
| /* Fill end of screen from cursor. */ | ||||
| void | ||||
| screen_display_fill_cursor_eos( | ||||
|     struct screen *s, u_char data, u_char attr, u_char colr) | ||||
| { | ||||
| 	screen_display_fill_cursor_eol(s, data, attr, colr); | ||||
| 	if (s->cy != screen_last_y(s)) { | ||||
| 		screen_display_fill_lines( | ||||
| 		    s, s->cy, screen_size_y(s) - s->cy, data, attr, colr); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| /* Fill beginning of screen from cursor. */ | ||||
| void | ||||
| screen_display_fill_cursor_bos( | ||||
|     struct screen *s, u_char data, u_char attr, u_char colr) | ||||
| { | ||||
| 	screen_display_fill_lines(s, 0, s->cy, data, attr, colr); | ||||
| } | ||||
|  | ||||
| /* Fill a single line. */ | ||||
| void | ||||
| screen_display_fill_line( | ||||
|     struct screen *s, u_int py, u_char data, u_char attr, u_char colr) | ||||
| { | ||||
| 	screen_display_fill_lines(s, py, 1, data, attr, colr); | ||||
| } | ||||
|  | ||||
| /* Fill cursor to beginning of line. */ | ||||
| void | ||||
| screen_display_fill_cursor_bol( | ||||
|     struct screen *s, u_char data, u_char attr, u_char colr) | ||||
| { | ||||
| 	screen_display_fill_cells(s, 0, s->cy, s->cx, data, attr, colr); | ||||
| } | ||||
|  | ||||
| /* Fill cursor to end of line. */ | ||||
| void | ||||
| screen_display_fill_cursor_eol( | ||||
|     struct screen *s, u_char data, u_char attr, u_char colr) | ||||
| { | ||||
| 	screen_display_fill_cells( | ||||
| 	    s, s->cx, s->cy, screen_size_x(s) - s->cx, data, attr, colr); | ||||
| } | ||||
|  | ||||
| /* Set character at cursor. */ | ||||
| void | ||||
| screen_display_cursor_set(struct screen *s, u_char ch) | ||||
| { | ||||
| 	u_int	px, py; | ||||
|  | ||||
| 	px = screen_x(s, s->cx); | ||||
| 	py = screen_y(s, s->cy); | ||||
|  | ||||
| 	screen_set_cell(s, px, py, ch, s->attr, s->colr); | ||||
| } | ||||
|  | ||||
| /* Move cursor up and scroll if necessary. */ | ||||
| void | ||||
| screen_display_cursor_up(struct screen *s) | ||||
| { | ||||
| 	if (s->cy == s->rupper) | ||||
| 		screen_display_scroll_region_down(s); | ||||
| 	else if (s->cy > 0) | ||||
| 		s->cy--; | ||||
| } | ||||
|  | ||||
| /* Move cursor down and scroll if necessary. */ | ||||
| void | ||||
| screen_display_cursor_down(struct screen *s) | ||||
| { | ||||
| 	if (s->cy == s->rlower) | ||||
| 		screen_display_scroll_region_up(s); | ||||
| 	else if (s->cy < screen_last_y(s)) | ||||
| 		s->cy++; | ||||
| 	if (nx == 0 || ny == 0) | ||||
| 		return; | ||||
| 	if (!screen_in_x(s, px) || !screen_in_y(s, py)) | ||||
| 		return; | ||||
| 	if (!screen_in_x(s, px + nx - 1) || !screen_in_y(s, py - ny - 1)) | ||||
| 		return; | ||||
| 	screen_fill_area( | ||||
| 	    s, screen_x(s, px), screen_y(s, py), nx, ny, data, attr, colr); | ||||
| } | ||||
|  | ||||
| /* Scroll region up. */ | ||||
| @@ -252,9 +164,9 @@ void | ||||
| screen_display_insert_lines(struct screen *s, u_int py, u_int ny) | ||||
| { | ||||
| 	if (!screen_in_y(s, py)) | ||||
| 		fatalx("bad value"); | ||||
| 		return; | ||||
| 	if (ny == 0) | ||||
| 		fatalx("bad value"); | ||||
| 		return; | ||||
|  | ||||
| 	if (py + ny > screen_last_y(s)) | ||||
| 		ny = screen_size_y(s) - py; | ||||
| @@ -289,9 +201,9 @@ void | ||||
| screen_display_insert_lines_region(struct screen *s, u_int py, u_int ny) | ||||
| { | ||||
| 	if (!screen_in_region(s, py)) | ||||
| 		fatalx("bad value"); | ||||
| 		return; | ||||
| 	if (ny == 0) | ||||
| 		fatalx("bad value"); | ||||
| 		return; | ||||
|  | ||||
| 	if (py + ny > s->rlower) | ||||
| 		ny = (s->rlower + 1) - py; | ||||
| @@ -326,9 +238,9 @@ void | ||||
| screen_display_delete_lines(struct screen *s, u_int py, u_int ny) | ||||
| { | ||||
| 	if (!screen_in_y(s, py)) | ||||
| 		fatalx("bad value"); | ||||
| 		return; | ||||
| 	if (ny == 0) | ||||
| 		fatalx("bad value"); | ||||
| 		return; | ||||
|  | ||||
| 	if (py + ny > screen_last_y(s)) | ||||
| 		ny = screen_size_y(s) - py; | ||||
| @@ -363,9 +275,9 @@ void | ||||
| screen_display_delete_lines_region(struct screen *s, u_int py, u_int ny) | ||||
| { | ||||
| 	if (!screen_in_region(s, py)) | ||||
| 		fatalx("bad value"); | ||||
| 		return; | ||||
| 	if (ny == 0) | ||||
| 		fatalx("bad value"); | ||||
| 		return; | ||||
|  | ||||
| 	if (py + ny > s->rlower) | ||||
| 		ny = (s->rlower + 1) - py; | ||||
| @@ -402,7 +314,7 @@ screen_display_insert_characters(struct screen *s, u_int px, u_int py, u_int nx) | ||||
| 	u_int	mx; | ||||
|  | ||||
| 	if (!screen_in_x(s, px) || !screen_in_y(s, py)) | ||||
| 		fatalx("bad value"); | ||||
| 		return; | ||||
|  | ||||
| 	if (px + nx > screen_last_x(s)) | ||||
| 		nx = screen_last_x(s) - px; | ||||
| @@ -439,7 +351,7 @@ screen_display_delete_characters(struct screen *s, u_int px, u_int py, u_int nx) | ||||
| 	u_int	mx; | ||||
|  | ||||
| 	if (!screen_in_x(s, px) || !screen_in_y(s, py)) | ||||
| 		fatalx("bad value"); | ||||
| 		return; | ||||
|  | ||||
| 	if (px + nx > screen_last_x(s)) | ||||
| 		nx = screen_last_x(s) - px; | ||||
| @@ -468,3 +380,28 @@ screen_display_delete_characters(struct screen *s, u_int px, u_int py, u_int nx) | ||||
| 	memset(&s->grid_attr[py][screen_size_x(s) - nx], SCREEN_DEFATTR, nx); | ||||
| 	memset(&s->grid_colr[py][screen_size_x(s) - nx], SCREEN_DEFCOLR, nx); | ||||
| } | ||||
|  | ||||
| /* Fill cells from another screen, with an offset. */ | ||||
| void | ||||
| screen_display_copy_area(struct screen *dst, struct screen *src, | ||||
|     u_int px, u_int py, u_int nx, u_int ny, u_int ox, u_int oy) | ||||
| { | ||||
| 	u_int	i, j; | ||||
| 	u_char	data, attr, colr; | ||||
|  | ||||
| 	if (nx == 0 || ny == 0) | ||||
| 		return; | ||||
| 	if (!screen_in_x(dst, px) || !screen_in_y(dst, py)) | ||||
| 		return; | ||||
| 	if (!screen_in_x(dst, px + nx - 1) || !screen_in_y(dst, py + ny - 1)) | ||||
| 		return; | ||||
|  | ||||
| 	for (i = py; i < py + ny; i++) { | ||||
| 		for (j = px; j < px + nx; j++) { | ||||
| 			screen_get_cell(src, | ||||
| 			    screen_x(src, j) + ox, screen_y(src, i) - oy, | ||||
| 			    &data, &attr, &colr); | ||||
| 			screen_display_set_cell(dst, j, i, data, attr, colr); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|   | ||||
							
								
								
									
										218
									
								
								screen-redraw.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										218
									
								
								screen-redraw.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,218 @@ | ||||
| /* $Id: screen-redraw.c,v 1.1 2007-12-06 09:46:22 nicm Exp $ */ | ||||
|  | ||||
| /* | ||||
|  * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> | ||||
|  * | ||||
|  * Permission to use, copy, modify, and distribute this software for any | ||||
|  * purpose with or without fee is hereby granted, provided that the above | ||||
|  * copyright notice and this permission notice appear in all copies. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||||
|  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||||
|  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||||
|  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||||
|  * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER | ||||
|  * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING | ||||
|  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||||
|  */ | ||||
|  | ||||
| #include <sys/types.h> | ||||
|  | ||||
| #include <string.h> | ||||
|  | ||||
| #include "tmux.h" | ||||
|  | ||||
| void	screen_redraw_get_cell(struct screen_redraw_ctx *, | ||||
|     	    u_int, u_int, u_char *, u_char *, u_char *); | ||||
|  | ||||
| /* Initialise redrawing with a window. */ | ||||
| void | ||||
| screen_redraw_start_window(struct screen_redraw_ctx *ctx, struct window *w) | ||||
| { | ||||
| 	struct screen	*t = w->screen; | ||||
|  | ||||
| 	screen_redraw_start(ctx, t, tty_write_window, w); | ||||
| } | ||||
|  | ||||
| /* Initialise redrawing with a client. */ | ||||
| void | ||||
| screen_redraw_start_client(struct screen_redraw_ctx *ctx, struct client *c) | ||||
| { | ||||
| 	struct screen	*t = c->session->curw->window->screen; | ||||
|  | ||||
| 	screen_redraw_start(ctx, t, tty_write_client, c); | ||||
| } | ||||
|  | ||||
| /* Initialise redrawing with a session. */ | ||||
| void | ||||
| screen_redraw_start_session(struct screen_redraw_ctx *ctx, struct session *s) | ||||
| { | ||||
| 	struct screen	*t = s->curw->window->screen; | ||||
|  | ||||
| 	screen_redraw_start(ctx, t, tty_write_session, s); | ||||
| } | ||||
|  | ||||
| /* Initialise for redrawing. */ | ||||
| void | ||||
| screen_redraw_start(struct screen_redraw_ctx *ctx, | ||||
|     struct screen *s, void (*write)(void *, int, ...), void *data) | ||||
| { | ||||
| 	ctx->write = write; | ||||
| 	ctx->data = data; | ||||
|  | ||||
| 	ctx->s = s; | ||||
|  | ||||
| 	/* | ||||
| 	 * Save screen cursor position. Emulation of some TTY_* commands | ||||
| 	 * requires this to be correct in the screen, so rather than having | ||||
| 	 * a local copy and just manipulating it, save the screen's values, | ||||
| 	 * modify them during redraw, and restore them when finished. | ||||
| 	 */ | ||||
| 	ctx->saved_cx = s->cx; | ||||
| 	ctx->saved_cy = s->cy; | ||||
|  | ||||
| 	ctx->write(ctx->data, TTY_ATTRIBUTES, s->attr, s->colr); | ||||
| 	ctx->write(ctx->data, TTY_SCROLLREGION, 0, screen_last_y(s)); | ||||
| 	ctx->write(ctx->data, TTY_CURSORMOVE, s->cy, s->cx); | ||||
| 	ctx->write(ctx->data, TTY_CURSOROFF); | ||||
| 	ctx->write(ctx->data, TTY_MOUSEOFF); | ||||
| } | ||||
|  | ||||
| /* Finish redrawing. */ | ||||
| void | ||||
| screen_redraw_stop(struct screen_redraw_ctx *ctx) | ||||
| { | ||||
| 	struct screen	*s = ctx->s; | ||||
|  | ||||
| 	s->cx = ctx->saved_cx; | ||||
| 	s->cy = ctx->saved_cy; | ||||
|  | ||||
| 	ctx->write(ctx->data, TTY_ATTRIBUTES, s->attr, s->colr); | ||||
| 	ctx->write(ctx->data, TTY_SCROLLREGION, s->rupper, s->rlower); | ||||
| 	ctx->write(ctx->data, TTY_CURSORMOVE, s->cy, s->cx); | ||||
| 	if (s->mode & MODE_CURSOR) | ||||
| 		ctx->write(ctx->data, TTY_CURSORON); | ||||
| 	if (s->mode & MODE_MOUSE) | ||||
| 		ctx->write(ctx->data, TTY_MOUSEON); | ||||
| } | ||||
|  | ||||
| /* Get cell data. */ | ||||
| void | ||||
| screen_redraw_get_cell(struct screen_redraw_ctx *ctx, | ||||
|     u_int px, u_int py, u_char *data, u_char *attr, u_char *colr) | ||||
| { | ||||
| 	struct screen	*s = ctx->s; | ||||
|  | ||||
| 	screen_get_cell(s, screen_x(s, px), screen_y(s, py), data, attr, colr); | ||||
| } | ||||
|  | ||||
| /* Move cursor. */ | ||||
| void | ||||
| screen_redraw_move_cursor(struct screen_redraw_ctx *ctx, u_int px, u_int py) | ||||
| { | ||||
| 	if (px != ctx->s->cx || py != ctx->s->cy) { | ||||
| 		ctx->s->cx = px; | ||||
| 		ctx->s->cy = py; | ||||
| 		ctx->write(ctx->data, TTY_CURSORMOVE, ctx->s->cy, ctx->s->cx); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| /* Set attributes. */ | ||||
| void | ||||
| screen_redraw_set_attributes( | ||||
|     struct screen_redraw_ctx *ctx, u_int attr, u_int colr) | ||||
| { | ||||
| 	ctx->write(ctx->data, TTY_ATTRIBUTES, attr, colr); | ||||
| } | ||||
|  | ||||
| /* Write string. */ | ||||
| void printflike2 | ||||
| screen_redraw_write_string(struct screen_redraw_ctx *ctx, const char *fmt, ...) | ||||
| { | ||||
| 	struct screen	*s = ctx->s; | ||||
| 	va_list		 ap; | ||||
| 	char   		*msg, *ptr; | ||||
|  | ||||
| 	va_start(ap, fmt); | ||||
| 	xvasprintf(&msg, fmt, ap); | ||||
| 	va_end(ap); | ||||
|  | ||||
| 	for (ptr = msg; *ptr != '\0'; ptr++) { | ||||
| 		if (ctx->s->cx > screen_last_x(s)) | ||||
| 			break; | ||||
| 		if (*ptr < 0x20) | ||||
| 			continue; | ||||
| 		ctx->write(ctx->data, TTY_CHARACTER, *ptr); | ||||
| 		ctx->s->cx++; | ||||
| 	} | ||||
|  | ||||
| 	xfree(msg); | ||||
| } | ||||
|  | ||||
| /* Clear screen. */ | ||||
| void | ||||
| screen_redraw_clear_screen(struct screen_redraw_ctx *ctx) | ||||
| { | ||||
| 	u_int	i; | ||||
|  | ||||
| 	for (i = 0; i < screen_size_y(ctx->s); i++) { | ||||
| 		screen_redraw_move_cursor(ctx, 0, i); | ||||
| 		ctx->write(ctx->data, TTY_CLEARLINE); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| /* Clear to end of line. */ | ||||
| void | ||||
| screen_redraw_clear_end_of_line(struct screen_redraw_ctx *ctx) | ||||
| { | ||||
| 	ctx->write(ctx->data, TTY_CLEARENDOFLINE); | ||||
| } | ||||
|  | ||||
| /* Redraw single cell. */ | ||||
| void | ||||
| screen_redraw_cell(struct screen_redraw_ctx *ctx, u_int px, u_int py) | ||||
| { | ||||
| 	u_char	 data, attr, colr; | ||||
|  | ||||
| 	screen_redraw_move_cursor(ctx, px, py); | ||||
| 	screen_redraw_get_cell(ctx, px, py, &data, &attr, &colr); | ||||
|  | ||||
| 	ctx->write(ctx->data, TTY_ATTRIBUTES, attr, colr); | ||||
| 	ctx->write(ctx->data, TTY_CHARACTER, data); | ||||
|  | ||||
| 	ctx->s->cx++; | ||||
| } | ||||
|  | ||||
| /* Redraw area of cells. */ | ||||
| void | ||||
| screen_redraw_area( | ||||
|     struct screen_redraw_ctx *ctx, u_int px, u_int py, u_int nx, u_int ny) | ||||
| { | ||||
| 	u_int	i, j; | ||||
|  | ||||
| 	for (i = py; i < py + ny; i++) { | ||||
| 		for (j = px; j < px + nx; j++) | ||||
| 			screen_redraw_cell(ctx, j, i); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| /* Draw set of lines. */ | ||||
| void | ||||
| screen_redraw_lines(struct screen_redraw_ctx *ctx, u_int py, u_int ny) | ||||
| { | ||||
| 	u_int	i, cx, sx; | ||||
|  | ||||
| 	sx = screen_size_x(ctx->s); | ||||
| 	for (i = py; i < py + ny; i++) { | ||||
| 		cx = ctx->s->grid_size[screen_y(ctx->s, i)]; | ||||
| 		if (ctx->s->sel.flag || sx < 5 || cx >= sx - 5) { | ||||
| 			screen_redraw_area(ctx, 0, i, screen_size_x(ctx->s), 1); | ||||
| 			continue; | ||||
| 		} | ||||
| 		screen_redraw_area(ctx, 0, i, cx, 1); | ||||
| 		screen_redraw_move_cursor(ctx, cx, i); | ||||
| 		screen_redraw_set_attributes( | ||||
| 		    ctx, SCREEN_DEFATTR, SCREEN_DEFCOLR); | ||||
| 		ctx->write(ctx->data, TTY_CLEARENDOFLINE); | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										516
									
								
								screen-write.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										516
									
								
								screen-write.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,516 @@ | ||||
| /* $Id: screen-write.c,v 1.1 2007-12-06 09:46:23 nicm Exp $ */ | ||||
|  | ||||
| /* | ||||
|  * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> | ||||
|  * | ||||
|  * Permission to use, copy, modify, and distribute this software for any | ||||
|  * purpose with or without fee is hereby granted, provided that the above | ||||
|  * copyright notice and this permission notice appear in all copies. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||||
|  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||||
|  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||||
|  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||||
|  * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER | ||||
|  * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING | ||||
|  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||||
|  */ | ||||
|  | ||||
| #include <sys/types.h> | ||||
|  | ||||
| #include <string.h> | ||||
|  | ||||
| #include "tmux.h" | ||||
|  | ||||
| #define screen_write_limit(v, lower, upper) do {	\ | ||||
| 	if (v < lower)					\ | ||||
| 		v = lower;				\ | ||||
| 	if (v > upper)					\ | ||||
| 		v = upper;				\ | ||||
| } while (0) | ||||
|  | ||||
| /* Initialise writing with a window. */ | ||||
| void | ||||
| screen_write_start_window(struct screen_write_ctx *ctx, struct window *w) | ||||
| { | ||||
| 	struct screen	*t = w->screen; | ||||
|  | ||||
| 	screen_write_start(ctx, t, tty_write_window, w); | ||||
| } | ||||
|  | ||||
| /* Initialise writing with a client. */ | ||||
| void | ||||
| screen_write_start_client(struct screen_write_ctx *ctx, struct client *c) | ||||
| { | ||||
| 	struct screen	*t = c->session->curw->window->screen; | ||||
|  | ||||
| 	screen_write_start(ctx, t, tty_write_client, c); | ||||
| } | ||||
|  | ||||
| /* Initialise writing with a session. */ | ||||
| void | ||||
| screen_write_start_session(struct screen_write_ctx *ctx, struct session *s) | ||||
| { | ||||
| 	struct screen	*t = s->curw->window->screen; | ||||
|  | ||||
| 	screen_write_start(ctx, t, tty_write_session, s); | ||||
| } | ||||
|  | ||||
| /* Initialise writing. */ | ||||
| void | ||||
| screen_write_start(struct screen_write_ctx *ctx, | ||||
|     struct screen *s, void (*write)(void *, int, ...), void *data) | ||||
| { | ||||
| 	ctx->write = write; | ||||
| 	ctx->data = data; | ||||
|  | ||||
| 	ctx->s = s; | ||||
|  | ||||
| 	if (ctx->write != NULL) | ||||
| 		ctx->write(ctx->data, TTY_CURSOROFF); | ||||
| } | ||||
|  | ||||
| /* Finalise writing. */ | ||||
| void | ||||
| screen_write_stop(struct screen_write_ctx *ctx) | ||||
| { | ||||
| 	struct screen	*s = ctx->s; | ||||
|  | ||||
| 	if (ctx->write != NULL && s->mode & MODE_CURSOR) | ||||
| 		ctx->write(ctx->data, TTY_CURSORON); | ||||
| } | ||||
|  | ||||
| /* Set screen title. */ | ||||
| void | ||||
| screen_write_set_title(struct screen_write_ctx *ctx, char *title) | ||||
| { | ||||
| 	struct screen	*s = ctx->s; | ||||
|  | ||||
| 	xfree(s->title); | ||||
| 	s->title = title; | ||||
|  | ||||
| 	if (ctx->write != NULL) | ||||
| 		ctx->write(ctx->data, TTY_TITLE, s->title); | ||||
| } | ||||
|  | ||||
| /* Put a character. */ | ||||
| void | ||||
| screen_write_put_character(struct screen_write_ctx *ctx, u_char ch) | ||||
| { | ||||
| 	struct screen	*s = ctx->s; | ||||
|  | ||||
| 	if (s->cx == screen_size_x(s)) { | ||||
| 		s->cx = 0; | ||||
| 		screen_write_cursor_down_scroll(ctx); | ||||
| 	} else if (!screen_in_x(s, s->cx) || !screen_in_y(s, s->cy)) | ||||
| 		return; | ||||
|  | ||||
| 	screen_display_set_cell(s, s->cx, s->cy, ch, s->attr, s->colr); | ||||
| 	s->cx++; | ||||
|  | ||||
| 	if (ctx->write != NULL) | ||||
| 		ctx->write(ctx->data, TTY_CHARACTER, ch); | ||||
| } | ||||
|  | ||||
| /* Put a string right-justified. */ | ||||
| size_t printflike2 | ||||
| screen_write_put_string_rjust( | ||||
|     struct screen_write_ctx *ctx, const char *fmt, ...) | ||||
| { | ||||
| 	struct screen	*s = ctx->s; | ||||
| 	va_list		 ap; | ||||
| 	size_t		 size; | ||||
| 	char   		*msg, *ptr; | ||||
|  | ||||
| 	va_start(ap, fmt); | ||||
| 	size = vasprintf(&msg, fmt, ap); | ||||
| 	va_end(ap); | ||||
|  | ||||
| 	ptr = msg; | ||||
| 	if (size > screen_size_x(s)) { | ||||
| 		ptr += size - screen_size_x(s); | ||||
| 		size = screen_size_x(s); | ||||
| 	} | ||||
| 	screen_write_move_cursor(ctx, screen_size_x(s) - size, s->cy); | ||||
| 	for (; *ptr != '\0'; ptr++) { | ||||
| 		if (s->cx == screen_size_x(s)) | ||||
| 			break; | ||||
| 		screen_write_put_character(ctx, *ptr); | ||||
| 	} | ||||
|  | ||||
| 	xfree(msg); | ||||
|  | ||||
| 	return (size); | ||||
| } | ||||
|  | ||||
| /* Put a string, truncating at end of line. */ | ||||
| void printflike2 | ||||
| screen_write_put_string(struct screen_write_ctx *ctx, const char *fmt, ...) | ||||
| { | ||||
| 	struct screen	*s = ctx->s; | ||||
| 	va_list		 ap; | ||||
| 	char		*msg, *ptr; | ||||
|  | ||||
| 	va_start(ap, fmt); | ||||
| 	vasprintf(&msg, fmt, ap); | ||||
| 	va_end(ap); | ||||
|  | ||||
| 	for (ptr = msg; *ptr != '\0'; ptr++) { | ||||
| 		if (s->cx == screen_size_x(s)) | ||||
| 			break; | ||||
| 		screen_write_put_character(ctx, *ptr); | ||||
| 	} | ||||
|  | ||||
| 	xfree(msg); | ||||
| } | ||||
|  | ||||
| /* Set screen attributes. */ | ||||
| void | ||||
| screen_write_set_attributes( | ||||
|     struct screen_write_ctx *ctx, u_char attr, u_char colr) | ||||
| { | ||||
| 	struct screen	*s = ctx->s; | ||||
|  | ||||
| 	if (s->attr != attr || s->colr != colr) { | ||||
| 		s->attr = attr; | ||||
| 		s->colr = colr; | ||||
|  | ||||
| 		if (ctx->write != NULL) | ||||
| 			ctx->write(ctx->data, TTY_ATTRIBUTES, attr, colr); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| /* Set scroll region.  */ | ||||
| void | ||||
| screen_write_set_region(struct screen_write_ctx *ctx, u_int upper, u_int lower) | ||||
| { | ||||
| 	struct screen	*s = ctx->s; | ||||
|  | ||||
| 	screen_write_limit(upper, 0, screen_last_y(s)); | ||||
| 	screen_write_limit(lower, 0, screen_last_y(s)); | ||||
| 	if (upper > lower) | ||||
| 		return; | ||||
|  | ||||
| 	/* Cursor moves to top-left. */ | ||||
| 	s->cx = 0; | ||||
| 	s->cy = upper; | ||||
|  | ||||
| 	s->rupper = upper; | ||||
| 	s->rlower = lower; | ||||
|  | ||||
| 	if (ctx->write != NULL) | ||||
| 		ctx->write(ctx->data, TTY_SCROLLREGION, s->rupper, s->rlower); | ||||
| } | ||||
|  | ||||
| /* Move cursor up and scroll if necessary. */ | ||||
| void | ||||
| screen_write_cursor_up_scroll(struct screen_write_ctx *ctx) | ||||
| { | ||||
| 	struct screen	*s = ctx->s; | ||||
|  | ||||
| 	if (s->cy == s->rupper) | ||||
| 		screen_display_scroll_region_down(s); | ||||
| 	else if (s->cy > 0) | ||||
| 		s->cy--; | ||||
|  | ||||
| 	if (ctx->write != NULL) | ||||
| 		ctx->write(ctx->data, TTY_REVERSEINDEX); | ||||
| } | ||||
|  | ||||
| /* Move cursor down and scroll if necessary  */ | ||||
| void | ||||
| screen_write_cursor_down_scroll(struct screen_write_ctx *ctx) | ||||
| { | ||||
| 	struct screen	*s = ctx->s; | ||||
|  | ||||
| 	if (s->cy == s->rlower) | ||||
| 		screen_display_scroll_region_up(s); | ||||
| 	else if (s->cy < screen_last_y(s)) | ||||
| 		s->cy++; | ||||
|  | ||||
| 	if (ctx->write != NULL)	/* XXX FORWARDINDEX */ | ||||
| 		ctx->write(ctx->data, TTY_CHARACTER, '\n'); | ||||
| } | ||||
|  | ||||
| /* Move cursor up. */ | ||||
| void | ||||
| screen_write_cursor_up(struct screen_write_ctx *ctx, u_int n) | ||||
| { | ||||
| 	struct screen	*s = ctx->s; | ||||
|  | ||||
| 	screen_write_limit(n, 1, screen_above_y(s, s->cy) - 1); | ||||
|  | ||||
| 	s->cy -= n; | ||||
|  | ||||
| 	if (ctx->write != NULL) | ||||
| 		ctx->write(ctx->data, TTY_CURSORMOVE, s->cy, s->cx); | ||||
| } | ||||
|  | ||||
| /* Move cursor down. */ | ||||
| void | ||||
| screen_write_cursor_down(struct screen_write_ctx *ctx, u_int n) | ||||
| { | ||||
| 	struct screen	*s = ctx->s; | ||||
|  | ||||
| 	screen_write_limit(n, 1, screen_below_y(s, s->cy) - 1); | ||||
|  | ||||
| 	s->cy += n; | ||||
|  | ||||
| 	if (ctx->write != NULL) | ||||
| 		ctx->write(ctx->data, TTY_CURSORMOVE, s->cy, s->cx); | ||||
| } | ||||
|  | ||||
| /* Move cursor left.  */ | ||||
| void | ||||
| screen_write_cursor_left(struct screen_write_ctx *ctx, u_int n) | ||||
| { | ||||
| 	struct screen	*s = ctx->s; | ||||
|  | ||||
| 	screen_write_limit(n, 1, screen_left_x(s, s->cx) - 1); | ||||
|  | ||||
| 	s->cx -= n; | ||||
|  | ||||
| 	if (ctx->write != NULL) | ||||
| 		ctx->write(ctx->data, TTY_CURSORMOVE, s->cy, s->cx); | ||||
| } | ||||
|  | ||||
| /* Move cursor right.  */ | ||||
| void | ||||
| screen_write_cursor_right(struct screen_write_ctx *ctx, u_int n) | ||||
| { | ||||
| 	struct screen	*s = ctx->s; | ||||
|  | ||||
| 	screen_write_limit(n, 1, screen_right_x(s, s->cx) - 1); | ||||
|  | ||||
| 	s->cx += n; | ||||
|  | ||||
| 	if (ctx->write != NULL) | ||||
| 		ctx->write(ctx->data, TTY_CURSORMOVE, s->cy, s->cx); | ||||
| } | ||||
|  | ||||
| /* Delete lines. */ | ||||
| void | ||||
| screen_write_delete_lines(struct screen_write_ctx *ctx, u_int n) | ||||
| { | ||||
| 	struct screen	*s = ctx->s; | ||||
|  | ||||
| 	screen_write_limit(n, 1, screen_below_y(s, s->cy)); | ||||
|  | ||||
| 	if (s->cy < s->rupper || s->cy > s->rlower) | ||||
| 		screen_display_delete_lines(s, s->cy, n); | ||||
| 	else | ||||
| 		screen_display_delete_lines_region(s, s->cy, n); | ||||
|  | ||||
| 	if (ctx->write != NULL) | ||||
| 		ctx->write(ctx->data, TTY_DELETELINE, n); | ||||
| } | ||||
|  | ||||
| /* Delete characters. */ | ||||
| void | ||||
| screen_write_delete_characters(struct screen_write_ctx *ctx, u_int n) | ||||
| { | ||||
| 	struct screen	*s = ctx->s; | ||||
|  | ||||
| 	screen_write_limit(n, 1, screen_right_x(s, s->cx)); | ||||
|  | ||||
| 	screen_display_delete_characters(s, s->cx, s->cy, n); | ||||
|  | ||||
| 	if (ctx->write != NULL) | ||||
| 		ctx->write(ctx->data, TTY_DELETECHARACTER, n); | ||||
| } | ||||
|  | ||||
| /* Insert lines. */ | ||||
| void | ||||
| screen_write_insert_lines(struct screen_write_ctx *ctx, u_int n) | ||||
| { | ||||
| 	struct screen	*s = ctx->s; | ||||
|  | ||||
| 	screen_write_limit(n, 1, screen_below_y(s, s->cy)); | ||||
|  | ||||
| 	if (s->cy < s->rupper || s->cy > s->rlower) | ||||
| 		screen_display_insert_lines(s, s->cy, n); | ||||
| 	else | ||||
| 		screen_display_insert_lines_region(s, s->cy, n); | ||||
|  | ||||
| 	if (ctx->write != NULL) | ||||
| 		ctx->write(ctx->data, TTY_INSERTLINE, n); | ||||
| } | ||||
|  | ||||
| /* Insert characters. */ | ||||
| void | ||||
| screen_write_insert_characters(struct screen_write_ctx *ctx, u_int n) | ||||
| { | ||||
|  	struct screen	*s = ctx->s; | ||||
|  | ||||
| 	screen_write_limit(n, 1, screen_right_x(s, s->cx)); | ||||
|  | ||||
| 	screen_display_insert_characters(s, s->cx, s->cy, n); | ||||
|  | ||||
| 	if (ctx->write != NULL) | ||||
| 		ctx->write(ctx->data, TTY_INSERTCHARACTER, n); | ||||
| } | ||||
|  | ||||
| /* Move the cursor. */ | ||||
| void | ||||
| screen_write_move_cursor(struct screen_write_ctx *ctx, u_int n, u_int m) | ||||
| { | ||||
|  	struct screen	*s = ctx->s; | ||||
|  | ||||
| 	screen_write_limit(n, 0, screen_last_x(s)); | ||||
| 	screen_write_limit(m, 0, screen_last_y(s)); | ||||
|  | ||||
| 	s->cx = n; | ||||
| 	s->cy = m; | ||||
|  | ||||
| 	if (ctx->write != NULL) | ||||
| 		ctx->write(ctx->data, TTY_CURSORMOVE, s->cy, s->cx); | ||||
| } | ||||
|  | ||||
| /* Full to end of screen. */ | ||||
| void | ||||
| screen_write_fill_end_of_screen(struct screen_write_ctx *ctx) | ||||
| { | ||||
|  	struct screen	*s = ctx->s; | ||||
| 	u_int		 i; | ||||
|  | ||||
| 	screen_fill_area(s, s->cx, s->cy, | ||||
| 	    screen_right_x(s, s->cx), 1, SCREEN_DEFDATA, s->attr, s->colr); | ||||
| 	screen_fill_area(s, 0, s->cy + 1, | ||||
| 	    screen_below_y(s, s->cy + 1), 1, SCREEN_DEFDATA, s->attr, s->colr); | ||||
|  | ||||
| 	if (ctx->write != NULL) { | ||||
| 		ctx->write(ctx->data, TTY_CLEARENDOFLINE); | ||||
| 		for (i = s->cy + 1; i < screen_size_y(s); i++) { | ||||
| 			ctx->write(ctx->data, TTY_CURSORMOVE, i, 0); | ||||
| 			ctx->write(ctx->data, TTY_CLEARENDOFLINE); | ||||
| 		} | ||||
| 		ctx->write(ctx->data, TTY_CURSORMOVE, s->cy, s->cx); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| /* Fill entire screen. */ | ||||
| void | ||||
| screen_write_fill_screen(struct screen_write_ctx *ctx) | ||||
| { | ||||
|  	struct screen	*s = ctx->s; | ||||
| 	u_int		 i; | ||||
|  | ||||
| 	screen_display_fill_area(s, 0, 0, screen_size_x(s), screen_size_y(s), | ||||
| 	    SCREEN_DEFDATA, s->attr, s->colr); | ||||
|  | ||||
| 	if (ctx->write != NULL) { | ||||
| 		for (i = 0; i < screen_size_y(s); i++) { | ||||
| 			ctx->write(ctx->data, TTY_CURSORMOVE, i, 0); | ||||
| 			ctx->write(ctx->data, TTY_CLEARENDOFLINE); | ||||
| 		} | ||||
| 		ctx->write(ctx->data, TTY_CURSORMOVE, s->cy, s->cx); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| /* Fill to end of line.  */ | ||||
| void | ||||
| screen_write_fill_end_of_line(struct screen_write_ctx *ctx) | ||||
| { | ||||
|  	struct screen	*s = ctx->s; | ||||
|  | ||||
| 	screen_display_fill_area(s, s->cx, s->cy, | ||||
| 	    screen_right_x(s, s->cx), 1, SCREEN_DEFDATA, s->attr, s->colr); | ||||
|  | ||||
| 	if (ctx->write != NULL) | ||||
| 		ctx->write(ctx->data, TTY_CLEARENDOFLINE); | ||||
| } | ||||
|  | ||||
| /* Fill to start of line.  */ | ||||
| void | ||||
| screen_write_fill_start_of_line(struct screen_write_ctx *ctx) | ||||
| { | ||||
|  	struct screen	*s = ctx->s; | ||||
|  | ||||
| 	screen_display_fill_area(s, 0, s->cy, | ||||
| 	    screen_left_x(s, s->cx), 1, SCREEN_DEFDATA, s->attr, s->colr); | ||||
|  | ||||
| 	if (ctx->write != NULL) | ||||
| 		ctx->write(ctx->data, TTY_CLEARSTARTOFLINE); | ||||
| } | ||||
|  | ||||
| /* Fill entire line. */ | ||||
| void | ||||
| screen_write_fill_line(struct screen_write_ctx *ctx) | ||||
| { | ||||
|  	struct screen	*s = ctx->s; | ||||
|  | ||||
| 	screen_display_fill_area(s, 0, s->cy, | ||||
| 	    screen_size_x(s), s->cy, SCREEN_DEFDATA, s->attr, s->colr); | ||||
|  | ||||
| 	if (ctx->write != NULL) | ||||
| 		ctx->write(ctx->data, TTY_CLEARLINE); | ||||
| } | ||||
|  | ||||
| /* Set a screen mode. */ | ||||
| void | ||||
| screen_write_set_mode(struct screen_write_ctx *ctx, int mode) | ||||
| { | ||||
|  	struct screen	*s = ctx->s; | ||||
|  | ||||
| 	s->mode |= mode; | ||||
|  | ||||
| 	if (ctx->write == NULL) | ||||
| 		return; | ||||
|  | ||||
| 	if (mode & MODE_INSERT) | ||||
| 		ctx->write(ctx->data, TTY_INSERTON); | ||||
| 	if (mode & MODE_KCURSOR) | ||||
| 		ctx->write(ctx->data, TTY_KCURSORON); | ||||
| 	if (mode & MODE_KKEYPAD) | ||||
| 		ctx->write(ctx->data, TTY_KKEYPADON); | ||||
| 	if (mode & MODE_MOUSE) | ||||
| 		ctx->write(ctx->data, TTY_MOUSEON); | ||||
| } | ||||
|  | ||||
| /* Clear a screen mode. */ | ||||
| void | ||||
| screen_write_clear_mode(struct screen_write_ctx *ctx, int mode) | ||||
| { | ||||
|  	struct screen	*s = ctx->s; | ||||
|  | ||||
| 	s->mode &= ~mode; | ||||
|  | ||||
| 	if (ctx->write == NULL) | ||||
| 		return; | ||||
|  | ||||
| 	if (mode & MODE_INSERT) | ||||
| 		ctx->write(ctx->data, TTY_INSERTOFF); | ||||
| 	if (mode & MODE_KCURSOR) | ||||
| 		ctx->write(ctx->data, TTY_KCURSOROFF); | ||||
| 	if (mode & MODE_KKEYPAD) | ||||
| 		ctx->write(ctx->data, TTY_KKEYPADOFF); | ||||
| 	if (mode & MODE_MOUSE) | ||||
| 		ctx->write(ctx->data, TTY_MOUSEOFF); | ||||
| } | ||||
|  | ||||
| /* Copy cells from another screen. */ | ||||
| void | ||||
| screen_write_copy_area(struct screen_write_ctx *ctx, | ||||
|     struct screen *src, u_int nx, u_int ny, u_int ox, u_int oy) | ||||
| { | ||||
|  	struct screen		       *s = ctx->s; | ||||
| 	struct screen_redraw_ctx	rctx; | ||||
| 	int				saved_mode; | ||||
|  | ||||
| 	screen_write_limit(nx, 1, screen_right_x(s, s->cx)); | ||||
| 	screen_write_limit(ny, 1, screen_below_y(s, s->cy)); | ||||
|  | ||||
| 	screen_display_copy_area(ctx->s, src, s->cx, s->cy, nx, ny, ox, oy); | ||||
|  | ||||
| 	if (ctx->write != NULL) { | ||||
| 		/* Save mode XXX hack */ | ||||
| 		saved_mode = ctx->s->mode; | ||||
| 		ctx->s->mode &= ~MODE_CURSOR; | ||||
|  | ||||
| 		screen_redraw_start(&rctx, ctx->s, ctx->write, ctx->data); | ||||
| 		screen_redraw_area(&rctx, s->cx, s->cy, nx, ny); | ||||
| 		screen_redraw_stop(&rctx); | ||||
|  | ||||
| 		ctx->s->mode = saved_mode; | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										440
									
								
								screen.c
									
									
									
									
									
								
							
							
						
						
									
										440
									
								
								screen.c
									
									
									
									
									
								
							| @@ -1,4 +1,4 @@ | ||||
| /* $Id: screen.c,v 1.55 2007-12-02 18:23:10 nicm Exp $ */ | ||||
| /* $Id: screen.c,v 1.56 2007-12-06 09:46:23 nicm Exp $ */ | ||||
|  | ||||
| /* | ||||
|  * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> | ||||
| @@ -24,6 +24,54 @@ | ||||
|  | ||||
| /* | ||||
|  * Virtual screen. | ||||
|  * | ||||
|  * A screen is stored as three arrays of lines of 8-bit values, one for the | ||||
|  * actual characters (data), one for attributes and one for colours. Three | ||||
|  * seperate blocks means memset and friends can be used. Each array is y by x | ||||
|  * in size, row then column order. Sizes are 0-based. There is an additional | ||||
|  * array of u_ints with the size of each line. | ||||
|  * | ||||
|  * Each screen has a history starting at the beginning of the arrays and | ||||
|  * extending for hsize lines. Beyond that is the screen display of size | ||||
|  * dy: | ||||
|  * | ||||
|  * ----------- array base | ||||
|  * |         | | ||||
|  * | history | | ||||
|  * ----------- array base + hsize | ||||
|  * |         | | ||||
|  * | display | | ||||
|  * |         | | ||||
|  * ----------- array base + hsize + dy | ||||
|  * | ||||
|  * The screen_x/screen_y macros are used to convert a cell on the displayed | ||||
|  * area to an absolute position in the arrays.  | ||||
|  * | ||||
|  * Screen handling code is split into four files: | ||||
|  * | ||||
|  *	screen.c: Creation/deletion, utility functions, and basic functions to | ||||
|  *		  manipulate the screen based on offsets from the base. | ||||
|  *	screen-display.c: Basic functions for manipulating the displayed | ||||
|  *			  part of the screen. x,y coordinates passed to these | ||||
|  *			  are relative to the display. These are largely | ||||
|  *			  utility functions for screen-write.c.  | ||||
|  *	screen-redraw.c: Functions for redrawing all or part of a screen to | ||||
|  *			 one or more ttys. A context is filled via one of the | ||||
|  *			 screen_redraw_start* variants which sets up (removes | ||||
|  *			 cursor etc) and figures out which tty_write_* function | ||||
|  *			 to use to write to the terminals, then the other | ||||
|  *			 screen_redraw_* functions are used to draw the screen, | ||||
|  *			 and screen_redraw_stop used to reset the cursor and | ||||
|  *			 clean up. These are used when changing window and a | ||||
|  *			 few other bits (status line). | ||||
|  * 	screen-write.c: Functions for modifying (writing into) the screen and | ||||
|  *			optionally simultaneously updating one or more ttys. | ||||
|  *			These are used in much the same way as the redraw | ||||
|  *			functions. These are used to update when parsing | ||||
|  *			input from the window (input.c) and for the various | ||||
|  *			other modes which maintain private screens. | ||||
|  * | ||||
|  * If you're thinking this all seems too complicated, that's because it is :-/. | ||||
|  */ | ||||
|  | ||||
| /* Colour to string. */ | ||||
| @@ -104,6 +152,8 @@ screen_create(struct screen *s, u_int dx, u_int dy) | ||||
| 	s->grid_colr = xmalloc(dy * (sizeof *s->grid_colr)); | ||||
| 	s->grid_size = xmalloc(dy * (sizeof *s->grid_size)); | ||||
| 	screen_make_lines(s, 0, dy); | ||||
|  | ||||
| 	screen_clear_selection(s); | ||||
| } | ||||
|  | ||||
| /* Resize screen. */ | ||||
| @@ -237,6 +287,9 @@ screen_get_cell(struct screen *s, | ||||
| 		*attr = s->grid_attr[cy][cx]; | ||||
| 		*colr = s->grid_colr[cy][cx]; | ||||
| 	} | ||||
|  | ||||
| 	if (screen_check_selection(s, cx, cy)) | ||||
| 		*attr |= ATTR_REVERSE; | ||||
| } | ||||
|  | ||||
| /* Set a cell. */ | ||||
| @@ -268,331 +321,6 @@ screen_destroy(struct screen *s) | ||||
| 	xfree(s->grid_size); | ||||
| } | ||||
|  | ||||
| /* Initialise redrawing a window. */ | ||||
| void | ||||
| screen_draw_start_window( | ||||
|     struct screen_draw_ctx *ctx, struct window *w, u_int ox, u_int oy) | ||||
| { | ||||
| 	struct screen	*t = &w->screen; | ||||
|  | ||||
| 	screen_draw_start(ctx, t, tty_write_window, w, ox, oy); | ||||
| } | ||||
|  | ||||
| /* Initialise redrawing a client. */ | ||||
| void | ||||
| screen_draw_start_client( | ||||
|     struct screen_draw_ctx *ctx, struct client *c, u_int ox, u_int oy) | ||||
| { | ||||
| 	struct screen	*t = &c->session->curw->window->screen; | ||||
|  | ||||
| 	screen_draw_start(ctx, t, tty_write_client, c, ox, oy); | ||||
| } | ||||
|  | ||||
| /* Initialise redrawing a session. */ | ||||
| void | ||||
| screen_draw_start_session( | ||||
|     struct screen_draw_ctx *ctx, struct session *s, u_int ox, u_int oy) | ||||
| { | ||||
| 	struct screen	*t = &s->curw->window->screen; | ||||
|  | ||||
| 	screen_draw_start(ctx, t, tty_write_session, s, ox, oy); | ||||
| } | ||||
|  | ||||
| /* Initialise drawing. */ | ||||
| void | ||||
| screen_draw_start(struct screen_draw_ctx *ctx, struct screen *s, | ||||
|     void (*write)(void *, int, ...), void *data, u_int ox, u_int oy) | ||||
| { | ||||
| 	ctx->write = write; | ||||
| 	ctx->data = data; | ||||
|  | ||||
| 	ctx->s = s; | ||||
|  | ||||
| 	ctx->ox = ox; | ||||
| 	ctx->oy = oy; | ||||
|  | ||||
| 	/* Resetting the scroll region homes the cursor so start at 0,0. */ | ||||
| 	ctx->cx = 0; | ||||
| 	ctx->cy = 0; | ||||
|  | ||||
| 	ctx->sel.flag = 0; | ||||
|  | ||||
| 	ctx->write(ctx->data, TTY_ATTRIBUTES, s->attr, s->colr); | ||||
| 	ctx->write(ctx->data, TTY_SCROLLREGION, 0, screen_last_y(s)); | ||||
| 	ctx->write(ctx->data, TTY_CURSOROFF); | ||||
| 	ctx->write(ctx->data, TTY_MOUSEOFF); | ||||
| } | ||||
|  | ||||
| /* Set offset. */ | ||||
| void | ||||
| screen_draw_set_offset(struct screen_draw_ctx *ctx, u_int ox, u_int oy) | ||||
| { | ||||
| 	ctx->ox = ox; | ||||
| 	ctx->oy = oy; | ||||
| } | ||||
|  | ||||
| /* Set selection. */ | ||||
| void | ||||
| screen_draw_set_selection(struct screen_draw_ctx *ctx,  | ||||
|     int flag, u_int sx, u_int sy, u_int ex, u_int ey) | ||||
| { | ||||
| 	struct screen_draw_sel	*sel = &ctx->sel; | ||||
|  | ||||
| 	sel->flag = flag; | ||||
| 	if (!sel->flag) | ||||
| 		return; | ||||
|  | ||||
| 	if (ey < sy || (sy == ey && ex < sx)) { | ||||
| 		sel->sx = ex; sel->sy = ey; | ||||
| 		sel->ex = sx; sel->ey = sy; | ||||
| 	} else { | ||||
| 		sel->sx = sx; sel->sy = sy; | ||||
| 		sel->ex = ex; sel->ey = ey; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| /* Check if cell in selection. */ | ||||
| int | ||||
| screen_draw_check_selection(struct screen_draw_ctx *ctx, u_int px, u_int py) | ||||
| { | ||||
| 	struct screen_draw_sel	*sel = &ctx->sel; | ||||
|  | ||||
| 	if (!sel->flag) | ||||
| 		return (0); | ||||
|  | ||||
| 	if (py < sel->sy || py > sel->ey) | ||||
| 		return (0); | ||||
|  | ||||
| 	if (py == sel->sy && py == sel->ey) { | ||||
| 		if (px < sel->sx || px > sel->ex) | ||||
| 			return (0); | ||||
| 		return (1); | ||||
| 	} | ||||
|  | ||||
| 	if ((py == sel->sy && px < sel->sx) || (py == sel->ey && px > sel->ex)) | ||||
| 		return (0); | ||||
| 	return (1); | ||||
| } | ||||
|  | ||||
| /* Get cell data during drawing. */ | ||||
| void | ||||
| screen_draw_get_cell(struct screen_draw_ctx *ctx, | ||||
|     u_int px, u_int py, u_char *data, u_char *attr, u_char *colr) | ||||
| { | ||||
| 	struct screen	*s = ctx->s; | ||||
| 	u_int		 cx, cy; | ||||
| 	 | ||||
| 	cx = ctx->ox + px; | ||||
| 	cy = screen_y(s, py) - ctx->oy; | ||||
|  | ||||
| 	screen_get_cell(s, cx, cy, data, attr, colr); | ||||
|  | ||||
| 	if (screen_draw_check_selection(ctx, cx, cy)) | ||||
| 		*attr |= ATTR_REVERSE; | ||||
| } | ||||
|  | ||||
| /* Finalise drawing. */ | ||||
| void | ||||
| screen_draw_stop(struct screen_draw_ctx *ctx) | ||||
| { | ||||
| 	struct screen	*s = ctx->s; | ||||
|  | ||||
| 	ctx->write(ctx->data, TTY_SCROLLREGION, s->rupper, s->rlower); | ||||
|  | ||||
| 	if (ctx->cx != s->cx || ctx->cy != s->cy) | ||||
| 		ctx->write(ctx->data, TTY_CURSORMOVE, s->cy, s->cx); | ||||
|  | ||||
| 	ctx->write(ctx->data, TTY_ATTRIBUTES, s->attr, s->colr); | ||||
|  | ||||
| 	if (s->mode & MODE_BACKGROUND) { | ||||
| 		if (s->mode & MODE_BGCURSOR) | ||||
| 			ctx->write(ctx->data, TTY_CURSORON); | ||||
| 	} else { | ||||
| 		if (s->mode & MODE_CURSOR) | ||||
| 			ctx->write(ctx->data, TTY_CURSORON); | ||||
| 	} | ||||
| 	if (s->mode & MODE_MOUSE) | ||||
| 		ctx->write(ctx->data, TTY_MOUSEON); | ||||
| } | ||||
|  | ||||
| /* Insert lines. */ | ||||
| void | ||||
| screen_draw_insert_lines(struct screen_draw_ctx *ctx, u_int ny) | ||||
| { | ||||
| 	ctx->write(ctx->data, TTY_INSERTLINE, ny); | ||||
| } | ||||
|  | ||||
| /* Delete lines. */ | ||||
| void | ||||
| screen_draw_delete_lines(struct screen_draw_ctx *ctx, u_int ny) | ||||
| { | ||||
| 	ctx->write(ctx->data, TTY_DELETELINE, ny); | ||||
| } | ||||
|  | ||||
| /* Insert characters. */ | ||||
| void | ||||
| screen_draw_insert_characters(struct screen_draw_ctx *ctx, u_int nx) | ||||
| { | ||||
| 	ctx->write(ctx->data, TTY_INSERTCHARACTER, nx); | ||||
| } | ||||
|  | ||||
| /* Delete characters. */ | ||||
| void | ||||
| screen_draw_delete_characters(struct screen_draw_ctx *ctx, u_int nx) | ||||
| { | ||||
| 	ctx->write(ctx->data, TTY_DELETECHARACTER, nx); | ||||
| } | ||||
|  | ||||
| /* Clear end of line. */ | ||||
| void | ||||
| screen_draw_clear_line_to(struct screen_draw_ctx *ctx, u_int px) | ||||
| { | ||||
| 	while (ctx->cx <= px) { | ||||
| 		ctx->write(ctx->data, TTY_CHARACTER, SCREEN_DEFDATA); | ||||
| 		ctx->cx++; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| /* Clear screen. */ | ||||
| void | ||||
| screen_draw_clear_screen(struct screen_draw_ctx *ctx) | ||||
| { | ||||
| 	u_int	i; | ||||
|  | ||||
| 	screen_draw_set_attributes(ctx, SCREEN_DEFATTR, SCREEN_DEFCOLR); | ||||
| 	for (i = 0; i < screen_size_y(ctx->s); i++) { | ||||
| 		screen_draw_move_cursor(ctx, 0, i); | ||||
| 		screen_draw_clear_line_to(ctx, screen_size_x(ctx->s)); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| /* Write string. */ | ||||
| void printflike2 | ||||
| screen_draw_write_string(struct screen_draw_ctx *ctx, const char *fmt, ...) | ||||
| { | ||||
| 	struct screen	*s = ctx->s; | ||||
| 	va_list		 ap; | ||||
| 	char   		*msg, *ptr; | ||||
|  | ||||
| 	va_start(ap, fmt); | ||||
| 	xvasprintf(&msg, fmt, ap); | ||||
| 	va_end(ap); | ||||
|  | ||||
| 	for (ptr = msg; *ptr != '\0'; ptr++) { | ||||
| 		if (ctx->cx > screen_last_x(s)) | ||||
| 			break; | ||||
| 		ctx->write(ctx->data, TTY_CHARACTER, *ptr); | ||||
| 		ctx->cx++; | ||||
| 	} | ||||
|  | ||||
| 	xfree(msg); | ||||
| } | ||||
|  | ||||
| /* Move cursor. */ | ||||
| void | ||||
| screen_draw_move_cursor(struct screen_draw_ctx *ctx, u_int px, u_int py) | ||||
| { | ||||
| 	if (px == ctx->cx && py == ctx->cy) | ||||
| 		return; | ||||
|  | ||||
| 	if (px == 0 && py == ctx->cy) | ||||
| 		ctx->write(ctx->data, TTY_CHARACTER, '\r'); | ||||
| 	else if (px == ctx->cx && py == ctx->cy + 1) | ||||
| 		ctx->write(ctx->data, TTY_CHARACTER, '\n'); | ||||
| 	else if (px == 0 && py == ctx->cy + 1) { | ||||
| 		ctx->write(ctx->data, TTY_CHARACTER, '\r'); | ||||
| 		ctx->write(ctx->data, TTY_CHARACTER, '\n'); | ||||
| 	} else | ||||
| 		ctx->write(ctx->data, TTY_CURSORMOVE, py, px); | ||||
|  | ||||
| 	ctx->cx = px; | ||||
| 	ctx->cy = py; | ||||
| } | ||||
|  | ||||
| /* Set attributes. */ | ||||
| void | ||||
| screen_draw_set_attributes( | ||||
|     struct screen_draw_ctx *ctx, u_char attr, u_char colr) | ||||
| { | ||||
| 	ctx->write(ctx->data, TTY_ATTRIBUTES, attr, colr); | ||||
| } | ||||
|  | ||||
| /* Draw single cell. */ | ||||
| void | ||||
| screen_draw_cell(struct screen_draw_ctx *ctx, u_int px, u_int py) | ||||
| { | ||||
| 	u_char	 data, attr, colr; | ||||
|  | ||||
| 	screen_draw_move_cursor(ctx, px, py); | ||||
|  | ||||
| 	screen_draw_get_cell(ctx, px, py, &data, &attr, &colr); | ||||
| 	screen_draw_set_attributes(ctx, attr, colr); | ||||
| 	ctx->write(ctx->data, TTY_CHARACTER, data); | ||||
|  | ||||
| 	/* | ||||
| 	 * Don't try to wrap as it will cause problems when screen is smaller | ||||
| 	 * than client. | ||||
| 	 */ | ||||
| 	ctx->cx++; | ||||
| } | ||||
|  | ||||
| /* Draw range of cells. */ | ||||
| void | ||||
| screen_draw_cells(struct screen_draw_ctx *ctx, u_int px, u_int py, u_int nx) | ||||
| { | ||||
| 	u_int	i; | ||||
|  | ||||
| 	for (i = px; i < px + nx; i++) | ||||
| 		screen_draw_cell(ctx, i, py); | ||||
| } | ||||
|  | ||||
| /* Draw single column. */ | ||||
| void | ||||
| screen_draw_column(struct screen_draw_ctx *ctx, u_int px) | ||||
| { | ||||
| 	u_int	i; | ||||
|  | ||||
| 	for (i = 0; i < screen_size_y(ctx->s); i++) | ||||
| 		screen_draw_cell(ctx, px, i); | ||||
| } | ||||
|  | ||||
| /* Draw single line. */ | ||||
| void | ||||
| screen_draw_line(struct screen_draw_ctx *ctx, u_int py) | ||||
| { | ||||
|        u_int   cx, cy; | ||||
|  | ||||
|        cy = screen_y(ctx->s, py) - ctx->oy; | ||||
|        cx = ctx->s->grid_size[cy]; | ||||
|  | ||||
|        if (ctx->sel.flag || | ||||
| 	   screen_size_x(ctx->s) < 5 || cx >= screen_size_x(ctx->s) - 5) | ||||
|                screen_draw_cells(ctx, 0, py, screen_size_x(ctx->s)); | ||||
|        else { | ||||
|                screen_draw_cells(ctx, 0, py, cx); | ||||
|                screen_draw_move_cursor(ctx, cx, py); | ||||
| 	       screen_draw_set_attributes(ctx, SCREEN_DEFATTR, SCREEN_DEFCOLR); | ||||
|                ctx->write(ctx->data, TTY_CLEARENDOFLINE); | ||||
|        } | ||||
| } | ||||
|  | ||||
| /* Draw set of lines. */ | ||||
| void | ||||
| screen_draw_lines(struct screen_draw_ctx *ctx, u_int py, u_int ny) | ||||
| { | ||||
| 	u_int	i; | ||||
|  | ||||
| 	for (i = py; i < py + ny; i++) | ||||
| 		screen_draw_line(ctx, i); | ||||
| } | ||||
|  | ||||
| /* Draw entire screen. */ | ||||
| void | ||||
| screen_draw_screen(struct screen_draw_ctx *ctx) | ||||
| { | ||||
| 	screen_draw_lines(ctx, 0, screen_size_y(ctx->s)); | ||||
| } | ||||
|  | ||||
| /* Create a range of lines. */ | ||||
| void | ||||
| screen_make_lines(struct screen *s, u_int py, u_int ny) | ||||
| @@ -641,24 +369,60 @@ screen_move_lines(struct screen *s, u_int dy, u_int py, u_int ny) | ||||
| 	    &s->grid_size[dy], &s->grid_size[py], ny * (sizeof *s->grid_size)); | ||||
| } | ||||
|  | ||||
| /* Fill a range of lines. */ | ||||
| /* Fill an area. */ | ||||
| void | ||||
| screen_fill_lines( | ||||
|     struct screen *s, u_int py, u_int ny, u_char data, u_char attr, u_char colr) | ||||
| screen_fill_area(struct screen *s, u_int px, u_int py, | ||||
|     u_int nx, u_int ny, u_char data, u_char attr, u_char colr) | ||||
| { | ||||
| 	u_int	i; | ||||
| 	u_int	i, j; | ||||
|  | ||||
| 	for (i = py; i < py + ny; i++) | ||||
| 		screen_fill_cells(s, 0, i, s->dx, data, attr, colr); | ||||
| 	for (i = py; i < py + ny; i++) { | ||||
| 		for (j = px; j < px + nx; j++) | ||||
| 			screen_set_cell(s, j, i, data, attr, colr); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| /* Fill a range of cells. */ | ||||
| /* Set selection. */ | ||||
| void | ||||
| screen_fill_cells(struct screen *s, | ||||
|     u_int px, u_int py, u_int nx, u_char data, u_char attr, u_char colr) | ||||
| screen_set_selection(struct screen *s, u_int sx, u_int sy, u_int ex, u_int ey) | ||||
| { | ||||
| 	u_int	i; | ||||
| 	struct screen_sel	*sel = &s->sel; | ||||
|  | ||||
| 	for (i = px; i < px + nx; i++) | ||||
| 		screen_set_cell(s, i, py, data, attr, colr); | ||||
| 	sel->flag = 1; | ||||
| 	if (ey < sy || (sy == ey && ex < sx)) { | ||||
| 		sel->sx = ex; sel->sy = ey; | ||||
| 		sel->ex = sx; sel->ey = sy; | ||||
| 	} else { | ||||
| 		sel->sx = sx; sel->sy = sy; | ||||
| 		sel->ex = ex; sel->ey = ey; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| /* Clear selection. */ | ||||
| void | ||||
| screen_clear_selection(struct screen *s) | ||||
| { | ||||
| 	struct screen_sel	*sel = &s->sel; | ||||
|  | ||||
| 	sel->flag = 0; | ||||
| } | ||||
|  | ||||
| /* Check if cell in selection. */ | ||||
| int | ||||
| screen_check_selection(struct screen *s, u_int px, u_int py) | ||||
| { | ||||
| 	struct screen_sel	*sel = &s->sel; | ||||
|  | ||||
| 	if (!sel->flag || py < sel->sy || py > sel->ey) | ||||
| 		return (0); | ||||
|  | ||||
| 	if (py == sel->sy && py == sel->ey) { | ||||
| 		if (px < sel->sx || px > sel->ex) | ||||
| 			return (0); | ||||
| 		return (1); | ||||
| 	} | ||||
|  | ||||
| 	if ((py == sel->sy && px < sel->sx) || (py == sel->ey && px > sel->ex)) | ||||
| 		return (0); | ||||
| 	return (1); | ||||
| } | ||||
|   | ||||
							
								
								
									
										71
									
								
								server-fn.c
									
									
									
									
									
								
							
							
						
						
									
										71
									
								
								server-fn.c
									
									
									
									
									
								
							| @@ -1,4 +1,4 @@ | ||||
| /* $Id: server-fn.c,v 1.35 2007-11-27 19:23:34 nicm Exp $ */ | ||||
| /* $Id: server-fn.c,v 1.36 2007-12-06 09:46:23 nicm Exp $ */ | ||||
|  | ||||
| /* | ||||
|  * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> | ||||
| @@ -123,11 +123,12 @@ server_write_window( | ||||
| void | ||||
| server_clear_client(struct client *c) | ||||
| { | ||||
| 	struct screen_draw_ctx	ctx; | ||||
| 	struct screen_redraw_ctx	ctx; | ||||
|  | ||||
| 	screen_draw_start_client(&ctx, c, 0, 0); | ||||
| 	screen_draw_clear_screen(&ctx); | ||||
| 	screen_draw_stop(&ctx); | ||||
| 	screen_redraw_start_client(&ctx, c); | ||||
| 	screen_redraw_set_attributes(&ctx, SCREEN_DEFATTR, SCREEN_DEFCOLR); | ||||
| 	screen_redraw_clear_screen(&ctx); | ||||
| 	screen_redraw_stop(&ctx); | ||||
|  | ||||
| 	status_write_client(c); | ||||
| } | ||||
| @@ -135,12 +136,11 @@ server_clear_client(struct client *c) | ||||
| void | ||||
| server_redraw_client(struct client *c) | ||||
| { | ||||
| 	struct screen_draw_ctx	ctx; | ||||
| 	struct window	       *w = c->session->curw->window; | ||||
| 	struct screen_redraw_ctx	ctx; | ||||
|  | ||||
| 	screen_draw_start_client(&ctx, c, 0, 0); | ||||
| 	window_draw(w, &ctx, 0, screen_size_y(&w->screen)); | ||||
| 	screen_draw_stop(&ctx); | ||||
| 	screen_redraw_start_client(&ctx, c); | ||||
| 	screen_redraw_lines(&ctx, 0, screen_size_y(ctx.s)); | ||||
| 	screen_redraw_stop(&ctx); | ||||
|  | ||||
| 	status_write_client(c); | ||||
| } | ||||
| @@ -154,11 +154,12 @@ server_status_client(struct client *c) | ||||
| void | ||||
| server_clear_session(struct session *s) | ||||
| { | ||||
| 	struct screen_draw_ctx	ctx; | ||||
| 	struct screen_redraw_ctx	ctx; | ||||
|  | ||||
| 	screen_draw_start_session(&ctx, s, 0, 0); | ||||
| 	screen_draw_clear_screen(&ctx); | ||||
| 	screen_draw_stop(&ctx); | ||||
| 	screen_redraw_start_session(&ctx, s); | ||||
| 	screen_redraw_set_attributes(&ctx, SCREEN_DEFATTR, SCREEN_DEFCOLR); | ||||
| 	screen_redraw_clear_screen(&ctx); | ||||
| 	screen_redraw_stop(&ctx); | ||||
|  | ||||
| 	status_write_session(s); | ||||
| } | ||||
| @@ -166,12 +167,11 @@ server_clear_session(struct session *s) | ||||
| void | ||||
| server_redraw_session(struct session *s) | ||||
| { | ||||
| 	struct screen_draw_ctx	ctx; | ||||
| 	struct window	       *w = s->curw->window; | ||||
| 	struct screen_redraw_ctx	ctx; | ||||
|  | ||||
| 	screen_draw_start_session(&ctx, s, 0, 0); | ||||
| 	window_draw(w, &ctx, 0, screen_size_y(&w->screen)); | ||||
| 	screen_draw_stop(&ctx); | ||||
| 	screen_redraw_start_session(&ctx, s); | ||||
| 	screen_redraw_lines(&ctx, 0, screen_size_y(ctx.s)); | ||||
| 	screen_redraw_stop(&ctx); | ||||
|  | ||||
| 	status_write_session(s); | ||||
| } | ||||
| @@ -185,11 +185,12 @@ server_status_session(struct session *s) | ||||
| void | ||||
| server_clear_window(struct window *w) | ||||
| { | ||||
| 	struct screen_draw_ctx	ctx; | ||||
| 	struct screen_redraw_ctx	ctx; | ||||
|  | ||||
| 	screen_draw_start_window(&ctx, w, 0, 0); | ||||
| 	screen_draw_clear_screen(&ctx); | ||||
| 	screen_draw_stop(&ctx); | ||||
| 	screen_redraw_start_window(&ctx, w); | ||||
| 	screen_redraw_set_attributes(&ctx, SCREEN_DEFATTR, SCREEN_DEFCOLR); | ||||
| 	screen_redraw_clear_screen(&ctx); | ||||
| 	screen_redraw_stop(&ctx); | ||||
|  | ||||
| 	status_write_window(w); | ||||
| } | ||||
| @@ -197,11 +198,11 @@ server_clear_window(struct window *w) | ||||
| void | ||||
| server_redraw_window(struct window *w) | ||||
| { | ||||
| 	struct screen_draw_ctx	ctx; | ||||
| 	struct screen_redraw_ctx	ctx; | ||||
|  | ||||
| 	screen_draw_start_window(&ctx, w, 0, 0); | ||||
| 	window_draw(w, &ctx, 0, screen_size_y(&w->screen)); | ||||
| 	screen_draw_stop(&ctx); | ||||
| 	screen_redraw_start_window(&ctx, w); | ||||
| 	screen_redraw_lines(&ctx, 0, screen_size_y(ctx.s)); | ||||
| 	screen_redraw_stop(&ctx); | ||||
|  | ||||
| 	status_write_window(w); | ||||
| } | ||||
| @@ -228,14 +229,14 @@ server_status_window(struct window *w) | ||||
| void printflike2 | ||||
| server_write_message(struct client *c, const char *fmt, ...) | ||||
| { | ||||
| 	struct screen_draw_ctx	ctx; | ||||
| 	struct screen_redraw_ctx	ctx; | ||||
| 	va_list				ap; | ||||
| 	char			       *msg; | ||||
| 	size_t				size; | ||||
|  | ||||
| 	screen_draw_start_client(&ctx, c, 0, 0); | ||||
| 	screen_draw_move_cursor(&ctx, 0, c->sy - 1); | ||||
| 	screen_draw_set_attributes(&ctx, ATTR_REVERSE, 0x88); | ||||
| 	screen_redraw_start_client(&ctx, c); | ||||
| 	screen_redraw_move_cursor(&ctx, 0, c->sy - 1); | ||||
| 	screen_redraw_set_attributes(&ctx, ATTR_REVERSE, 0x88); | ||||
|  | ||||
| 	va_start(ap, fmt); | ||||
| 	xvasprintf(&msg, fmt, ap); | ||||
| @@ -247,17 +248,17 @@ server_write_message(struct client *c, const char *fmt, ...) | ||||
| 		msg[c->sx - 1] = '\0'; | ||||
| 		memset(msg + size, SCREEN_DEFDATA, (c->sx - 1) - size); | ||||
| 	} | ||||
| 	screen_draw_write_string(&ctx, "%s", msg); | ||||
| 	screen_redraw_write_string(&ctx, "%s", msg); | ||||
| 	xfree(msg); | ||||
|  | ||||
| 	buffer_flush(c->tty.fd, c->tty.in, c->tty.out); | ||||
| 	usleep(750000); | ||||
|  | ||||
| 	if (status_lines == 0) { | ||||
| 		window_draw(c->session->curw->window, &ctx, c->sy - 1, 1); | ||||
| 		screen_draw_stop(&ctx); | ||||
| 		screen_redraw_lines(&ctx, c->sy - 1, 1); | ||||
| 		screen_redraw_stop(&ctx); | ||||
| 	} else { | ||||
| 		screen_draw_stop(&ctx); | ||||
| 		screen_redraw_stop(&ctx); | ||||
| 		status_write_client(c); | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -1,5 +1,5 @@ | ||||
|  | ||||
| /* $Id: server-msg.c,v 1.39 2007-11-27 20:01:30 nicm Exp $ */ | ||||
| /* $Id: server-msg.c,v 1.40 2007-12-06 09:46:23 nicm Exp $ */ | ||||
|  | ||||
| /* | ||||
|  * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> | ||||
|   | ||||
							
								
								
									
										2
									
								
								server.c
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								server.c
									
									
									
									
									
								
							| @@ -1,4 +1,4 @@ | ||||
| /* $Id: server.c,v 1.43 2007-12-04 20:25:17 nicm Exp $ */ | ||||
| /* $Id: server.c,v 1.44 2007-12-06 09:46:23 nicm Exp $ */ | ||||
|  | ||||
| /* | ||||
|  * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| /* $Id: session.c,v 1.29 2007-11-12 16:39:30 nicm Exp $ */ | ||||
| /* $Id: session.c,v 1.30 2007-12-06 09:46:23 nicm Exp $ */ | ||||
|  | ||||
| /* | ||||
|  * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> | ||||
|   | ||||
							
								
								
									
										20
									
								
								status.c
									
									
									
									
									
								
							
							
						
						
									
										20
									
								
								status.c
									
									
									
									
									
								
							| @@ -1,4 +1,4 @@ | ||||
| /* $Id: status.c,v 1.14 2007-11-27 19:23:34 nicm Exp $ */ | ||||
| /* $Id: status.c,v 1.15 2007-12-06 09:46:23 nicm Exp $ */ | ||||
|  | ||||
| /* | ||||
|  * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> | ||||
| @@ -27,16 +27,16 @@ void printflike3 status_print(struct buffer *, size_t *, const char *, ...); | ||||
| void | ||||
| status_write_client(struct client *c) | ||||
| { | ||||
| 	struct screen_draw_ctx	ctx; | ||||
| 	struct screen_redraw_ctx	ctx; | ||||
| 	struct winlink	       	       *wl; | ||||
| 	char				flag; | ||||
|  | ||||
| 	if (status_lines == 0 || c->sy <= status_lines) | ||||
| 		return; | ||||
|  | ||||
| 	screen_draw_start_client(&ctx, c, 0, 0); | ||||
| 	screen_draw_move_cursor(&ctx, 0, c->sy - status_lines); | ||||
| 	screen_draw_set_attributes(&ctx, 0, status_colour); | ||||
| 	screen_redraw_start_client(&ctx, c); | ||||
| 	screen_redraw_move_cursor(&ctx, 0, c->sy - status_lines); | ||||
| 	screen_redraw_set_attributes(&ctx, 0, status_colour); | ||||
|  | ||||
| 	RB_FOREACH(wl, winlinks, &c->session->windows) { | ||||
| 		flag = ' '; | ||||
| @@ -46,15 +46,15 @@ status_write_client(struct client *c) | ||||
| 			flag = '*'; | ||||
| 		if (session_hasbell(c->session, wl)) | ||||
| 			flag = '!'; | ||||
| 		screen_draw_write_string( | ||||
| 		screen_redraw_write_string( | ||||
| 		    &ctx, "%d:%s%c ", wl->idx, wl->window->name, flag); | ||||
|  | ||||
| 		if (ctx.cx >= screen_last_x(ctx.s)) | ||||
| 		if (ctx.s->cx >= screen_last_x(ctx.s)) | ||||
| 			break; | ||||
| 	} | ||||
| 	screen_draw_clear_line_to(&ctx, screen_last_x(ctx.s)); | ||||
| 	screen_redraw_clear_end_of_line(&ctx); | ||||
|  | ||||
| 	screen_draw_stop(&ctx); | ||||
| 	screen_redraw_stop(&ctx); | ||||
| } | ||||
|  | ||||
| void | ||||
| @@ -63,7 +63,7 @@ status_write_window(struct window *w) | ||||
| 	struct client	*c; | ||||
| 	u_int		 i; | ||||
|  | ||||
| 	if (w->screen.mode & MODE_HIDDEN) | ||||
| 	if (w->flags & WINDOW_HIDDEN) | ||||
| 		return; | ||||
|  | ||||
| 	for (i = 0; i < ARRAY_LENGTH(&clients); i++) { | ||||
|   | ||||
							
								
								
									
										2
									
								
								tmux.c
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								tmux.c
									
									
									
									
									
								
							| @@ -1,4 +1,4 @@ | ||||
| /* $Id: tmux.c,v 1.44 2007-11-23 17:52:54 nicm Exp $ */ | ||||
| /* $Id: tmux.c,v 1.45 2007-12-06 09:46:23 nicm Exp $ */ | ||||
|  | ||||
| /* | ||||
|  * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> | ||||
|   | ||||
							
								
								
									
										209
									
								
								tmux.h
									
									
									
									
									
								
							
							
						
						
									
										209
									
								
								tmux.h
									
									
									
									
									
								
							| @@ -1,4 +1,4 @@ | ||||
| /* $Id: tmux.h,v 1.108 2007-12-02 18:23:10 nicm Exp $ */ | ||||
| /* $Id: tmux.h,v 1.109 2007-12-06 09:46:23 nicm Exp $ */ | ||||
|  | ||||
| /* | ||||
|  * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> | ||||
| @@ -335,23 +335,25 @@ struct msg_resize_data { | ||||
| #define ATTR_CHARSET 0x80	/* alternative character set */ | ||||
|  | ||||
| /* Modes. */ | ||||
| #define MODE_CURSOR 0x001 | ||||
| #define MODE_INSERT 0x002 | ||||
| #define MODE_KCURSOR 0x004 | ||||
| #define MODE_KKEYPAD 0x008 | ||||
| #define MODE_SAVED 0x010 | ||||
| #define MODE_HIDDEN 0x020 | ||||
| #define MODE_BACKGROUND 0x040 | ||||
| #define MODE_BGCURSOR 0x080 | ||||
| #define MODE_MOUSE 0x100 | ||||
| #define MODE_CURSOR 0x01 | ||||
| #define MODE_INSERT 0x02 | ||||
| #define MODE_KCURSOR 0x04 | ||||
| #define MODE_KKEYPAD 0x08 | ||||
| #define MODE_SAVED 0x10 | ||||
| #define MODE_MOUSE 0x20 | ||||
|  | ||||
| /* | ||||
|  * Virtual screen. This is stored as three blocks of 8-bit values, one for | ||||
|  * the actual characters, one for attributes and one for colours. Three | ||||
|  * seperate blocks means memset and friends can be used. | ||||
|  * | ||||
|  * Each block is y by x in size, row then column order. Sizes are 0-based. | ||||
|  */ | ||||
| /* Screen selection. */ | ||||
| struct screen_sel { | ||||
| 	int		 flag; | ||||
|  | ||||
| 	u_int		 sx; | ||||
| 	u_int		 sy; | ||||
|  | ||||
| 	u_int		 ex; | ||||
| 	u_int		 ey; | ||||
| }; | ||||
|  | ||||
| /* Virtual screen. */ | ||||
| struct screen { | ||||
| 	char		*title; | ||||
|  | ||||
| @@ -380,33 +382,27 @@ struct screen { | ||||
| 	u_char		 saved_colr; | ||||
|  | ||||
| 	int		 mode; | ||||
| }; | ||||
|  | ||||
| /* Screen redraw selection. */ | ||||
| struct screen_draw_sel { | ||||
| 	int		 flag; | ||||
|  | ||||
| 	u_int		 sx; | ||||
| 	u_int		 sy; | ||||
|  | ||||
| 	u_int		 ex; | ||||
| 	u_int		 ey; | ||||
| 	struct screen_sel sel; | ||||
| }; | ||||
|  | ||||
| /* Screen redraw context. */ | ||||
| struct screen_draw_ctx { | ||||
| struct screen_redraw_ctx { | ||||
| 	void		*data; | ||||
| 	void		 (*write)(void *, int, ...); | ||||
|  | ||||
| 	u_int		 saved_cx; | ||||
| 	u_int		 saved_cy; | ||||
|  | ||||
| 	struct screen	*s; | ||||
| }; | ||||
|  | ||||
| /* Screen write context. */ | ||||
| struct screen_write_ctx { | ||||
| 	void		*data; | ||||
| 	void		 (*write)(void *, int, ...); | ||||
|  | ||||
| 	struct screen	*s; | ||||
|  | ||||
| 	u_int		 cx; | ||||
| 	u_int		 cy; | ||||
|  | ||||
| 	u_int		 ox; | ||||
| 	u_int		 oy; | ||||
|  | ||||
| 	struct screen_draw_sel sel; | ||||
| }; | ||||
|  | ||||
| /* Screen display access macros. */ | ||||
| @@ -423,6 +419,15 @@ struct screen_draw_ctx { | ||||
| #define screen_in_y(s, y) ((y) < screen_size_y(s)) | ||||
| #define screen_in_region(s, y) ((y) >= (s)->rupper && (y) <= (s)->rlower) | ||||
|  | ||||
| /* These are inclusive... */ | ||||
| #define screen_left_x(s, x) ((x) + 1) | ||||
| #define screen_right_x(s, x) \ | ||||
| 	((x) < screen_size_x(s) ? screen_size_x(s) - (x) : 0) | ||||
|  | ||||
| #define screen_above_y(s, y) ((y) + 1) | ||||
| #define screen_below_y(s, y) \ | ||||
| 	((y) < screen_size_y(s) ? screen_size_y(s) - (y) : 0) | ||||
|  | ||||
| /* Screen default contents. */ | ||||
| #define SCREEN_DEFDATA ' ' | ||||
| #define SCREEN_DEFATTR 0 | ||||
| @@ -437,6 +442,7 @@ struct input_arg { | ||||
| /* Input parser context. */ | ||||
| struct input_ctx { | ||||
| 	struct window	*w; | ||||
| 	struct screen_write_ctx ctx; | ||||
|  | ||||
| 	u_char		*buf; | ||||
| 	size_t		 len; | ||||
| @@ -462,9 +468,8 @@ struct input_ctx { | ||||
|  */ | ||||
| struct window_mode { | ||||
| 	void	(*init)(struct window *); | ||||
| 	void	(*free)(struct window *); | ||||
| 	void	(*resize)(struct window *, u_int, u_int); | ||||
| 	void	(*draw)( | ||||
| 	    	    struct window *, struct screen_draw_ctx *, u_int, u_int); | ||||
| 	void	(*key)(struct window *, int); | ||||
| }; | ||||
|  | ||||
| @@ -480,8 +485,10 @@ struct window { | ||||
|  | ||||
| 	int		 flags; | ||||
| #define WINDOW_BELL 0x1 | ||||
| #define WINDOW_HIDDEN 0x2 | ||||
|  | ||||
| 	struct screen	 screen; | ||||
| 	struct screen	*screen; | ||||
| 	struct screen	 base; | ||||
|  | ||||
| 	const struct window_mode *mode; | ||||
| 	void		*modedata; | ||||
| @@ -661,7 +668,7 @@ void		 tty_init(struct tty *, char *, char *); | ||||
| int		 tty_open(struct tty *, char **); | ||||
| void		 tty_close(struct tty *); | ||||
| void		 tty_free(struct tty *); | ||||
| void		 tty_vwrite(struct tty *, int, va_list); | ||||
| void		 tty_vwrite(struct tty *, struct screen *s, int, va_list); | ||||
|  | ||||
| /* tty-keys.c */ | ||||
| int		 tty_keys_cmp(struct tty_key *, struct tty_key *); | ||||
| @@ -787,27 +794,13 @@ void	 input_parse(struct window *); | ||||
| void	 input_key(struct window *, int); | ||||
|  | ||||
| /* screen-display.c */ | ||||
| void	 screen_display_set_cell( | ||||
|     	     struct screen *, u_int, u_int, u_char, u_char, u_char); | ||||
| void	 screen_display_make_lines(struct screen *, u_int, u_int); | ||||
| void	 screen_display_free_lines(struct screen *, u_int, u_int); | ||||
| void	 screen_display_move_lines(struct screen *, u_int, u_int, u_int); | ||||
| void	 screen_display_fill_lines( | ||||
| 	     struct screen *, u_int, u_int, u_char, u_char, u_char); | ||||
| void	 screen_display_fill_cells( | ||||
|     	     struct screen *, u_int, u_int, u_int, u_char, u_char, u_char); | ||||
| void	 screen_display_fill_screen(struct screen *, u_char, u_char, u_char); | ||||
| void	 screen_display_fill_cursor_eos( | ||||
| 	     struct screen *, u_char, u_char, u_char); | ||||
| void	 screen_display_fill_cursor_bos( | ||||
| 	     struct screen *, u_char, u_char, u_char); | ||||
| void	 screen_display_fill_line( | ||||
| 	     struct screen *, u_int, u_char, u_char, u_char); | ||||
| void	 screen_display_fill_cursor_bol( | ||||
| 	     struct screen *, u_char, u_char, u_char); | ||||
| void	 screen_display_fill_cursor_eol( | ||||
|     	     struct screen *, u_char, u_char, u_char); | ||||
| void	 screen_display_cursor_set(struct screen *, u_char); | ||||
| void	 screen_display_cursor_up(struct screen *); | ||||
| void	 screen_display_cursor_down(struct screen *); | ||||
| void	 screen_display_fill_area(struct screen *, | ||||
|     	     u_int, u_int, u_int, u_int, u_char, u_char, u_char); | ||||
| void	 screen_display_scroll_region_up(struct screen *); | ||||
| void	 screen_display_scroll_region_down(struct screen *); | ||||
| void	 screen_display_insert_lines(struct screen *, u_int, u_int); | ||||
| @@ -816,6 +809,64 @@ void	 screen_display_delete_lines(struct screen *, u_int, u_int); | ||||
| void	 screen_display_delete_lines_region(struct screen *, u_int, u_int); | ||||
| void	 screen_display_insert_characters(struct screen *, u_int, u_int, u_int); | ||||
| void	 screen_display_delete_characters(struct screen *, u_int, u_int, u_int); | ||||
| void	 screen_display_copy_area(struct screen *, struct screen *, | ||||
|     	     u_int, u_int, u_int, u_int, u_int, u_int); | ||||
|  | ||||
| /* screen-write.c */ | ||||
| void	 screen_write_start_window(struct screen_write_ctx *, struct window *); | ||||
| void	 screen_write_start_client(struct screen_write_ctx *, struct client *); | ||||
| void	 screen_write_start_session( | ||||
|     	    struct screen_write_ctx *, struct session *); | ||||
| void	 screen_write_start(struct screen_write_ctx *, | ||||
|     	    struct screen *, void (*)(void *, int, ...), void *); | ||||
| void	 screen_write_stop(struct screen_write_ctx *); | ||||
| void	 screen_write_set_title(struct screen_write_ctx *, char *); | ||||
| void	 screen_write_put_character(struct screen_write_ctx *, u_char); | ||||
| size_t printflike2 screen_write_put_string_rjust( | ||||
| 	     struct screen_write_ctx *, const char *, ...); | ||||
| void printflike2 screen_write_put_string( | ||||
| 	     struct screen_write_ctx *, const char *, ...); | ||||
| void	 screen_write_set_attributes(struct screen_write_ctx *, u_char, u_char); | ||||
| void	 screen_write_set_region(struct screen_write_ctx *, u_int, u_int); | ||||
| void	 screen_write_cursor_up_scroll(struct screen_write_ctx *); | ||||
| void	 screen_write_cursor_down_scroll(struct screen_write_ctx *); | ||||
| void	 screen_write_cursor_up(struct screen_write_ctx *, u_int); | ||||
| void	 screen_write_cursor_down(struct screen_write_ctx *, u_int); | ||||
| void	 screen_write_cursor_left(struct screen_write_ctx *, u_int); | ||||
| void	 screen_write_cursor_right(struct screen_write_ctx *, u_int); | ||||
| void	 screen_write_delete_lines(struct screen_write_ctx *, u_int); | ||||
| void	 screen_write_delete_characters(struct screen_write_ctx *, u_int); | ||||
| void	 screen_write_insert_lines(struct screen_write_ctx *, u_int); | ||||
| void	 screen_write_insert_characters(struct screen_write_ctx *, u_int); | ||||
| void	 screen_write_move_cursor(struct screen_write_ctx *, u_int, u_int); | ||||
| void	 screen_write_fill_end_of_screen(struct screen_write_ctx *); | ||||
| void	 screen_write_fill_screen(struct screen_write_ctx *); | ||||
| void	 screen_write_fill_end_of_line(struct screen_write_ctx *); | ||||
| void	 screen_write_fill_start_of_line(struct screen_write_ctx *); | ||||
| void	 screen_write_fill_line(struct screen_write_ctx *); | ||||
| void	 screen_write_set_mode(struct screen_write_ctx *, int); | ||||
| void	 screen_write_clear_mode(struct screen_write_ctx *, int); | ||||
| void	 screen_write_copy_area(struct screen_write_ctx *, | ||||
|     	     struct screen *, u_int, u_int, u_int, u_int); | ||||
|  | ||||
| /* screen-redraw.c */ | ||||
| void	screen_redraw_start_window(struct screen_redraw_ctx *, struct window *); | ||||
| void	screen_redraw_start_client(struct screen_redraw_ctx *, struct client *); | ||||
| void	screen_redraw_start_session( | ||||
|     	    struct screen_redraw_ctx *, struct session *); | ||||
| void	screen_redraw_start(struct screen_redraw_ctx *, | ||||
|     	    struct screen *, void (*)(void *, int, ...), void *); | ||||
| void	screen_redraw_stop(struct screen_redraw_ctx *); | ||||
| void	screen_redraw_move_cursor(struct screen_redraw_ctx *, u_int, u_int); | ||||
| void	screen_redraw_set_attributes(struct screen_redraw_ctx *, u_int, u_int); | ||||
| void printflike2 screen_redraw_write_string( | ||||
|     	     struct screen_redraw_ctx *, const char *, ...); | ||||
| void	screen_redraw_clear_end_of_line(struct screen_redraw_ctx *); | ||||
| void	screen_redraw_clear_screen(struct screen_redraw_ctx *); | ||||
| void	screen_redraw_cell(struct screen_redraw_ctx *, u_int, u_int); | ||||
| void	screen_redraw_area( | ||||
|     	    struct screen_redraw_ctx *, u_int, u_int, u_int, u_int); | ||||
| void	screen_redraw_lines(struct screen_redraw_ctx *, u_int, u_int); | ||||
|  | ||||
| /* screen.c */ | ||||
| const char *screen_colourstring(u_char); | ||||
| @@ -828,44 +879,14 @@ void	 screen_reduce_line(struct screen *, u_int, u_int); | ||||
| void	 screen_get_cell( | ||||
|     	     struct screen *, u_int, u_int, u_char *, u_char *, u_char *); | ||||
| void	 screen_set_cell(struct screen *, u_int, u_int, u_char, u_char, u_char); | ||||
| void	 screen_draw_start_window( | ||||
|     	     struct screen_draw_ctx *, struct window *, u_int, u_int); | ||||
| void	 screen_draw_start_client( | ||||
|     	     struct screen_draw_ctx *, struct client *, u_int, u_int); | ||||
| void	 screen_draw_start_session( | ||||
|     	     struct screen_draw_ctx *, struct session *, u_int, u_int); | ||||
| void	 screen_draw_start(struct screen_draw_ctx *, struct screen *s, | ||||
| 	     void (*)(void *, int, ...), void *, u_int, u_int); | ||||
| void	 screen_draw_stop(struct screen_draw_ctx *); | ||||
| void	 screen_draw_set_offset(struct screen_draw_ctx *, u_int, u_int); | ||||
| void	 screen_draw_set_selection( | ||||
|     	     struct screen_draw_ctx *, int, u_int, u_int, u_int, u_int); | ||||
| int	 screen_draw_check_selection(struct screen_draw_ctx *, u_int, u_int); | ||||
| void	 screen_draw_get_cell(struct screen_draw_ctx *, | ||||
|     	     u_int, u_int, u_char *, u_char *, u_char *); | ||||
| void	 screen_draw_insert_characters(struct screen_draw_ctx *, u_int); | ||||
| void	 screen_draw_delete_characters(struct screen_draw_ctx *, u_int); | ||||
| void	 screen_draw_insert_lines(struct screen_draw_ctx *, u_int); | ||||
| void	 screen_draw_delete_lines(struct screen_draw_ctx *, u_int); | ||||
| void	 screen_draw_clear_line_to(struct screen_draw_ctx *, u_int); | ||||
| void	 screen_draw_clear_screen(struct screen_draw_ctx *); | ||||
| void printflike2 screen_draw_write_string( | ||||
| 	     struct screen_draw_ctx *, const char *, ...); | ||||
| void	 screen_draw_move_cursor(struct screen_draw_ctx *, u_int, u_int); | ||||
| void	 screen_draw_set_attributes(struct screen_draw_ctx *, u_char, u_char); | ||||
| void	 screen_draw_cell(struct screen_draw_ctx *, u_int, u_int); | ||||
| void	 screen_draw_cells(struct screen_draw_ctx *, u_int, u_int, u_int); | ||||
| void	 screen_draw_column(struct screen_draw_ctx *, u_int); | ||||
| void	 screen_draw_line(struct screen_draw_ctx *, u_int); | ||||
| void	 screen_draw_lines(struct screen_draw_ctx *, u_int, u_int); | ||||
| void	 screen_draw_screen(struct screen_draw_ctx *); | ||||
| void	 screen_make_lines(struct screen *, u_int, u_int); | ||||
| void	 screen_free_lines(struct screen *, u_int, u_int); | ||||
| void	 screen_move_lines(struct screen *, u_int, u_int, u_int); | ||||
| void	 screen_fill_lines( | ||||
| 	     struct screen *, u_int, u_int, u_char, u_char, u_char); | ||||
| void	 screen_fill_cells( | ||||
|     	     struct screen *, u_int, u_int, u_int, u_char, u_char, u_char); | ||||
| void	 screen_fill_area(struct screen *, | ||||
|     	     u_int, u_int, u_int, u_int, u_char, u_char, u_char); | ||||
| void	 screen_set_selection(struct screen *, u_int, u_int, u_int, u_int); | ||||
| void	 screen_clear_selection(struct screen *); | ||||
| int	 screen_check_selection(struct screen *, u_int, u_int); | ||||
|  | ||||
| /* window.c */ | ||||
| extern struct windows windows; | ||||
| @@ -885,8 +906,6 @@ struct window	*window_create( | ||||
| void		 window_destroy(struct window *); | ||||
| int		 window_resize(struct window *, u_int, u_int); | ||||
| void		 window_parse(struct window *); | ||||
| void		 window_draw( | ||||
|     		     struct window *, struct screen_draw_ctx *, u_int, u_int); | ||||
| void		 window_key(struct window *, int); | ||||
|  | ||||
| /* window-copy.c */ | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| /* $Id: tty-keys.c,v 1.1 2007-11-27 19:23:34 nicm Exp $ */ | ||||
| /* $Id: tty-keys.c,v 1.2 2007-12-06 09:46:23 nicm Exp $ */ | ||||
|  | ||||
| /* | ||||
|  * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> | ||||
|   | ||||
							
								
								
									
										12
									
								
								tty-write.c
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								tty-write.c
									
									
									
									
									
								
							| @@ -1,4 +1,4 @@ | ||||
| /* $Id: tty-write.c,v 1.1 2007-11-27 19:23:34 nicm Exp $ */ | ||||
| /* $Id: tty-write.c,v 1.2 2007-12-06 09:46:23 nicm Exp $ */ | ||||
|  | ||||
| /* | ||||
|  * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> | ||||
| @@ -24,7 +24,6 @@ void | ||||
| tty_write_client(void *ptr, int cmd, ...) | ||||
| { | ||||
| 	struct client	*c = ptr; | ||||
|  | ||||
| 	va_list		 ap; | ||||
|  | ||||
| 	va_start(ap, cmd); | ||||
| @@ -36,8 +35,9 @@ void | ||||
| tty_vwrite_client(void *ptr, int cmd, va_list ap) | ||||
| { | ||||
| 	struct client	*c = ptr; | ||||
| 	struct screen	*s = c->session->curw->window->screen; | ||||
|  | ||||
| 	tty_vwrite(&c->tty, cmd, ap); | ||||
| 	tty_vwrite(&c->tty, s, cmd, ap); | ||||
| } | ||||
|  | ||||
| void | ||||
| @@ -58,7 +58,7 @@ tty_vwrite_window(void *ptr, int cmd, va_list ap) | ||||
| 	va_list		 aq; | ||||
| 	u_int		 i; | ||||
|  | ||||
| 	if (w->screen.mode & MODE_HIDDEN) | ||||
| 	if (w->flags & WINDOW_HIDDEN) | ||||
| 		return; | ||||
|  | ||||
| 	for (i = 0; i < ARRAY_LENGTH(&clients); i++) { | ||||
| @@ -69,7 +69,7 @@ tty_vwrite_window(void *ptr, int cmd, va_list ap) | ||||
| 			continue; | ||||
|  | ||||
| 		va_copy(aq, ap); | ||||
| 		tty_vwrite(&c->tty, cmd, aq); | ||||
| 		tty_vwrite_client(c, cmd, aq); | ||||
| 		va_end(aq); | ||||
| 	} | ||||
| } | ||||
| @@ -101,7 +101,7 @@ tty_vwrite_session(void *ptr, int cmd, va_list ap) | ||||
| 			continue; | ||||
|  | ||||
| 		va_copy(aq, ap); | ||||
| 		tty_vwrite(&c->tty, cmd, aq); | ||||
| 		tty_vwrite_client(c, cmd, aq); | ||||
| 		va_end(aq); | ||||
| 	} | ||||
| } | ||||
|   | ||||
							
								
								
									
										33
									
								
								tty.c
									
									
									
									
									
								
							
							
						
						
									
										33
									
								
								tty.c
									
									
									
									
									
								
							| @@ -1,4 +1,4 @@ | ||||
| /* $Id: tty.c,v 1.8 2007-12-03 10:47:27 nicm Exp $ */ | ||||
| /* $Id: tty.c,v 1.9 2007-12-06 09:46:23 nicm Exp $ */ | ||||
|  | ||||
| /* | ||||
|  * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> | ||||
| @@ -207,10 +207,10 @@ tty_putc(struct tty *tty, char ch) | ||||
| } | ||||
|  | ||||
| void | ||||
| tty_vwrite(struct tty *tty, int cmd, va_list ap) | ||||
| tty_vwrite(struct tty *tty, unused struct screen *s, int cmd, va_list ap) | ||||
| { | ||||
| 	char	ch; | ||||
| 	u_int	ua, ub; | ||||
| 	u_int	i, ua, ub; | ||||
|  | ||||
| 	set_curterm(tty->termp); | ||||
|  | ||||
| @@ -258,13 +258,36 @@ tty_vwrite(struct tty *tty, int cmd, va_list ap) | ||||
| 		tty_puts(tty, tparm(cursor_address, ua, ub)); | ||||
| 		break; | ||||
| 	case TTY_CLEARENDOFLINE: | ||||
| 		if (clr_eol != NULL) | ||||
| 			tty_puts(tty, clr_eol); | ||||
| 		else { | ||||
| 			tty_puts(tty, tparm(cursor_address, s->cy, s->cx)); | ||||
| 			for (i = s->cx; i < screen_size_x(s); i++) | ||||
| 				tty_putc(tty, ' '); | ||||
| 			tty_puts(tty, tparm(cursor_address, s->cy, s->cx)); | ||||
| 		} | ||||
| 		break; | ||||
| 	case TTY_CLEARSTARTOFLINE: | ||||
| 		if (clr_bol != NULL) | ||||
| 			tty_puts(tty, clr_bol); | ||||
| 		else { | ||||
| 			tty_puts(tty, tparm(cursor_address, s->cy, 0)); | ||||
| 			for (i = 0; i < s->cx + 1; i++) | ||||
| 				tty_putc(tty, ' '); | ||||
| 			tty_puts(tty, tparm(cursor_address, s->cy, s->cx)); | ||||
| 		} | ||||
| 		break; | ||||
| 	case TTY_CLEARLINE: | ||||
| 		tty_puts(tty, clr_eol);	/* XXX */ | ||||
| 		if (clr_eol != NULL) { | ||||
| 			tty_puts(tty, tparm(cursor_address, s->cy, 0)); | ||||
| 			tty_puts(tty, clr_eol); | ||||
| 			tty_puts(tty, tparm(cursor_address, s->cy, s->cx)); | ||||
| 		} else { | ||||
| 			tty_puts(tty, tparm(cursor_address, s->cy, 0)); | ||||
| 			for (i = 0; i < screen_size_x(s); i++) | ||||
| 				tty_putc(tty, ' '); | ||||
| 			tty_puts(tty, tparm(cursor_address, s->cy, s->cx)); | ||||
| 		} | ||||
| 		break; | ||||
| 	case TTY_INSERTLINE: | ||||
| 		ua = va_arg(ap, u_int); | ||||
| @@ -323,6 +346,7 @@ tty_vwrite(struct tty *tty, int cmd, va_list ap) | ||||
| 		ub = va_arg(ap, u_int); | ||||
| 		tty_puts(tty, tparm(change_scroll_region, ua, ub)); | ||||
| 		break; | ||||
| #if 0 | ||||
| 	case TTY_INSERTON: | ||||
| 		if (enter_insert_mode != NULL) | ||||
| 			tty_puts(tty, enter_insert_mode); | ||||
| @@ -331,7 +355,6 @@ tty_vwrite(struct tty *tty, int cmd, va_list ap) | ||||
| 		if (exit_insert_mode != NULL) | ||||
| 			tty_puts(tty, exit_insert_mode); | ||||
| 		break; | ||||
| #if 0 | ||||
| 	case TTY_KCURSOROFF: | ||||
| 		t = tigetstr("CE"); | ||||
| 		if (t != (char *) 0 && t != (char *) -1) | ||||
|   | ||||
							
								
								
									
										571
									
								
								window-copy.c
									
									
									
									
									
								
							
							
						
						
									
										571
									
								
								window-copy.c
									
									
									
									
									
								
							| @@ -1,4 +1,4 @@ | ||||
| /* $Id: window-copy.c,v 1.12 2007-11-27 19:43:50 nicm Exp $ */ | ||||
| /* $Id: window-copy.c,v 1.13 2007-12-06 09:46:23 nicm Exp $ */ | ||||
|  | ||||
| /* | ||||
|  * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> | ||||
| @@ -23,25 +23,34 @@ | ||||
| #include "tmux.h" | ||||
|  | ||||
| void	window_copy_init(struct window *); | ||||
| void	window_copy_free(struct window *); | ||||
| void	window_copy_resize(struct window *, u_int, u_int); | ||||
| void	window_copy_draw( | ||||
|     	    struct window *, struct screen_draw_ctx *, u_int, u_int); | ||||
| void	window_copy_key(struct window *, int); | ||||
|  | ||||
| void	window_copy_draw_position(struct window *, struct screen_draw_ctx *); | ||||
| void	window_copy_redraw_lines(struct window *, u_int, u_int); | ||||
| void	window_copy_redraw_screen(struct window *); | ||||
| void	window_copy_write_line( | ||||
|     	    struct window *, struct screen_write_ctx *, u_int); | ||||
| void	window_copy_write_lines( | ||||
|     	    struct window *, struct screen_write_ctx *, u_int, u_int); | ||||
| void	window_copy_write_column( | ||||
|     	    struct window *, struct screen_write_ctx *, u_int); | ||||
| void	window_copy_write_columns( | ||||
|     	    struct window *, struct screen_write_ctx *, u_int, u_int); | ||||
|  | ||||
| void	window_copy_update_cursor(struct window *); | ||||
| void	window_copy_start_selection(struct window *); | ||||
| int	window_copy_update_selection(struct window *); | ||||
| void	window_copy_copy_selection(struct window *); | ||||
| void	window_copy_copy_line( | ||||
| 	    struct window *, char **, size_t *, size_t *, u_int, u_int, u_int); | ||||
| u_int	window_copy_find_length(struct window *, u_int); | ||||
| void	window_copy_move_cursor(struct window *); | ||||
| void	window_copy_cursor_bol(struct window *); | ||||
| void	window_copy_cursor_eol(struct window *); | ||||
| void	window_copy_cursor_start_of_line(struct window *); | ||||
| void	window_copy_cursor_end_of_line(struct window *); | ||||
| void	window_copy_cursor_left(struct window *); | ||||
| void	window_copy_cursor_right(struct window *); | ||||
| void	window_copy_cursor_up(struct window *); | ||||
| void	window_copy_cursor_down(struct window *); | ||||
| void	window_copy_draw_lines(struct window *, u_int, u_int); | ||||
| void	window_copy_scroll_left(struct window *, u_int); | ||||
| void	window_copy_scroll_right(struct window *, u_int); | ||||
| void	window_copy_scroll_up(struct window *, u_int); | ||||
| @@ -49,106 +58,87 @@ void	window_copy_scroll_down(struct window *, u_int); | ||||
|  | ||||
| const struct window_mode window_copy_mode = { | ||||
| 	window_copy_init, | ||||
| 	window_copy_free, | ||||
| 	window_copy_resize, | ||||
| 	window_copy_draw, | ||||
| 	window_copy_key | ||||
| }; | ||||
|  | ||||
| struct window_copy_mode_data { | ||||
| 	struct screen	screen; | ||||
|  | ||||
| 	u_int	ox; | ||||
| 	u_int	oy; | ||||
| 	u_int	cx; | ||||
| 	u_int	cy; | ||||
| 	u_int	size; | ||||
|  | ||||
| 	int	selflag; | ||||
| 	u_int	selx; | ||||
| 	u_int	sely; | ||||
| 	 | ||||
| 	u_int	cx; | ||||
| 	u_int	cy; | ||||
| }; | ||||
|  | ||||
| void | ||||
| window_copy_init(struct window *w) | ||||
| { | ||||
| 	struct window_copy_mode_data	*data; | ||||
| 	struct screen			*s; | ||||
| 	struct screen_write_ctx	 	 ctx; | ||||
| 	u_int				 i; | ||||
|  | ||||
| 	w->modedata = data = xmalloc(sizeof *data); | ||||
| 	data->ox = data->oy = 0; | ||||
| 	data->cx = w->screen.cx; | ||||
| 	data->cy = w->screen.cy; | ||||
| 	data->size = w->screen.hsize; | ||||
| 	data->selflag = 0; | ||||
| 	data->ox = 0; | ||||
| 	data->oy = 0; | ||||
| 	data->cx = w->base.cx; | ||||
| 	data->cy = w->base.cy; | ||||
|  | ||||
| 	w->screen.mode |= (MODE_BACKGROUND|MODE_BGCURSOR); | ||||
| 	s = &data->screen; | ||||
| 	screen_create(s, screen_size_x(&w->base), screen_size_y(&w->base)); | ||||
| 	s->cx = data->cx; | ||||
| 	s->cy = data->cy; | ||||
| 	w->screen = s; | ||||
|  | ||||
| 	screen_write_start(&ctx, s, NULL, NULL); | ||||
| 	for (i = 0; i < screen_size_y(s); i++) | ||||
| 		window_copy_write_line(w, &ctx, i); | ||||
| 	screen_write_move_cursor(&ctx, data->cx, data->cy); | ||||
| 	screen_write_stop(&ctx); | ||||
| } | ||||
|  | ||||
| void | ||||
| window_copy_resize(unused struct window *w, unused u_int sx, unused u_int sy) | ||||
| { | ||||
| } | ||||
|  | ||||
| void | ||||
| window_copy_draw_position(struct window *w, struct screen_draw_ctx *ctx) | ||||
| window_copy_free(struct window *w) | ||||
| { | ||||
| 	struct window_copy_mode_data	*data = w->modedata; | ||||
| 	char				*ptr, buf[32]; | ||||
| 	size_t	 			 len; | ||||
|  | ||||
| 	len = xsnprintf( | ||||
| 	    buf, sizeof buf, "[%u,%u/%u]", data->ox, data->oy, data->size); | ||||
| 	if (len <= screen_size_x(ctx->s)) | ||||
| 		ptr = buf; | ||||
| 	else { | ||||
| 		ptr = buf + len - screen_size_x(ctx->s); | ||||
| 		len -= len - screen_size_x(ctx->s); | ||||
| 	} | ||||
| 	w->screen = &w->base; | ||||
| 	screen_destroy(&data->screen); | ||||
|  | ||||
| 	screen_draw_cells(ctx, 0, 0, screen_size_x(ctx->s) - len); | ||||
| 	 | ||||
| 	screen_draw_move_cursor(ctx, screen_size_x(ctx->s) - len, 0); | ||||
| 	screen_draw_set_attributes(ctx, 0, status_colour); | ||||
| 	screen_draw_write_string(ctx, "%s", ptr); | ||||
| 	w->mode = NULL; | ||||
| 	xfree(w->modedata); | ||||
| } | ||||
|  | ||||
| void | ||||
| window_copy_draw( | ||||
|     struct window *w, struct screen_draw_ctx *ctx, u_int py, u_int ny) | ||||
| window_copy_resize(struct window *w, u_int sx, u_int sy) | ||||
| { | ||||
| 	struct window_copy_mode_data	*data = w->modedata; | ||||
| 	struct screen			*s = &w->screen; | ||||
| 	struct screen			*s = &data->screen; | ||||
|  | ||||
| 	if (s->hsize != data->size) { | ||||
| 		data->oy += s->hsize - data->size; | ||||
| 		data->size = s->hsize; | ||||
| 	} | ||||
| 	screen_draw_set_offset(ctx, data->ox, data->oy); | ||||
| 	screen_draw_set_selection(ctx, | ||||
| 	    data->selflag, data->selx, data->sely, | ||||
| 	    data->cx + data->ox, data->size + data->cy - data->oy); | ||||
|  | ||||
| 	if (py != 0) | ||||
| 		screen_draw_lines(ctx, py, ny); | ||||
| 	else { | ||||
| 		if (ny > 1) | ||||
| 			screen_draw_lines(ctx, py + 1, ny - 1); | ||||
| 		window_copy_draw_position(w, ctx); | ||||
| 	} | ||||
|  | ||||
| 	window_copy_move_cursor(w); | ||||
| 	screen_resize(s, sx, sy); | ||||
| 	screen_display_copy_area(&data->screen, &w->base, | ||||
| 	    0, 0, screen_size_x(s), screen_size_y(s), data->ox, data->oy); | ||||
| 	window_copy_update_selection(w); | ||||
| } | ||||
|  | ||||
| void | ||||
| window_copy_key(struct window *w, int key) | ||||
| { | ||||
| 	struct window_copy_mode_data	*data = w->modedata; | ||||
| 	u_int				 oy, sy; | ||||
| 	 | ||||
| 	sy = screen_size_y(&w->screen); | ||||
| 	oy = data->oy; | ||||
| 	struct screen			*s = &data->screen; | ||||
|  | ||||
| 	switch (key) { | ||||
| 	case 'Q': | ||||
| 	case 'q': | ||||
| 		goto done; | ||||
| 		window_copy_free(w); | ||||
| 		server_redraw_window(w); | ||||
| 		break; | ||||
| 	case 'h': | ||||
| 	case KEYC_LEFT: | ||||
| 		window_copy_cursor_left(w); | ||||
| @@ -169,55 +159,199 @@ window_copy_key(struct window *w, int key) | ||||
| 		return; | ||||
| 	case '\025':	/* C-u */ | ||||
| 	case KEYC_PPAGE: | ||||
| 		if (data->oy + sy > data->size) | ||||
| 			data->oy = data->size; | ||||
| 		if (data->oy + screen_size_y(s) > w->base.hsize) | ||||
| 			data->oy = w->base.hsize; | ||||
| 		else | ||||
| 			data->oy += sy; | ||||
| 			data->oy += screen_size_y(s); | ||||
| 		window_copy_update_selection(w); | ||||
| 		window_copy_redraw_screen(w); | ||||
| 		break; | ||||
| 	case '\006':	/* C-f */ | ||||
| 	case KEYC_NPAGE: | ||||
| 		if (data->oy < sy) | ||||
| 		if (data->oy < screen_size_y(s)) | ||||
| 			data->oy = 0; | ||||
| 		else | ||||
| 			data->oy -= sy; | ||||
| 			data->oy -= screen_size_y(s); | ||||
| 		window_copy_update_selection(w); | ||||
| 		window_copy_redraw_screen(w); | ||||
| 		break; | ||||
| 	case '\000':	/* C-space */ | ||||
| 	case ' ': | ||||
| 		data->selflag = !data->selflag; | ||||
| 		data->selx = data->cx + data->ox; | ||||
| 		data->sely = data->size + data->cy - data->oy; | ||||
| 		oy = -1;	/* XXX */ | ||||
| 		window_copy_start_selection(w); | ||||
| 		break; | ||||
| 	case '\033': | ||||
| 		data->selflag = 0; | ||||
| 		oy = -1;	/* XXX */ | ||||
| 		screen_clear_selection(&data->screen); | ||||
| 		break; | ||||
| 	case '\027':	/* C-w */ | ||||
| 	case '\r':	/* enter */ | ||||
| 		if (data->selflag) | ||||
| 		window_copy_copy_selection(w); | ||||
| 		goto done; | ||||
| 		window_copy_free(w); | ||||
| 		server_redraw_window(w); | ||||
| 		break; | ||||
| 	case '\001':	/* C-a */ | ||||
| 		window_copy_cursor_bol(w); | ||||
| 		return; | ||||
| 		window_copy_cursor_start_of_line(w); | ||||
| 		break; | ||||
| 	case '\005':	/* C-e */ | ||||
| 		window_copy_cursor_eol(w); | ||||
| 		return; | ||||
| 		window_copy_cursor_end_of_line(w); | ||||
| 		break; | ||||
| 	} | ||||
| 	if (data->oy != oy) { | ||||
| 		server_redraw_window(w); | ||||
| 		window_copy_move_cursor(w); | ||||
| } | ||||
|  | ||||
| void | ||||
| window_copy_write_line( | ||||
|     struct window *w, struct screen_write_ctx *ctx, u_int py) | ||||
| { | ||||
| 	struct window_copy_mode_data	*data = w->modedata; | ||||
| 	struct screen			*s = &data->screen; | ||||
| 	size_t	 			 size; | ||||
|  | ||||
| 	if (py == 0) { | ||||
| 		screen_write_set_attributes(ctx, 0, status_colour); | ||||
| 		screen_write_move_cursor(ctx, 0, 0); | ||||
| 		size = screen_write_put_string_rjust( | ||||
| 		    ctx, "[%u,%u/%u]", data->ox, data->oy, w->base.hsize); | ||||
| 		screen_write_set_attributes( | ||||
| 		    ctx, SCREEN_DEFATTR, SCREEN_DEFCOLR); | ||||
| 	} else | ||||
| 		size = 0; | ||||
| 	screen_write_move_cursor(ctx, 0, py); | ||||
| 	screen_write_copy_area( | ||||
| 	    ctx, &w->base, screen_size_x(s) - size, 1, data->ox, data->oy); | ||||
| } | ||||
|  | ||||
| void | ||||
| window_copy_write_lines( | ||||
|     struct window *w, struct screen_write_ctx *ctx, u_int py, u_int ny) | ||||
| { | ||||
| 	struct window_copy_mode_data	*data = w->modedata; | ||||
| 	struct screen			*s = &data->screen; | ||||
|  | ||||
| 	if (py == 0) { | ||||
| 		window_copy_write_line(w, ctx, 0); | ||||
| 		if (ny == 1) | ||||
| 			return; | ||||
| 		py++; | ||||
| 		ny--; | ||||
| 	} | ||||
| 	screen_write_move_cursor(ctx, 0, py); | ||||
| 	screen_write_copy_area( | ||||
| 	    ctx, &w->base, screen_size_x(s), ny, data->ox, data->oy); | ||||
| } | ||||
|  | ||||
| done: | ||||
| 	w->mode = NULL; | ||||
| 	xfree(w->modedata); | ||||
| void | ||||
| window_copy_write_column( | ||||
|     struct window *w, struct screen_write_ctx *ctx, u_int px) | ||||
| { | ||||
| 	struct window_copy_mode_data	*data = w->modedata; | ||||
| 	struct screen			*s = &data->screen; | ||||
|  | ||||
| 	w->screen.mode &= ~MODE_BACKGROUND; | ||||
| 	screen_write_move_cursor(ctx, px, 0); | ||||
| 	screen_write_copy_area( | ||||
| 	    ctx, &w->base, 1, screen_size_y(s), data->ox, data->oy); | ||||
| } | ||||
|  | ||||
| 	recalculate_sizes(); | ||||
| 	server_redraw_window(w); | ||||
| void | ||||
| window_copy_write_columns( | ||||
|     struct window *w, struct screen_write_ctx *ctx, u_int px, u_int nx) | ||||
| { | ||||
| 	struct window_copy_mode_data	*data = w->modedata; | ||||
| 	struct screen			*s = &data->screen; | ||||
|  | ||||
| 	screen_write_move_cursor(ctx, px, 0); | ||||
| 	screen_write_copy_area( | ||||
| 	    ctx, &w->base, nx, screen_size_y(s), data->ox, data->oy); | ||||
| } | ||||
|  | ||||
| void | ||||
| window_copy_redraw_lines(struct window *w, u_int py, u_int ny) | ||||
| { | ||||
| 	struct window_copy_mode_data	*data = w->modedata; | ||||
| 	struct screen_write_ctx	 	 ctx; | ||||
| 	u_int				 i; | ||||
|  | ||||
| 	screen_write_start_window(&ctx, w); | ||||
| 	for (i = py; i < py + ny; i++) | ||||
| 		window_copy_write_line(w, &ctx, i); | ||||
| 	screen_write_move_cursor(&ctx, data->cx, data->cy); | ||||
| 	screen_write_stop(&ctx); | ||||
| } | ||||
|  | ||||
| void | ||||
| window_copy_redraw_screen(struct window *w) | ||||
| { | ||||
| 	struct window_copy_mode_data	*data = w->modedata; | ||||
|  | ||||
| 	window_copy_redraw_lines(w, 0, screen_size_x(&data->screen)); | ||||
| } | ||||
|  | ||||
| void | ||||
| window_copy_update_cursor(struct window *w) | ||||
| { | ||||
| 	struct window_copy_mode_data	*data = w->modedata; | ||||
| 	struct screen_write_ctx		 ctx; | ||||
|  | ||||
| 	screen_write_start_window(&ctx, w); | ||||
| 	screen_write_move_cursor(&ctx, data->cx, data->cy); | ||||
| 	screen_write_stop(&ctx); | ||||
| } | ||||
|  | ||||
| void | ||||
| window_copy_start_selection(struct window *w) | ||||
| { | ||||
| 	struct window_copy_mode_data	*data = w->modedata; | ||||
| 	struct screen			*s = &data->screen; | ||||
|  | ||||
| 	data->selx = screen_x(&w->base, data->cx) + data->ox; | ||||
| 	data->sely = screen_y(&w->base, data->cy) - data->oy; | ||||
|  | ||||
| 	s->sel.flag = 1; | ||||
| 	window_copy_update_selection(w); | ||||
| } | ||||
|  | ||||
| int | ||||
| window_copy_update_selection(struct window *w) | ||||
| { | ||||
| 	struct window_copy_mode_data	*data = w->modedata; | ||||
| 	struct screen			*s = &data->screen; | ||||
| 	u_int				 sx, sy, tx, ty; | ||||
|  | ||||
| 	if (!s->sel.flag) | ||||
| 		return (0); | ||||
|  | ||||
| 	/* Find top-left of screen. */ | ||||
| 	tx = screen_x(&w->base, 0) + data->ox; | ||||
| 	ty = screen_y(&w->base, 0) - data->oy; | ||||
|  | ||||
| 	/* Adjust the selection. */ | ||||
| 	sx = data->selx; | ||||
| 	sy = data->sely; | ||||
| 	if (sy < ty) { | ||||
| 		/* Above it. */ | ||||
| 		sx = 0; | ||||
| 		sy = 0; | ||||
| 	} else if (sy > ty + screen_last_y(s)) { | ||||
| 		/* Below it. */ | ||||
| 		sx = screen_last_x(s); | ||||
| 		sy = screen_last_y(s); | ||||
| 	} else if (sx < tx) { | ||||
| 		/* To the left. */ | ||||
| 		sx = 0; | ||||
| 	} else if (sx > tx + screen_last_x(s)) { | ||||
| 		/* To the right. */ | ||||
| 		sx = 0; | ||||
| 		sy++; | ||||
| 		if (sy > screen_last_y(s)) | ||||
| 			sy = screen_last_y(s); | ||||
| 	} else { | ||||
| 		sx -= tx; | ||||
| 		sy -= ty; | ||||
| 	} | ||||
| 	sx = screen_x(s, sx); | ||||
| 	sy = screen_x(s, sy); | ||||
|  | ||||
| 	screen_set_selection( | ||||
| 	    s, sx, sy, screen_x(s, data->cx), screen_y(s, data->cy)); | ||||
| 	return (1); | ||||
| } | ||||
|  | ||||
| void | ||||
| @@ -234,9 +368,14 @@ window_copy_copy_selection(struct window *w) | ||||
|  | ||||
| 	*buf = '\0'; | ||||
|  | ||||
| 	/* | ||||
| 	 * The selection extends from selx,sely to (adjusted) cx,cy on | ||||
| 	 * the base screen. | ||||
| 	 */ | ||||
|  | ||||
| 	/* Find start and end. */ | ||||
| 	xx = data->cx + data->ox; | ||||
| 	yy = data->size + data->cy - data->oy; | ||||
| 	xx = screen_x(&w->base, data->cx) + data->ox; | ||||
| 	yy = screen_y(&w->base, data->cy) - data->oy; | ||||
| 	if (xx < data->selx || (yy == data->sely && xx < data->selx)) { | ||||
| 		sx = xx; sy = yy; | ||||
| 		ex = data->selx; ey = data->sely; | ||||
| @@ -281,7 +420,6 @@ void | ||||
| window_copy_copy_line(struct window *w, | ||||
|     char **buf, size_t *off, size_t *len, u_int sy, u_int sx, u_int ex) | ||||
| { | ||||
| 	struct screen	*s = &w->screen; | ||||
| 	u_char	i, xx; | ||||
|  | ||||
| 	if (sx > ex) | ||||
| @@ -296,7 +434,7 @@ window_copy_copy_line(struct window *w, | ||||
| 	if (sx < ex) { | ||||
| 		for (i = sx; i < ex; i++) { | ||||
| 			*buf = ensure_size(*buf, len, 1, *off + 1); | ||||
| 			(*buf)[*off] = s->grid_data[sy][i]; | ||||
| 			(*buf)[*off] = w->base.grid_data[sy][i]; | ||||
| 			(*off)++; | ||||
| 		} | ||||
| 	} | ||||
| @@ -309,25 +447,16 @@ window_copy_copy_line(struct window *w, | ||||
| u_int | ||||
| window_copy_find_length(struct window *w, u_int py) | ||||
| { | ||||
| 	struct screen	*s = &w->screen; | ||||
| 	u_int	px; | ||||
|  | ||||
| 	px = s->grid_size[py]; | ||||
| 	while (px > 0 && s->grid_data[py][px - 1] == SCREEN_DEFDATA) | ||||
| 	px = w->base.grid_size[py]; | ||||
| 	while (px > 0 && w->base.grid_data[py][px - 1] == SCREEN_DEFDATA) | ||||
| 		px--; | ||||
| 	return (px); | ||||
| } | ||||
|  | ||||
| void | ||||
| window_copy_move_cursor(struct window *w) | ||||
| { | ||||
| 	struct window_copy_mode_data	*data = w->modedata; | ||||
|  | ||||
| 	tty_write_window(w, TTY_CURSORMOVE, data->cy, data->cx); | ||||
| } | ||||
|  | ||||
| void | ||||
| window_copy_cursor_bol(struct window *w) | ||||
| window_copy_cursor_start_of_line(struct window *w) | ||||
| { | ||||
| 	struct window_copy_mode_data	*data = w->modedata; | ||||
|  | ||||
| @@ -335,49 +464,52 @@ window_copy_cursor_bol(struct window *w) | ||||
| 		window_copy_scroll_right(w, data->ox); | ||||
| 	data->cx = 0; | ||||
|  | ||||
| 	if (data->selflag) | ||||
| 		window_copy_draw_lines(w, data->cy, 1); | ||||
| 	window_copy_move_cursor(w); | ||||
| 	if (window_copy_update_selection(w)) | ||||
| 		window_copy_redraw_lines(w, data->cy, 1); | ||||
| 	else | ||||
| 		window_copy_update_cursor(w); | ||||
| } | ||||
|  | ||||
| void | ||||
| window_copy_cursor_eol(struct window *w) | ||||
| window_copy_cursor_end_of_line(struct window *w) | ||||
| { | ||||
| 	struct window_copy_mode_data	*data = w->modedata; | ||||
| 	struct screen			*s = &w->screen; | ||||
| 	u_int				 xx; | ||||
| 	struct screen			*s = &data->screen; | ||||
| 	u_int				 px, py; | ||||
|  | ||||
| 	xx = window_copy_find_length(w, data->size + data->cy - data->oy); | ||||
| 	py = screen_y(&w->base, data->cy) - data->oy; | ||||
| 	px = window_copy_find_length(w, py); | ||||
|  | ||||
| 	/* On screen. */ | ||||
| 	if (xx > data->ox && xx < data->ox + screen_last_x(s)) | ||||
| 		data->cx = xx - data->ox; | ||||
| 	if (px > data->ox && px < data->ox + screen_last_x(s)) | ||||
| 		data->cx = px - data->ox; | ||||
|  | ||||
| 	/* Off right of screen. */ | ||||
| 	if (xx > data->ox + screen_last_x(s)) { | ||||
| 	if (px > data->ox + screen_last_x(s)) { | ||||
| 		/* Move cursor to last and scroll screen. */ | ||||
| 		window_copy_scroll_left(w, | ||||
| 		    xx - data->ox - screen_last_x(s)); | ||||
| 		    px - data->ox - screen_last_x(s)); | ||||
| 		data->cx = screen_last_x(s); | ||||
| 	} | ||||
|  | ||||
| 	/* Off left of screen. */ | ||||
| 	if (xx <= data->ox) { | ||||
| 		if (xx < screen_last_x(s)) { | ||||
| 	if (px <= data->ox) { | ||||
| 		if (px < screen_last_x(s)) { | ||||
| 			/* Short enough to fit on screen. */ | ||||
| 			window_copy_scroll_right(w, data->ox); | ||||
| 			data->cx = xx; | ||||
| 			data->cx = px; | ||||
| 		} else { | ||||
| 			/* Too long to fit on screen. */ | ||||
| 			window_copy_scroll_right( | ||||
| 			    w, data->ox - (xx - screen_last_x(s))); | ||||
| 			    w, data->ox - (px - screen_last_x(s))); | ||||
| 			data->cx = screen_last_x(s); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if (data->selflag) | ||||
| 		window_copy_draw_lines(w, data->cy, 1); | ||||
| 	window_copy_move_cursor(w); | ||||
| 	if (window_copy_update_selection(w)) | ||||
| 		window_copy_redraw_lines(w, data->cy, 1); | ||||
| 	else | ||||
| 		window_copy_update_cursor(w); | ||||
| } | ||||
|  | ||||
| void | ||||
| @@ -385,79 +517,102 @@ window_copy_cursor_left(struct window *w) | ||||
| { | ||||
| 	struct window_copy_mode_data	*data = w->modedata; | ||||
|  | ||||
| 	if (data->cx == 0) | ||||
| 	if (data->cx == 0) { | ||||
| 		if (data->ox > 0) | ||||
| 			window_copy_scroll_right(w, 1); | ||||
| 		else { | ||||
| 		data->cx--; | ||||
| 		if (data->selflag) | ||||
| 			window_copy_draw_lines(w, data->cy, 1); | ||||
| 			window_copy_cursor_up(w); | ||||
| 			window_copy_cursor_end_of_line(w); | ||||
| 		} | ||||
| 	} else { | ||||
| 		data->cx--; | ||||
| 		if (window_copy_update_selection(w)) | ||||
| 			window_copy_redraw_lines(w, data->cy, 1); | ||||
| 		else | ||||
| 			window_copy_update_cursor(w); | ||||
| 	} | ||||
| 	window_copy_move_cursor(w); | ||||
| } | ||||
|  | ||||
| void | ||||
| window_copy_cursor_right(struct window *w) | ||||
| { | ||||
| 	struct window_copy_mode_data	*data = w->modedata; | ||||
| 	struct screen			*s = &w->screen; | ||||
| 	u_int				 px, py; | ||||
|  | ||||
| 	if (data->cx == screen_last_x(s)) | ||||
| 		window_copy_scroll_left(w, 1); | ||||
| 	else { | ||||
| 	py = screen_y(&w->base, data->cy) - data->oy; | ||||
| 	px = window_copy_find_length(w, py); | ||||
|  | ||||
| 	if (data->cx >= px) { | ||||
| 		window_copy_cursor_start_of_line(w); | ||||
| 		window_copy_cursor_down(w); | ||||
| 	} else { | ||||
| 		data->cx++; | ||||
| 		if (data->selflag) | ||||
| 			window_copy_draw_lines(w, data->cy, 1); | ||||
| 		if (window_copy_update_selection(w)) | ||||
| 			window_copy_redraw_lines(w, data->cy, 1); | ||||
| 		else | ||||
| 			window_copy_update_cursor(w); | ||||
| 	} | ||||
| 	window_copy_move_cursor(w); | ||||
| } | ||||
|  | ||||
| void | ||||
| window_copy_cursor_up(struct window *w) | ||||
| { | ||||
| 	struct window_copy_mode_data	*data = w->modedata; | ||||
| 	u_int				 ox, oy, px, py; | ||||
|  | ||||
| 	oy = screen_y(&w->base, data->cy) - data->oy; | ||||
| 	ox = window_copy_find_length(w, oy); | ||||
|  | ||||
| 	if (data->cy == 0) | ||||
| 		window_copy_scroll_down(w, 1); | ||||
| 	else { | ||||
| 		data->cy--; | ||||
| 		if (data->selflag)	 | ||||
| 			window_copy_draw_lines(w, data->cy, 2); | ||||
| 		if (window_copy_update_selection(w)) | ||||
| 			window_copy_redraw_lines(w, data->cy, 2); | ||||
| 		else | ||||
| 			window_copy_update_cursor(w); | ||||
| 	} | ||||
| 	window_copy_move_cursor(w); | ||||
|  | ||||
| 	py = screen_y(&w->base, data->cy) - data->oy; | ||||
| 	px = window_copy_find_length(w, py); | ||||
|  | ||||
| 	if (data->cx > px || data->cx == ox) | ||||
| 		window_copy_cursor_end_of_line(w); | ||||
| } | ||||
|  | ||||
| void | ||||
| window_copy_cursor_down(struct window *w) | ||||
| { | ||||
| 	struct window_copy_mode_data	*data = w->modedata; | ||||
| 	struct screen			*s = &w->screen; | ||||
| 	struct screen			*s = &data->screen; | ||||
| 	u_int				 ox, oy, px, py; | ||||
|  | ||||
| 	oy = screen_y(&w->base, data->cy) - data->oy; | ||||
| 	ox = window_copy_find_length(w, oy); | ||||
|  | ||||
| 	if (data->cy == screen_last_y(s)) | ||||
| 		window_copy_scroll_up(w, 1); | ||||
| 	else { | ||||
| 		data->cy++; | ||||
| 		if (data->selflag)	 | ||||
| 			window_copy_draw_lines(w, data->cy - 1, 2); | ||||
| 	} | ||||
| 	window_copy_move_cursor(w); | ||||
| 		if (window_copy_update_selection(w)) | ||||
| 			window_copy_redraw_lines(w, data->cy - 1, 2); | ||||
| 		else | ||||
| 			window_copy_update_cursor(w); | ||||
| 	} | ||||
|  | ||||
| void | ||||
| window_copy_draw_lines(struct window *w, u_int py, u_int ny) | ||||
| { | ||||
| 	struct window_copy_mode_data	*data = w->modedata; | ||||
| 	struct screen_draw_ctx		 ctx; | ||||
| 	py = screen_y(&w->base, data->cy) - data->oy; | ||||
| 	px = window_copy_find_length(w, py); | ||||
|  | ||||
| 	screen_draw_start_window(&ctx, w, data->ox, data->oy); | ||||
| 	window_copy_draw(w, &ctx, py, ny); | ||||
| 	screen_draw_stop(&ctx); | ||||
| 	if (data->cx > px || data->cx == ox) | ||||
| 		window_copy_cursor_end_of_line(w); | ||||
| } | ||||
|  | ||||
| void | ||||
| window_copy_scroll_left(struct window *w, u_int nx) | ||||
| { | ||||
| 	struct window_copy_mode_data	*data = w->modedata; | ||||
| 	struct screen_draw_ctx		 ctx; | ||||
| 	struct screen			*s = &data->screen; | ||||
| 	struct screen_write_ctx		 ctx; | ||||
| 	u_int				 i; | ||||
|  | ||||
| 	if (data->ox > SHRT_MAX - nx) | ||||
| @@ -465,26 +620,29 @@ window_copy_scroll_left(struct window *w, u_int nx) | ||||
| 	if (nx == 0) | ||||
| 		return; | ||||
| 	data->ox += nx; | ||||
| 	window_copy_update_selection(w); | ||||
|  | ||||
| 	screen_draw_start_window(&ctx, w, data->ox, data->oy); | ||||
| 	screen_draw_set_selection(&ctx, | ||||
| 	    data->selflag, data->selx, data->sely, | ||||
| 	    data->cx + data->ox, data->size + data->cy - data->oy); | ||||
| 	for (i = 1; i < screen_size_y(&w->screen); i++) { | ||||
| 		screen_draw_move_cursor(&ctx, 0, i); | ||||
|  		screen_draw_delete_characters(&ctx, nx); | ||||
| 	screen_write_start_window(&ctx, w); | ||||
| 	for (i = 1; i < screen_size_y(s); i++) { | ||||
| 		screen_write_move_cursor(&ctx, 0, i); | ||||
| 		screen_write_delete_characters(&ctx, nx); | ||||
| 	} | ||||
| 	for (i = 0; i < nx; i++) | ||||
| 		screen_draw_column(&ctx, screen_last_x(&w->screen) - i); | ||||
| 	window_copy_draw_position(w, &ctx); | ||||
| 	screen_draw_stop(&ctx); | ||||
| 	window_copy_write_columns(w, &ctx, screen_size_x(s) - nx, nx); | ||||
| 	window_copy_write_line(w, &ctx, 0); | ||||
| 	if (s->sel.flag) { | ||||
| 		window_copy_update_selection(w); | ||||
| 		window_copy_write_lines(w, &ctx, data->cy, 1); | ||||
| 	} | ||||
| 	screen_write_move_cursor(&ctx, data->cx, data->cy); | ||||
| 	screen_write_stop(&ctx); | ||||
| } | ||||
|  | ||||
| void | ||||
| window_copy_scroll_right(struct window *w, u_int nx) | ||||
| { | ||||
| 	struct window_copy_mode_data	*data = w->modedata; | ||||
| 	struct screen_draw_ctx		 ctx; | ||||
| 	struct screen			*s = &data->screen; | ||||
| 	struct screen_write_ctx		 ctx; | ||||
| 	u_int		 		 i; | ||||
|  | ||||
| 	if (data->ox < nx) | ||||
| @@ -492,72 +650,71 @@ window_copy_scroll_right(struct window *w, u_int nx) | ||||
| 	if (nx == 0) | ||||
| 		return; | ||||
| 	data->ox -= nx; | ||||
| 	window_copy_update_selection(w); | ||||
|  | ||||
| 	screen_draw_start_window(&ctx, w, data->ox, data->oy); | ||||
| 	screen_draw_set_selection(&ctx, | ||||
| 	    data->selflag, data->selx, data->sely, | ||||
| 	    data->cx + data->ox, data->size + data->cy - data->oy); | ||||
| 	for (i = 1; i < screen_size_y(&w->screen); i++) { | ||||
| 		screen_draw_move_cursor(&ctx, 0, i); | ||||
|  		screen_draw_insert_characters(&ctx, nx); | ||||
| 	screen_write_start_window(&ctx, w); | ||||
| 	for (i = 1; i < screen_size_y(s); i++) { | ||||
| 		screen_write_move_cursor(&ctx, 0, i); | ||||
| 		screen_write_insert_characters(&ctx, nx); | ||||
| 	} | ||||
| 	for (i = 0; i < nx; i++) | ||||
| 		screen_draw_column(&ctx, i); | ||||
| 	window_copy_draw_position(w, &ctx); | ||||
| 	screen_draw_stop(&ctx); | ||||
| 	window_copy_write_columns(w, &ctx, 0, nx); | ||||
| 	window_copy_write_line(w, &ctx, 0); | ||||
| 	if (s->sel.flag) | ||||
| 		window_copy_write_lines(w, &ctx, data->cy, 1); | ||||
| 	screen_write_move_cursor(&ctx, data->cx, data->cy); | ||||
| 	screen_write_stop(&ctx); | ||||
| } | ||||
|  | ||||
| void | ||||
| window_copy_scroll_up(struct window *w, u_int ny) | ||||
| { | ||||
| 	struct window_copy_mode_data	*data = w->modedata; | ||||
| 	struct screen_draw_ctx		 ctx; | ||||
| 	u_int		 		 i; | ||||
| 	struct screen			*s = &data->screen; | ||||
| 	struct screen_write_ctx		 ctx; | ||||
|  | ||||
| 	if (data->oy < ny) | ||||
| 		ny = data->oy; | ||||
| 	if (ny == 0) | ||||
| 		return; | ||||
| 	data->oy -= ny; | ||||
| 	window_copy_update_selection(w); | ||||
|  | ||||
| 	screen_draw_start_window(&ctx, w, data->ox, data->oy); | ||||
| 	screen_draw_set_selection(&ctx, | ||||
| 	    data->selflag, data->selx, data->sely, | ||||
| 	    data->cx + data->ox, data->size + data->cy - data->oy); | ||||
| 	screen_draw_move_cursor(&ctx, 0, 0); | ||||
| 	screen_draw_delete_lines(&ctx, ny); | ||||
| 	for (i = 0; i < ny; i++) | ||||
| 		screen_draw_line(&ctx, screen_last_y(&w->screen) - i); | ||||
| 	if (data->selflag) | ||||
| 		screen_draw_line(&ctx, screen_last_y(&w->screen) - ny); | ||||
| 	window_copy_draw_position(w, &ctx); | ||||
| 	screen_draw_stop(&ctx); | ||||
| 	screen_write_start_window(&ctx, w); | ||||
| 	screen_write_move_cursor(&ctx, 0, 0); | ||||
| 	screen_write_delete_lines(&ctx, ny); | ||||
| 	window_copy_write_lines(w, &ctx, screen_size_y(s) - ny, ny); | ||||
| 	window_copy_write_line(w, &ctx, 0); | ||||
| 	if (s->sel.flag && screen_size_y(s) > ny) | ||||
| 		window_copy_write_lines(w, &ctx, screen_size_y(s) - ny - 1, 1); | ||||
| 	screen_write_move_cursor(&ctx, data->cx, data->cy); | ||||
| 	screen_write_stop(&ctx); | ||||
| } | ||||
|  | ||||
| void | ||||
| window_copy_scroll_down(struct window *w, u_int ny) | ||||
| { | ||||
| 	struct window_copy_mode_data	*data = w->modedata; | ||||
| 	struct screen_draw_ctx		 ctx; | ||||
| 	u_int		 		 i; | ||||
| 	struct screen			*s = &data->screen; | ||||
| 	struct screen_write_ctx		 ctx; | ||||
|  | ||||
| 	if (ny > data->size) | ||||
| 	if (ny > w->base.hsize) | ||||
| 		return; | ||||
|  | ||||
| 	if (data->oy > data->size - ny) | ||||
| 		ny = data->size - data->oy; | ||||
| 	if (data->oy > w->base.hsize - ny) | ||||
| 		ny = w->base.hsize - data->oy; | ||||
| 	if (ny == 0) | ||||
| 		return; | ||||
| 	data->oy += ny; | ||||
| 	window_copy_update_selection(w); | ||||
|  | ||||
| 	screen_draw_start_window(&ctx, w, data->ox, data->oy); | ||||
| 	screen_draw_set_selection(&ctx, | ||||
| 	    data->selflag, data->selx, data->sely, | ||||
| 	    data->cx + data->ox, data->size + data->cy - data->oy); | ||||
| 	screen_draw_move_cursor(&ctx, 0, 0); | ||||
| 	screen_draw_insert_lines(&ctx, ny); | ||||
| 	for (i = 1; i < ny + 1; i++) | ||||
| 		screen_draw_line(&ctx, i); | ||||
| 	window_copy_draw_position(w, &ctx); | ||||
| 	screen_draw_stop(&ctx); | ||||
| 	screen_write_start_window(&ctx, w); | ||||
| 	screen_write_move_cursor(&ctx, 0, 0); | ||||
| 	screen_write_insert_lines(&ctx, ny); | ||||
| 	window_copy_write_lines(w, &ctx, 0, ny); | ||||
| 	if (s->sel.flag && screen_size_y(s) > ny) | ||||
| 		window_copy_write_lines(w, &ctx, ny, 1); | ||||
| 	else if (ny == 1) /* nuke position */ | ||||
| 		window_copy_write_line(w, &ctx, 1); | ||||
| 	screen_write_move_cursor(&ctx, data->cx, data->cy); | ||||
| 	screen_write_stop(&ctx); | ||||
| } | ||||
|   | ||||
							
								
								
									
										283
									
								
								window-more.c
									
									
									
									
									
								
							
							
						
						
									
										283
									
								
								window-more.c
									
									
									
									
									
								
							| @@ -1,4 +1,4 @@ | ||||
| /* $Id: window-more.c,v 1.5 2007-11-27 19:23:34 nicm Exp $ */ | ||||
| /* $Id: window-more.c,v 1.6 2007-12-06 09:46:23 nicm Exp $ */ | ||||
|  | ||||
| /* | ||||
|  * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> | ||||
| @@ -23,25 +23,27 @@ | ||||
| #include "tmux.h" | ||||
|  | ||||
| void	window_more_init(struct window *); | ||||
| void	window_more_free(struct window *); | ||||
| void	window_more_resize(struct window *, u_int, u_int); | ||||
| void	window_more_draw( | ||||
|     	    struct window *, struct screen_draw_ctx *, u_int, u_int); | ||||
| void	window_more_key(struct window *, int); | ||||
|  | ||||
| void	window_more_draw_position(struct window *, struct screen_draw_ctx *); | ||||
| void	window_more_draw_line(struct window *, struct screen_draw_ctx *, u_int); | ||||
| void	window_more_redraw_screen(struct window *); | ||||
| void	window_more_write_line( | ||||
|     	    struct window *, struct screen_write_ctx *, u_int); | ||||
|  | ||||
| void	window_more_up_1(struct window *); | ||||
| void	window_more_down_1(struct window *); | ||||
| void	window_more_scroll_up(struct window *); | ||||
| void	window_more_scroll_down(struct window *); | ||||
|  | ||||
| const struct window_mode window_more_mode = { | ||||
| 	window_more_init, | ||||
| 	window_more_free, | ||||
| 	window_more_resize, | ||||
| 	window_more_draw, | ||||
| 	window_more_key | ||||
| }; | ||||
|  | ||||
| struct window_more_mode_data { | ||||
| 	struct screen	        screen; | ||||
|  | ||||
| 	ARRAY_DECL(, char *)	list; | ||||
| 	u_int			top; | ||||
| }; | ||||
| @@ -50,10 +52,25 @@ void | ||||
| window_more_vadd(struct window *w, const char *fmt, va_list ap) | ||||
| { | ||||
| 	struct window_more_mode_data	*data = w->modedata; | ||||
| 	char   				*s; | ||||
| 	struct screen			*s = &data->screen; | ||||
| 	struct screen_write_ctx	 	 ctx; | ||||
| 	char   				*msg; | ||||
| 	u_int				 size; | ||||
|  | ||||
| 	xvasprintf(&s, fmt, ap); | ||||
| 	ARRAY_ADD(&data->list, s); | ||||
| 	xvasprintf(&msg, fmt, ap); | ||||
| 	ARRAY_ADD(&data->list, msg); | ||||
|  | ||||
| 	size = ARRAY_LENGTH(&data->list); | ||||
| 	if (size == 0) | ||||
| 		return; | ||||
| 	size--; | ||||
| 	if (size >= data->top && size <= data->top + screen_last_y(s)) { | ||||
| 		screen_write_start_window(&ctx, w); | ||||
| 		window_more_write_line(w, &ctx, size - data->top); | ||||
| 		if (size != data->top) | ||||
| 			window_more_write_line(w, &ctx, 0); | ||||
| 		screen_write_stop(&ctx); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void | ||||
| @@ -70,170 +87,160 @@ void | ||||
| window_more_init(struct window *w) | ||||
| { | ||||
| 	struct window_more_mode_data	*data; | ||||
| 	struct screen			*s; | ||||
|  | ||||
| 	w->modedata = data = xmalloc(sizeof *data); | ||||
| 	ARRAY_INIT(&data->list); | ||||
| 	data->top = 0; | ||||
|  | ||||
| 	w->screen.mode |= MODE_BACKGROUND; | ||||
| 	w->screen.mode &= ~MODE_BGCURSOR; | ||||
| 	s = &data->screen; | ||||
| 	screen_create(s, screen_size_x(&w->base), screen_size_y(&w->base)); | ||||
| 	s->mode = 0; | ||||
| 	w->screen = s; | ||||
| } | ||||
|  | ||||
| void | ||||
| window_more_resize(unused struct window *w, unused u_int sx, unused u_int sy) | ||||
| { | ||||
| } | ||||
|  | ||||
| void | ||||
| window_more_draw_position(struct window *w, struct screen_draw_ctx *ctx) | ||||
| window_more_free(struct window *w) | ||||
| { | ||||
| 	struct window_more_mode_data	*data = w->modedata; | ||||
| 	char				*ptr, buf[32]; | ||||
| 	size_t	 			 len; | ||||
| 	char				*line; | ||||
|  | ||||
| 	len = xsnprintf( | ||||
| 	    buf, sizeof buf, "[%u/%u]", data->top, ARRAY_LENGTH(&data->list)); | ||||
| 	if (len <= screen_size_x(ctx->s)) | ||||
| 		ptr = buf; | ||||
| 	else { | ||||
| 		ptr = buf + len - screen_size_x(ctx->s); | ||||
| 		len -= len - screen_size_x(ctx->s); | ||||
| 	} | ||||
|  | ||||
| 	screen_draw_move_cursor(ctx, 0, 0); | ||||
|  | ||||
| 	if (data->top < ARRAY_LENGTH(&data->list)) { | ||||
| 		line = xstrdup(ARRAY_ITEM(&data->list, data->top)); | ||||
| 		if (strlen(line) > screen_size_x(ctx->s) - len) | ||||
| 			line[screen_size_x(ctx->s) - len] = '\0'; | ||||
| 		screen_draw_write_string(ctx, "%s", line); | ||||
| 		xfree(line); | ||||
| 	} | ||||
| 	screen_draw_clear_line_to(ctx, screen_size_x(ctx->s) - len - 1); | ||||
|  | ||||
| 	screen_draw_move_cursor(ctx, screen_size_x(ctx->s) - len, 0); | ||||
| 	screen_draw_set_attributes(ctx, 0, status_colour); | ||||
| 	screen_draw_write_string(ctx, "%s", ptr); | ||||
| } | ||||
|  | ||||
| void | ||||
| window_more_draw_line(struct window *w, struct screen_draw_ctx *ctx, u_int py) | ||||
| { | ||||
| 	struct window_more_mode_data	*data = w->modedata; | ||||
| 	u_int				 p; | ||||
|  | ||||
| 	screen_draw_move_cursor(ctx, 0, py); | ||||
| 	screen_draw_set_attributes(ctx, SCREEN_DEFATTR, SCREEN_DEFCOLR); | ||||
| 	 | ||||
| 	p = data->top + py; | ||||
| 	if (p < ARRAY_LENGTH(&data->list)) | ||||
| 		screen_draw_write_string(ctx, "%s", ARRAY_ITEM(&data->list, p)); | ||||
|  | ||||
| 	screen_draw_clear_line_to(ctx, screen_last_x(ctx->s)); | ||||
| } | ||||
|  | ||||
| void | ||||
| window_more_draw( | ||||
|     struct window *w, struct screen_draw_ctx *ctx, u_int py, u_int ny) | ||||
| { | ||||
| 	u_int				 i; | ||||
|  | ||||
| 	for (i = py; i < py + ny; i++) { | ||||
| 		if (i == 0) | ||||
| 			window_more_draw_position(w, ctx); | ||||
| 		else | ||||
| 			window_more_draw_line(w, ctx, i); | ||||
| 	} | ||||
| } | ||||
| 	w->screen = &w->base; | ||||
| 	screen_destroy(&data->screen); | ||||
|  | ||||
| void | ||||
| window_more_key(struct window *w, int key) | ||||
| { | ||||
| 	struct window_more_mode_data	*data = w->modedata; | ||||
| 	u_int				 top, sy, i; | ||||
| 	 | ||||
| 	sy = screen_size_y(&w->screen); | ||||
|  | ||||
| 	top = data->top; | ||||
|  | ||||
| 	switch (key) { | ||||
| 	case 'Q': | ||||
| 	case 'q': | ||||
| 	for (i = 0; i < ARRAY_LENGTH(&data->list); i++) | ||||
| 		xfree(ARRAY_ITEM(&data->list, i)); | ||||
| 	ARRAY_FREE(&data->list); | ||||
|  | ||||
| 	w->mode = NULL; | ||||
| 	xfree(w->modedata); | ||||
|  | ||||
| 		w->screen.mode &= ~MODE_BACKGROUND; | ||||
|  | ||||
| 		recalculate_sizes(); | ||||
| 		server_redraw_window(w); | ||||
| 		return; | ||||
| 	case 'k': | ||||
| 	case 'K': | ||||
| 	case KEYC_UP: | ||||
| 		window_more_up_1(w); | ||||
| 		return; | ||||
| 	case 'j': | ||||
| 	case 'J': | ||||
| 	case KEYC_DOWN: | ||||
| 		window_more_down_1(w); | ||||
| 		return; | ||||
| 	case '\025':	/* C-u */ | ||||
| 	case KEYC_PPAGE: | ||||
| 		if (data->top < sy) | ||||
| 			data->top = 0; | ||||
| 		else | ||||
| 			data->top -= sy; | ||||
| 		break; | ||||
| 	case '\006':	/* C-f */ | ||||
| 	case KEYC_NPAGE: | ||||
| 		if (data->top + sy > ARRAY_LENGTH(&data->list)) | ||||
| 			data->top = ARRAY_LENGTH(&data->list); | ||||
| 		else | ||||
| 			data->top += sy; | ||||
| 		break; | ||||
| 	} | ||||
| 	if (top != data->top) | ||||
| 		server_redraw_window(w); | ||||
| } | ||||
|  | ||||
| void | ||||
| window_more_up_1(struct window *w) | ||||
| window_more_resize(struct window *w, u_int sx, u_int sy) | ||||
| { | ||||
| 	struct window_more_mode_data	*data = w->modedata; | ||||
| 	struct screen_draw_ctx		 ctx; | ||||
| 	struct screen			*s = &data->screen; | ||||
|  | ||||
| 	screen_resize(s, sx, sy); | ||||
| 	window_more_redraw_screen(w); | ||||
| } | ||||
|  | ||||
| void | ||||
| window_more_key(struct window *w, int key) | ||||
| { | ||||
| 	struct window_more_mode_data	*data = w->modedata; | ||||
| 	struct screen			*s = &data->screen; | ||||
|  | ||||
| 	switch (key) { | ||||
| 	case 'Q': | ||||
| 	case 'q': | ||||
| 		window_more_free(w); | ||||
| 		server_redraw_window(w); | ||||
| 		break; | ||||
| 	case 'k': | ||||
| 	case 'K': | ||||
| 	case KEYC_UP: | ||||
| 		window_more_scroll_up(w); | ||||
| 		break; | ||||
| 	case 'j': | ||||
| 	case 'J': | ||||
| 	case KEYC_DOWN: | ||||
| 		window_more_scroll_down(w); | ||||
| 		break; | ||||
| 	case '\025':	/* C-u */ | ||||
| 	case KEYC_PPAGE: | ||||
| 		if (data->top < screen_size_y(s)) | ||||
| 			data->top = 0; | ||||
| 		else | ||||
| 			data->top -= screen_size_y(s); | ||||
| 		window_more_redraw_screen(w); | ||||
| 		break; | ||||
| 	case '\006':	/* C-f */ | ||||
| 	case KEYC_NPAGE: | ||||
| 		if (data->top + screen_size_y(s) > ARRAY_LENGTH(&data->list)) | ||||
| 			data->top = ARRAY_LENGTH(&data->list); | ||||
| 		else | ||||
| 			data->top += screen_size_y(s); | ||||
| 		window_more_redraw_screen(w); | ||||
| 		break; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void | ||||
| window_more_write_line(struct window *w, struct screen_write_ctx *ctx, u_int py) | ||||
| { | ||||
| 	struct window_more_mode_data	*data = w->modedata; | ||||
| 	struct screen			*s = &data->screen; | ||||
| 	char   				*msg; | ||||
| 	size_t	 			 size; | ||||
|  | ||||
| 	if (py == 0) { | ||||
| 		screen_write_set_attributes(ctx, 0, status_colour); | ||||
| 		screen_write_move_cursor(ctx, 0, 0); | ||||
| 		size = screen_write_put_string_rjust( | ||||
| 		    ctx, "[%u/%u]", data->top, ARRAY_LENGTH(&data->list)); | ||||
| 	} else | ||||
| 		size = 0; | ||||
|  | ||||
| 	screen_write_set_attributes(ctx, SCREEN_DEFATTR, SCREEN_DEFCOLR); | ||||
| 	screen_write_move_cursor(ctx, 0, py); | ||||
| 	if (data->top + py  < ARRAY_LENGTH(&data->list)) { | ||||
| 		msg = ARRAY_ITEM(&data->list, data->top + py); | ||||
| 		screen_write_put_string( | ||||
| 		    ctx, "%.*s", (int) (screen_size_x(s) - size), msg); | ||||
| 	} | ||||
| 	while (s->cx < screen_size_x(s) - size) | ||||
| 		screen_write_put_character(ctx, SCREEN_DEFDATA); | ||||
| } | ||||
|  | ||||
| void | ||||
| window_more_redraw_screen(struct window *w) | ||||
| { | ||||
| 	struct window_more_mode_data	*data = w->modedata; | ||||
| 	struct screen			*s = &data->screen; | ||||
| 	struct screen_write_ctx	 	 ctx; | ||||
| 	u_int				 i; | ||||
|  | ||||
| 	screen_write_start_window(&ctx, w); | ||||
| 	for (i = 0; i < screen_size_y(s); i++) | ||||
| 		window_more_write_line(w, &ctx, i); | ||||
| 	screen_write_stop(&ctx); | ||||
| } | ||||
|  | ||||
| void | ||||
| window_more_scroll_up(struct window *w) | ||||
| { | ||||
| 	struct window_more_mode_data	*data = w->modedata; | ||||
| 	struct screen_write_ctx		 ctx; | ||||
|  | ||||
| 	if (data->top == 0) | ||||
| 		return; | ||||
| 	data->top--; | ||||
|  | ||||
| 	screen_draw_start_window(&ctx, w, 0, 0); | ||||
| 	screen_draw_move_cursor(&ctx, 0, 0); | ||||
| 	screen_draw_insert_lines(&ctx, 1); | ||||
| 	window_more_draw_position(w, &ctx); | ||||
| 	window_more_draw_line(w, &ctx, 1); | ||||
| 	screen_draw_stop(&ctx); | ||||
| 	screen_write_start_window(&ctx, w); | ||||
| 	screen_write_move_cursor(&ctx, 0, 0); | ||||
| 	screen_write_insert_lines(&ctx, 1); | ||||
| 	window_more_write_line(w, &ctx, 0); | ||||
| 	window_more_write_line(w, &ctx, 1); | ||||
| 	screen_write_stop(&ctx); | ||||
| } | ||||
|  | ||||
| void | ||||
| window_more_down_1(struct window *w) | ||||
| window_more_scroll_down(struct window *w) | ||||
| { | ||||
| 	struct window_more_mode_data	*data = w->modedata; | ||||
| 	struct screen			*s = &w->screen; | ||||
| 	struct screen_draw_ctx		 ctx; | ||||
| 	struct screen			*s = &data->screen; | ||||
| 	struct screen_write_ctx		 ctx; | ||||
|  | ||||
| 	if (data->top >= ARRAY_LENGTH(&data->list)) | ||||
| 		return; | ||||
| 	data->top++; | ||||
|  | ||||
| 	screen_draw_start_window(&ctx, w, 0, 0); | ||||
| 	screen_draw_move_cursor(&ctx, 0, 0); | ||||
| 	screen_draw_delete_lines(&ctx, 1); | ||||
| 	window_more_draw_line(w, &ctx, screen_last_y(s)); | ||||
| 	window_more_draw_position(w, &ctx); | ||||
| 	screen_draw_stop(&ctx); | ||||
| 	screen_write_start_window(&ctx, w); | ||||
| 	screen_write_move_cursor(&ctx, 0, 0); | ||||
| 	screen_write_delete_lines(&ctx, 1); | ||||
| 	window_more_write_line(w, &ctx, screen_last_y(s)); | ||||
| 	window_more_write_line(w, &ctx, 0); | ||||
| 	screen_write_stop(&ctx); | ||||
| } | ||||
|   | ||||
							
								
								
									
										256
									
								
								window-scroll.c
									
									
									
									
									
								
							
							
						
						
									
										256
									
								
								window-scroll.c
									
									
									
									
									
								
							| @@ -1,4 +1,4 @@ | ||||
| /* $Id: window-scroll.c,v 1.14 2007-11-27 19:32:15 nicm Exp $ */ | ||||
| /* $Id: window-scroll.c,v 1.15 2007-12-06 09:46:23 nicm Exp $ */ | ||||
|  | ||||
| /* | ||||
|  * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> | ||||
| @@ -23,229 +23,253 @@ | ||||
| #include "tmux.h" | ||||
|  | ||||
| void	window_scroll_init(struct window *); | ||||
| void	window_scroll_free(struct window *); | ||||
| void	window_scroll_resize(struct window *, u_int, u_int); | ||||
| void	window_scroll_draw( | ||||
|     	    struct window *, struct screen_draw_ctx *, u_int, u_int); | ||||
| void	window_scroll_key(struct window *, int); | ||||
|  | ||||
| void	window_scroll_draw_position(struct window *, struct screen_draw_ctx *); | ||||
| void	window_scroll_redraw_screen(struct window *); | ||||
| void	window_scroll_write_line( | ||||
|     	    struct window *, struct screen_write_ctx *, u_int); | ||||
| void	window_scroll_write_column( | ||||
|     	    struct window *, struct screen_write_ctx *, u_int); | ||||
|  | ||||
| void	window_scroll_up_1(struct window *); | ||||
| void	window_scroll_down_1(struct window *); | ||||
| void	window_scroll_left_1(struct window *); | ||||
| void	window_scroll_right_1(struct window *); | ||||
| void	window_scroll_scroll_up(struct window *); | ||||
| void	window_scroll_scroll_down(struct window *); | ||||
| void	window_scroll_scroll_left(struct window *); | ||||
| void	window_scroll_scroll_right(struct window *); | ||||
|  | ||||
| const struct window_mode window_scroll_mode = { | ||||
| 	window_scroll_init, | ||||
| 	window_scroll_free, | ||||
| 	window_scroll_resize, | ||||
| 	window_scroll_draw, | ||||
| 	window_scroll_key | ||||
| }; | ||||
|  | ||||
| struct window_scroll_mode_data { | ||||
| 	struct screen	screen; | ||||
|  | ||||
| 	u_int		ox; | ||||
| 	u_int		oy; | ||||
| 	u_int	size; | ||||
| }; | ||||
|  | ||||
| void | ||||
| window_scroll_init(struct window *w) | ||||
| { | ||||
| 	struct window_scroll_mode_data	*data; | ||||
| 	struct screen			*s; | ||||
| 	struct screen_write_ctx	 	 ctx; | ||||
| 	u_int				 i; | ||||
|  | ||||
| 	w->modedata = data = xmalloc(sizeof *data); | ||||
| 	data->ox = data->oy = 0; | ||||
| 	data->size = w->screen.hsize; | ||||
| 	data->ox = 0; | ||||
| 	data->oy = 0; | ||||
|  | ||||
| 	w->screen.mode |= MODE_BACKGROUND; | ||||
| 	w->screen.mode &= ~MODE_BGCURSOR; | ||||
| 	s = &data->screen; | ||||
| 	screen_create(s, screen_size_x(&w->base), screen_size_y(&w->base)); | ||||
| 	s->mode = 0; | ||||
| 	w->screen = s; | ||||
|  | ||||
| 	screen_write_start(&ctx, s, NULL, NULL); | ||||
| 	for (i = 0; i < screen_size_y(s); i++) | ||||
| 		window_scroll_write_line(w, &ctx, i); | ||||
| 	screen_write_stop(&ctx); | ||||
| } | ||||
|  | ||||
| void | ||||
| window_scroll_resize(unused struct window *w, unused u_int sx, unused u_int sy) | ||||
| { | ||||
| } | ||||
|  | ||||
| void | ||||
| window_scroll_draw_position(struct window *w, struct screen_draw_ctx *ctx) | ||||
| window_scroll_free(struct window *w) | ||||
| { | ||||
| 	struct window_scroll_mode_data	*data = w->modedata; | ||||
| 	char				*ptr, buf[32]; | ||||
| 	size_t	 			 len; | ||||
|  | ||||
| 	len = xsnprintf( | ||||
| 	    buf, sizeof buf, "[%u,%u/%u]", data->ox, data->oy, data->size); | ||||
| 	if (len <= screen_size_x(ctx->s)) | ||||
| 		ptr = buf; | ||||
| 	else { | ||||
| 		ptr = buf + len - screen_size_x(ctx->s); | ||||
| 		len -= len - screen_size_x(ctx->s); | ||||
| 	} | ||||
| 	w->screen = &w->base; | ||||
| 	screen_destroy(&data->screen); | ||||
|  | ||||
| 	screen_draw_cells(ctx, 0, 0, screen_size_x(ctx->s) - len); | ||||
| 	 | ||||
| 	screen_draw_move_cursor(ctx, screen_size_x(ctx->s) - len, 0); | ||||
| 	screen_draw_set_attributes(ctx, 0, status_colour); | ||||
| 	screen_draw_write_string(ctx, "%s", ptr); | ||||
| 	w->mode = NULL; | ||||
| 	xfree(w->modedata); | ||||
| } | ||||
|  | ||||
| void | ||||
| window_scroll_draw( | ||||
|     struct window *w, struct screen_draw_ctx *ctx, u_int py, u_int ny) | ||||
| window_scroll_resize(struct window *w, u_int sx, u_int sy) | ||||
| { | ||||
| 	struct window_scroll_mode_data	*data = w->modedata; | ||||
| 	struct screen			*s = &w->screen; | ||||
| 	struct screen			*s = &data->screen; | ||||
|  | ||||
| 	if (s->hsize != data->size) { | ||||
| 		data->oy += s->hsize - data->size; | ||||
| 		data->size = s->hsize; | ||||
| 	} | ||||
| 	screen_draw_set_offset(ctx, data->ox, data->oy); | ||||
|  | ||||
| 	if (py != 0) | ||||
| 		screen_draw_lines(ctx, py, ny); | ||||
| 	else { | ||||
| 		if (ny > 1) | ||||
| 			screen_draw_lines(ctx, py + 1, ny - 1); | ||||
| 		window_scroll_draw_position(w, ctx); | ||||
| 	} | ||||
| 	screen_resize(s, sx, sy); | ||||
| 	screen_display_copy_area(&data->screen, &w->base, | ||||
| 	    0, 0, screen_size_x(s), screen_size_y(s), data->ox, data->oy); | ||||
| } | ||||
|  | ||||
| void | ||||
| window_scroll_key(struct window *w, int key) | ||||
| { | ||||
| 	struct window_scroll_mode_data	*data = w->modedata; | ||||
| 	u_int				 ox, oy, sx, sy; | ||||
| 	 | ||||
| 	sx = screen_size_x(&w->screen); | ||||
| 	sy = screen_size_y(&w->screen); | ||||
|  | ||||
| 	ox = data->ox; | ||||
| 	oy = data->oy; | ||||
| 	struct screen			*s = &data->screen; | ||||
|  | ||||
| 	switch (key) { | ||||
| 	case 'Q': | ||||
| 	case 'q': | ||||
| 		w->mode = NULL; | ||||
| 		xfree(w->modedata); | ||||
|  | ||||
| 		w->screen.mode &= ~MODE_BACKGROUND; | ||||
|  | ||||
| 		recalculate_sizes(); | ||||
| 		window_scroll_free(w); | ||||
| 		server_redraw_window(w); | ||||
| 		return; | ||||
| 		break; | ||||
| 	case 'h': | ||||
| 	case KEYC_LEFT: | ||||
| 		window_scroll_left_1(w); | ||||
| 		return; | ||||
| 		window_scroll_scroll_left(w); | ||||
| 		break; | ||||
| 	case 'l': | ||||
| 	case KEYC_RIGHT: | ||||
| 		window_scroll_right_1(w); | ||||
| 		return; | ||||
| 		window_scroll_scroll_right(w); | ||||
| 		break; | ||||
| 	case 'k': | ||||
| 	case 'K': | ||||
| 	case KEYC_UP: | ||||
| 		window_scroll_up_1(w); | ||||
| 		return; | ||||
| 		window_scroll_scroll_up(w); | ||||
| 		break; | ||||
| 	case 'j': | ||||
| 	case 'J': | ||||
| 	case KEYC_DOWN: | ||||
| 		window_scroll_down_1(w); | ||||
| 		return; | ||||
| 		window_scroll_scroll_down(w); | ||||
| 		break; | ||||
| 	case '\025':	/* C-u */ | ||||
| 	case KEYC_PPAGE: | ||||
| 		if (data->oy + sy > data->size) | ||||
| 			data->oy = data->size; | ||||
| 		if (data->oy + screen_size_y(s) > w->base.hsize) | ||||
| 			data->oy = w->base.hsize; | ||||
| 		else | ||||
| 			data->oy += sy; | ||||
| 			data->oy += screen_size_y(s); | ||||
| 		window_scroll_redraw_screen(w); | ||||
| 		break; | ||||
| 	case '\006':	/* C-f */ | ||||
| 	case KEYC_NPAGE: | ||||
| 		if (data->oy < sy) | ||||
| 		if (data->oy < screen_size_y(s)) | ||||
| 			data->oy = 0; | ||||
| 		else | ||||
| 			data->oy -= sy; | ||||
| 			data->oy -= screen_size_y(s); | ||||
| 		window_scroll_redraw_screen(w); | ||||
| 		break; | ||||
| 	} | ||||
| 	if (ox != data->ox || oy != data->oy) | ||||
| 		server_redraw_window(w); | ||||
| } | ||||
|  | ||||
| void | ||||
| window_scroll_up_1(struct window *w) | ||||
| window_scroll_write_line( | ||||
|     struct window *w, struct screen_write_ctx *ctx, u_int py) | ||||
| { | ||||
| 	struct window_scroll_mode_data	*data = w->modedata; | ||||
| 	struct screen_draw_ctx		 ctx; | ||||
| 	struct screen			*s = &data->screen; | ||||
| 	size_t	 			 size; | ||||
|  | ||||
| 	if (data->oy >= data->size) | ||||
| 	if (py == 0) { | ||||
| 		screen_write_set_attributes(ctx, 0, status_colour); | ||||
| 		screen_write_move_cursor(ctx, 0, 0); | ||||
| 		size = screen_write_put_string_rjust( | ||||
| 		    ctx, "[%u,%u/%u]", data->ox, data->oy, w->base.hsize); | ||||
| 	} else | ||||
| 		size = 0; | ||||
| 	screen_write_move_cursor(ctx, 0, py); | ||||
| 	screen_write_copy_area( | ||||
| 	    ctx, &w->base, screen_size_x(s) - size, 1, data->ox, data->oy); | ||||
| } | ||||
|  | ||||
| void | ||||
| window_scroll_write_column( | ||||
|     struct window *w, struct screen_write_ctx *ctx, u_int px) | ||||
| { | ||||
| 	struct window_scroll_mode_data	*data = w->modedata; | ||||
| 	struct screen			*s = &data->screen; | ||||
|  | ||||
| 	screen_write_move_cursor(ctx, px, 0); | ||||
| 	screen_write_copy_area( | ||||
| 	    ctx, &w->base, 1, screen_size_y(s), data->ox, data->oy); | ||||
| } | ||||
|  | ||||
| void | ||||
| window_scroll_redraw_screen(struct window *w) | ||||
| { | ||||
| 	struct window_scroll_mode_data	*data = w->modedata; | ||||
| 	struct screen			*s = &data->screen; | ||||
| 	struct screen_write_ctx	 	 ctx; | ||||
| 	u_int				 i; | ||||
|  | ||||
| 	screen_write_start_window(&ctx, w); | ||||
| 	for (i = 0; i < screen_size_y(s); i++) | ||||
| 		window_scroll_write_line(w, &ctx, i); | ||||
| 	screen_write_stop(&ctx); | ||||
| } | ||||
|  | ||||
| void | ||||
| window_scroll_scroll_up(struct window *w) | ||||
| { | ||||
| 	struct window_scroll_mode_data	*data = w->modedata; | ||||
| 	struct screen_write_ctx		 ctx; | ||||
|  | ||||
| 	if (data->oy >= w->base.hsize) | ||||
| 		return; | ||||
| 	data->oy++; | ||||
|  | ||||
| 	screen_draw_start_window(&ctx, w, data->ox, data->oy); | ||||
| 	screen_draw_move_cursor(&ctx, 0, 0); | ||||
| 	screen_draw_insert_lines(&ctx, 1); | ||||
| 	window_scroll_draw_position(w, &ctx); | ||||
| 	screen_draw_line(&ctx, 1); | ||||
| 	screen_draw_stop(&ctx); | ||||
| 	screen_write_start_window(&ctx, w); | ||||
| 	screen_write_move_cursor(&ctx, 0, 0); | ||||
| 	screen_write_insert_lines(&ctx, 1); | ||||
| 	window_scroll_write_line(w, &ctx, 0); | ||||
| 	window_scroll_write_line(w, &ctx, 1); | ||||
| 	screen_write_stop(&ctx); | ||||
| } | ||||
|  | ||||
| void | ||||
| window_scroll_down_1(struct window *w) | ||||
| window_scroll_scroll_down(struct window *w) | ||||
| { | ||||
| 	struct window_scroll_mode_data	*data = w->modedata; | ||||
| 	struct screen_draw_ctx		 ctx; | ||||
| 	struct screen			*s = &data->screen; | ||||
| 	struct screen_write_ctx		 ctx; | ||||
|  | ||||
| 	if (data->oy == 0) | ||||
| 		return; | ||||
| 	data->oy--; | ||||
|  | ||||
| 	screen_draw_start_window(&ctx, w, data->ox, data->oy); | ||||
| 	screen_draw_move_cursor(&ctx, 0, 0); | ||||
| 	screen_draw_delete_lines(&ctx, 1); | ||||
| 	screen_draw_line(&ctx, screen_last_y(&w->screen)); | ||||
| 	window_scroll_draw_position(w, &ctx); | ||||
| 	screen_draw_stop(&ctx); | ||||
| 	screen_write_start_window(&ctx, w); | ||||
| 	screen_write_move_cursor(&ctx, 0, 0); | ||||
| 	screen_write_delete_lines(&ctx, 1); | ||||
| 	window_scroll_write_line(w, &ctx, screen_last_y(s)); | ||||
| 	window_scroll_write_line(w, &ctx, 0); | ||||
| 	screen_write_stop(&ctx); | ||||
| } | ||||
|  | ||||
| void | ||||
| window_scroll_right_1(struct window *w) | ||||
| window_scroll_scroll_right(struct window *w) | ||||
| { | ||||
| 	struct window_scroll_mode_data	*data = w->modedata; | ||||
| 	struct screen_draw_ctx		 ctx; | ||||
| 	struct screen			*s = &data->screen; | ||||
| 	struct screen_write_ctx		 ctx; | ||||
| 	u_int		 		 i; | ||||
|  | ||||
| 	if (data->ox >= SHRT_MAX) | ||||
| 		return; | ||||
| 	data->ox++; | ||||
|  | ||||
| 	screen_draw_start_window(&ctx, w, data->ox, data->oy); | ||||
| 	for (i = 1; i < screen_size_y(&w->screen); i++) { | ||||
| 		screen_draw_move_cursor(&ctx, 0, i); | ||||
| 		screen_draw_delete_characters(&ctx, 1); | ||||
| 	screen_write_start_window(&ctx, w); | ||||
| 	for (i = 1; i < screen_size_y(s); i++) { | ||||
| 		screen_write_move_cursor(&ctx, 0, i); | ||||
| 		screen_write_delete_characters(&ctx, 1); | ||||
| 	} | ||||
| 	screen_draw_column(&ctx, screen_last_x(&w->screen)); | ||||
| 	window_scroll_draw_position(w, &ctx); | ||||
| 	screen_draw_stop(&ctx); | ||||
| 	window_scroll_write_column(w, &ctx, screen_last_x(s)); | ||||
| 	window_scroll_write_line(w, &ctx, 0); | ||||
| 	screen_write_stop(&ctx); | ||||
| } | ||||
|  | ||||
| void | ||||
| window_scroll_left_1(struct window *w) | ||||
| window_scroll_scroll_left(struct window *w) | ||||
| { | ||||
| 	struct window_scroll_mode_data	*data = w->modedata; | ||||
| 	struct screen_draw_ctx		 ctx; | ||||
| 	struct screen			*s = &data->screen; | ||||
| 	struct screen_write_ctx		 ctx; | ||||
| 	u_int		 		 i; | ||||
|  | ||||
| 	if (data->ox == 0) | ||||
| 		return; | ||||
| 	data->ox--; | ||||
|  | ||||
|  | ||||
| 	screen_draw_start_window(&ctx, w, data->ox, data->oy); | ||||
| 	for (i = 1; i < screen_size_y(&w->screen); i++) { | ||||
| 		screen_draw_move_cursor(&ctx, 0, i); | ||||
| 		screen_draw_insert_characters(&ctx, 1); | ||||
| 	screen_write_start_window(&ctx, w); | ||||
| 	for (i = 1; i < screen_size_y(s); i++) { | ||||
| 		screen_write_move_cursor(&ctx, 0, i); | ||||
| 		screen_write_insert_characters(&ctx, 1); | ||||
| 	} | ||||
| 	screen_draw_column(&ctx, 0); | ||||
| 	window_scroll_draw_position(w, &ctx); | ||||
| 	screen_draw_stop(&ctx); | ||||
| 	window_scroll_write_column(w, &ctx, 0); | ||||
| 	window_scroll_write_line(w, &ctx, 0); | ||||
| 	screen_write_stop(&ctx); | ||||
| } | ||||
|   | ||||
							
								
								
									
										22
									
								
								window.c
									
									
									
									
									
								
							
							
						
						
									
										22
									
								
								window.c
									
									
									
									
									
								
							| @@ -1,4 +1,4 @@ | ||||
| /* $Id: window.c,v 1.32 2007-11-27 19:23:34 nicm Exp $ */ | ||||
| /* $Id: window.c,v 1.33 2007-12-06 09:46:23 nicm Exp $ */ | ||||
|  | ||||
| /* | ||||
|  * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> | ||||
| @@ -196,7 +196,8 @@ window_create( | ||||
| 	w->in = buffer_create(BUFSIZ); | ||||
| 	w->out = buffer_create(BUFSIZ); | ||||
| 	w->mode = NULL; | ||||
| 	screen_create(&w->screen, sx, sy); | ||||
| 	screen_create(&w->base, sx, sy); | ||||
| 	w->screen = &w->base; | ||||
| 	input_init(w); | ||||
|  | ||||
| 	if (name == NULL) { | ||||
| @@ -243,7 +244,9 @@ window_destroy(struct window *w) | ||||
|  | ||||
| 	input_free(w); | ||||
|  | ||||
| 	screen_destroy(&w->screen); | ||||
| 	screen_destroy(&w->base); | ||||
| 	if (w->mode != NULL) | ||||
| 		w->mode->free(w); | ||||
|  | ||||
| 	buffer_destroy(w->in); | ||||
| 	buffer_destroy(w->out); | ||||
| @@ -257,16 +260,16 @@ window_resize(struct window *w, u_int sx, u_int sy) | ||||
| { | ||||
| 	struct winsize	ws; | ||||
|  | ||||
| 	if (sx == screen_size_x(&w->screen) && sy == screen_size_y(&w->screen)) | ||||
| 	if (sx == screen_size_x(&w->base) && sy == screen_size_y(&w->base)) | ||||
| 		return (-1); | ||||
|  | ||||
| 	memset(&ws, 0, sizeof ws); | ||||
| 	ws.ws_col = sx; | ||||
| 	ws.ws_row = sy; | ||||
|  | ||||
| 	screen_resize(&w->base, sx, sy); | ||||
| 	if (w->mode != NULL) | ||||
| 		w->mode->resize(w, sx, sy); | ||||
| 	screen_resize(&w->screen, sx, sy); | ||||
|  | ||||
| 	if (ioctl(w->fd, TIOCSWINSZ, &ws) == -1) | ||||
| 		fatal("ioctl failed"); | ||||
| @@ -279,15 +282,6 @@ window_parse(struct window *w) | ||||
| 	input_parse(w); | ||||
| } | ||||
|  | ||||
| void | ||||
| window_draw(struct window *w, struct screen_draw_ctx *ctx, u_int py, u_int ny) | ||||
| { | ||||
| 	if (w->mode != NULL) | ||||
| 		w->mode->draw(w, ctx, py, ny); | ||||
| 	else | ||||
| 		screen_draw_lines(ctx, py, ny); | ||||
| } | ||||
|  | ||||
| void | ||||
| window_key(struct window *w, int key) | ||||
| { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Nicholas Marriott
					Nicholas Marriott