diff --git a/CHANGES b/CHANGES index 932ec115..69ef8fb6 100644 --- a/CHANGES +++ b/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 $ diff --git a/GNUmakefile b/GNUmakefile index 3acfd1c7..7c3354f1 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -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 @@ -37,7 +37,7 @@ CFLAGS+= -Wmissing-prototypes -Wstrict-prototypes -Wmissing-declarations CFLAGS+= -Wwrite-strings -Wshadow -Wpointer-arith -Wcast-qual -Wsign-compare CFLAGS+= -Wundef -Wbad-function-cast -Winline -Wcast-align -LDFLAGS+= +LDFLAGS+= LIBS+= -lncurses PREFIX?= /usr/local diff --git a/Makefile b/Makefile index 13155c90..cf31418e 100644 --- a/Makefile +++ b/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 diff --git a/TODO b/TODO index 47c7f90c..a4c6c8f9 100644 --- a/TODO +++ b/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 diff --git a/buffer.c b/buffer.c index f5864892..7bf0e4b0 100644 --- a/buffer.c +++ b/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 @@ -215,7 +215,7 @@ uint16_t buffer_read16(struct buffer *b) { uint16_t n; - + n = BUFFER_OUT(b)[0] | (BUFFER_OUT(b)[1] << 8); buffer_remove(b, 2); return (n); diff --git a/client-msg.c b/client-msg.c index 878bbcd0..65287f50 100644 --- a/client-msg.c +++ b/client-msg.c @@ -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 @@ -34,7 +34,7 @@ int client_msg_fn_pause(struct hdr *, struct client_ctx *, char **); struct client_msg { enum hdrtype type; - + int (*fn)(struct hdr *, struct client_ctx *, char **); }; struct client_msg client_msg_table[] = { @@ -58,7 +58,7 @@ client_msg_dispatch(struct client_ctx *cctx, char **error) if (BUFFER_USED(cctx->srv_in) < (sizeof hdr) + hdr.size) return (1); buffer_remove(cctx->srv_in, sizeof hdr); - + for (i = 0; i < NCLIENTMSG; i++) { msg = client_msg_table + i; if (msg->type == hdr.type) { @@ -92,7 +92,7 @@ client_msg_fn_detach( client_write_server(cctx, MSG_EXITING, NULL, 0); cctx->flags |= CCTX_DETACH; - + return (0); } diff --git a/client.c b/client.c index 4caf30a4..20e5dc33 100644 --- a/client.c +++ b/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 @@ -134,7 +134,7 @@ client_main(struct client_ctx *cctx) pfd.events = POLLIN; if (BUFFER_USED(cctx->srv_out) > 0) pfd.events |= POLLOUT; - + if (poll(&pfd, 1, timeout) == -1) { if (errno == EAGAIN || errno == EINTR) continue; @@ -157,18 +157,18 @@ client_main(struct client_ctx *cctx) break; } } - + out: if (sigterm) { printf("[terminated]\n"); return (1); } - + if (cctx->flags & CCTX_EXIT) { printf("[exited]\n"); return (0); } - + if (cctx->flags & CCTX_DETACH) { printf("[detached]\n"); return (0); @@ -187,13 +187,13 @@ client_handle_winch(struct client_ctx *cctx) { struct msg_resize_data data; struct winsize ws; - + if (ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) == -1) fatal("ioctl failed"); data.sx = ws.ws_col; data.sy = ws.ws_row; client_write_server(cctx, MSG_RESIZE, &data, sizeof data); - + sigwinch = 0; } diff --git a/cmd-attach-session.c b/cmd-attach-session.c index 930b756b..1741b36e 100644 --- a/cmd-attach-session.c +++ b/cmd-attach-session.c @@ -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 @@ -40,7 +40,7 @@ const struct cmd_entry cmd_attach_session_entry = { "attach-session", "attach", "[-d]", CMD_CANTNEST|CMD_NOCLIENT, cmd_attach_session_parse, - cmd_attach_session_exec, + cmd_attach_session_exec, cmd_attach_session_send, cmd_attach_session_recv, cmd_attach_session_free @@ -63,7 +63,7 @@ cmd_attach_session_parse(void **ptr, int argc, char **argv, char **cause) default: goto usage; } - } + } argc -= optind; argv += optind; if (argc != 0) diff --git a/cmd-bind-key.c b/cmd-bind-key.c index 5f739aca..537a12f5 100644 --- a/cmd-bind-key.c +++ b/cmd-bind-key.c @@ -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 @@ -41,7 +41,7 @@ const struct cmd_entry cmd_bind_key_entry = { "bind-key", "bind", "key command [arguments]", CMD_NOCLIENT|CMD_NOSESSION, cmd_bind_key_parse, - cmd_bind_key_exec, + cmd_bind_key_exec, cmd_bind_key_send, cmd_bind_key_recv, cmd_bind_key_free @@ -61,7 +61,7 @@ cmd_bind_key_parse(void **ptr, int argc, char **argv, char **cause) default: goto usage; } - } + } argc -= optind; argv += optind; if (argc < 1) diff --git a/cmd-copy-mode.c b/cmd-copy-mode.c index 665507e1..c5945743 100644 --- a/cmd-copy-mode.c +++ b/cmd-copy-mode.c @@ -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 @@ -33,7 +33,7 @@ const struct cmd_entry cmd_copy_mode_entry = { "copy-mode", NULL, "", CMD_NOCLIENT, NULL, - cmd_copy_mode_exec, + cmd_copy_mode_exec, NULL, NULL, NULL diff --git a/cmd-kill-session.c b/cmd-kill-session.c index e4addc87..21cb6025 100644 --- a/cmd-kill-session.c +++ b/cmd-kill-session.c @@ -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 @@ -47,7 +47,7 @@ cmd_kill_session_exec(unused void *ptr, struct cmd_ctx *ctx) { struct client *c; u_int i; - + for (i = 0; i < ARRAY_LENGTH(&clients); i++) { c = ARRAY_ITEM(&clients, i); if (c->session == ctx->session) { @@ -57,7 +57,7 @@ cmd_kill_session_exec(unused void *ptr, struct cmd_ctx *ctx) } session_destroy(ctx->session); - + if (ctx->cmdclient != NULL) server_write_client(ctx->cmdclient, MSG_EXIT, NULL, 0); } diff --git a/cmd-kill-window.c b/cmd-kill-window.c index e962fc75..13742e19 100644 --- a/cmd-kill-window.c +++ b/cmd-kill-window.c @@ -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 @@ -41,7 +41,7 @@ const struct cmd_entry cmd_kill_window_entry = { "kill-window", "killw", "[-i index]", CMD_NOCLIENT, cmd_kill_window_parse, - cmd_kill_window_exec, + cmd_kill_window_exec, cmd_kill_window_send, cmd_kill_window_recv, cmd_kill_window_free @@ -69,7 +69,7 @@ cmd_kill_window_parse(void **ptr, int argc, char **argv, char **cause) default: goto usage; } - } + } argc -= optind; argv += optind; if (argc != 0) @@ -117,7 +117,7 @@ cmd_kill_window_exec(void *ptr, struct cmd_ctx *ctx) } else server_redraw_client(c); } - + if (ctx->cmdclient != NULL) server_write_client(ctx->cmdclient, MSG_EXIT, NULL, 0); } diff --git a/cmd-last-window.c b/cmd-last-window.c index 7052c1f1..e68289cd 100644 --- a/cmd-last-window.c +++ b/cmd-last-window.c @@ -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 @@ -45,8 +45,8 @@ cmd_last_window_exec(unused void *ptr, struct cmd_ctx *ctx) if (session_last(ctx->session) == 0) server_redraw_session(ctx->session); else - ctx->error(ctx, "no last window"); - + ctx->error(ctx, "no last window"); + if (ctx->cmdclient != NULL) server_write_client(ctx->cmdclient, MSG_EXIT, NULL, 0); } diff --git a/cmd-link-window.c b/cmd-link-window.c index 331c6c45..00e3b4a7 100644 --- a/cmd-link-window.c +++ b/cmd-link-window.c @@ -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 @@ -45,7 +45,7 @@ const struct cmd_entry cmd_link_window_entry = { "link-window", "linkw", "[-dk] [-i index] name index", CMD_NOCLIENT, cmd_link_window_parse, - cmd_link_window_exec, + cmd_link_window_exec, cmd_link_window_send, cmd_link_window_recv, cmd_link_window_free @@ -83,7 +83,7 @@ cmd_link_window_parse(void **ptr, int argc, char **argv, char **cause) default: goto usage; } - } + } argc -= optind; argv += optind; if (argc != 2) @@ -116,7 +116,7 @@ cmd_link_window_exec(void *ptr, struct cmd_ctx *ctx) if (data == NULL) return; - + if ((src = session_find(data->srcname)) == NULL) { ctx->error(ctx, "session not found: %s", data->srcname); return; @@ -155,7 +155,7 @@ cmd_link_window_exec(void *ptr, struct cmd_ctx *ctx) dst->lastw = NULL; /* - * Can't error out after this or there could be an empty + * Can't error out after this or there could be an empty * session! */ } diff --git a/cmd-list-windows.c b/cmd-list-windows.c index 111101b2..056af295 100644 --- a/cmd-list-windows.c +++ b/cmd-list-windows.c @@ -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 @@ -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) diff --git a/cmd-new-session.c b/cmd-new-session.c index 418fbf8e..aff19eab 100644 --- a/cmd-new-session.c +++ b/cmd-new-session.c @@ -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 @@ -44,7 +44,7 @@ const struct cmd_entry cmd_new_session_entry = { "[-d] [-s session-name] [-n window-name] [command]", CMD_STARTSERVER|CMD_NOCLIENT|CMD_NOSESSION|CMD_CANTNEST, cmd_new_session_parse, - cmd_new_session_exec, + cmd_new_session_exec, cmd_new_session_send, cmd_new_session_recv, cmd_new_session_free @@ -76,7 +76,7 @@ cmd_new_session_parse(void **ptr, int argc, char **argv, char **cause) default: goto usage; } - } + } argc -= optind; argv += optind; if (argc != 0 && argc != 1) @@ -90,7 +90,7 @@ cmd_new_session_parse(void **ptr, int argc, char **argv, char **cause) usage: usage(cause, "%s %s", cmd_new_session_entry.name, cmd_new_session_entry.usage); - + cmd_new_session_free(data); return (-1); } @@ -103,7 +103,7 @@ cmd_new_session_exec(void *ptr, struct cmd_ctx *ctx) struct client *c = ctx->cmdclient; char *cmd, *cause; u_int sy; - + if (data == NULL) data = &std; diff --git a/cmd-new-window.c b/cmd-new-window.c index 730c0293..71d922f3 100644 --- a/cmd-new-window.c +++ b/cmd-new-window.c @@ -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 @@ -44,7 +44,7 @@ const struct cmd_entry cmd_new_window_entry = { "new-window", "neww", "[-d] [-i index] [-n name] [command]", CMD_NOCLIENT, cmd_new_window_parse, - cmd_new_window_exec, + cmd_new_window_exec, cmd_new_window_send, cmd_new_window_recv, cmd_new_window_free @@ -81,7 +81,7 @@ cmd_new_window_parse(void **ptr, int argc, char **argv, char **cause) default: goto usage; } - } + } argc -= optind; argv += optind; if (argc != 0 && argc != 1) @@ -111,7 +111,7 @@ cmd_new_window_exec(void *ptr, struct cmd_ctx *ctx) if (data == NULL) data = &std; - + cmd = data->cmd; if (cmd == NULL) cmd = default_command; @@ -128,7 +128,7 @@ cmd_new_window_exec(void *ptr, struct cmd_ctx *ctx) server_redraw_session(ctx->session); } else server_status_session(ctx->session); - + if (ctx->cmdclient != NULL) server_write_client(ctx->cmdclient, MSG_EXIT, NULL, 0); } diff --git a/cmd-next-window.c b/cmd-next-window.c index 8a807714..4495558e 100644 --- a/cmd-next-window.c +++ b/cmd-next-window.c @@ -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 @@ -45,8 +45,8 @@ cmd_next_window_exec(unused void *ptr, struct cmd_ctx *ctx) if (session_next(ctx->session) == 0) server_redraw_session(ctx->session); else - ctx->error(ctx, "no next window"); - + ctx->error(ctx, "no next window"); + if (ctx->cmdclient != NULL) server_write_client(ctx->cmdclient, MSG_EXIT, NULL, 0); } diff --git a/cmd-paste-buffer.c b/cmd-paste-buffer.c index b4bdf324..349feb48 100644 --- a/cmd-paste-buffer.c +++ b/cmd-paste-buffer.c @@ -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 @@ -34,7 +34,7 @@ const struct cmd_entry cmd_paste_buffer_entry = { "paste-buffer", NULL, "paste", CMD_NOCLIENT, NULL, - cmd_paste_buffer_exec, + cmd_paste_buffer_exec, NULL, NULL, NULL diff --git a/cmd-previous-window.c b/cmd-previous-window.c index cdf0b7d8..d0423998 100644 --- a/cmd-previous-window.c +++ b/cmd-previous-window.c @@ -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 @@ -45,8 +45,8 @@ cmd_previous_window_exec(unused void *ptr, struct cmd_ctx *ctx) if (session_previous(ctx->session) == 0) server_redraw_session(ctx->session); else - ctx->error(ctx, "no previous window"); - + ctx->error(ctx, "no previous window"); + if (ctx->cmdclient != NULL) server_write_client(ctx->cmdclient, MSG_EXIT, NULL, 0); } diff --git a/cmd-rename-session.c b/cmd-rename-session.c index ae28eec6..498bacd2 100644 --- a/cmd-rename-session.c +++ b/cmd-rename-session.c @@ -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 @@ -41,7 +41,7 @@ const struct cmd_entry cmd_rename_session_entry = { "rename-session", "rename", "new-name", CMD_NOCLIENT, cmd_rename_session_parse, - cmd_rename_session_exec, + cmd_rename_session_exec, cmd_rename_session_send, cmd_rename_session_recv, cmd_rename_session_free @@ -61,7 +61,7 @@ cmd_rename_session_parse(void **ptr, int argc, char **argv, char **cause) default: goto usage; } - } + } argc -= optind; argv += optind; if (argc != 1) @@ -89,7 +89,7 @@ cmd_rename_session_exec(void *ptr, struct cmd_ctx *ctx) xfree(ctx->session->name); ctx->session->name = xstrdup(data->newname); - + if (ctx->cmdclient != NULL) server_write_client(ctx->cmdclient, MSG_EXIT, NULL, 0); } diff --git a/cmd-rename-window.c b/cmd-rename-window.c index ba2f4fad..5ed0c161 100644 --- a/cmd-rename-window.c +++ b/cmd-rename-window.c @@ -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 @@ -42,7 +42,7 @@ const struct cmd_entry cmd_rename_window_entry = { "rename-window", "renamew", "[-i index] new-name", CMD_NOCLIENT, cmd_rename_window_parse, - cmd_rename_window_exec, + cmd_rename_window_exec, cmd_rename_window_send, cmd_rename_window_recv, cmd_rename_window_free @@ -71,7 +71,7 @@ cmd_rename_window_parse(void **ptr, int argc, char **argv, char **cause) default: goto usage; } - } + } argc -= optind; argv += optind; if (argc != 1) @@ -110,7 +110,7 @@ cmd_rename_window_exec(void *ptr, struct cmd_ctx *ctx) wl->window->name = xstrdup(data->newname); server_status_session(ctx->session); - + if (ctx->cmdclient != NULL) server_write_client(ctx->cmdclient, MSG_EXIT, NULL, 0); } diff --git a/cmd-scroll-mode.c b/cmd-scroll-mode.c index 17d839ae..5bdf5bb6 100644 --- a/cmd-scroll-mode.c +++ b/cmd-scroll-mode.c @@ -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 @@ -33,7 +33,7 @@ const struct cmd_entry cmd_scroll_mode_entry = { "scroll-mode", NULL, "", CMD_NOCLIENT, NULL, - cmd_scroll_mode_exec, + cmd_scroll_mode_exec, NULL, NULL, NULL diff --git a/cmd-select-window.c b/cmd-select-window.c index 16329ecf..896b18cb 100644 --- a/cmd-select-window.c +++ b/cmd-select-window.c @@ -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 @@ -41,7 +41,7 @@ const struct cmd_entry cmd_select_window_entry = { "select-window", "selectw", "index", CMD_NOCLIENT, cmd_select_window_parse, - cmd_select_window_exec, + cmd_select_window_exec, cmd_select_window_send, cmd_select_window_recv, cmd_select_window_free @@ -75,7 +75,7 @@ cmd_select_window_parse(void **ptr, int argc, char **argv, char **cause) default: goto usage; } - } + } argc -= optind; argv += optind; if (argc != 1) @@ -86,7 +86,7 @@ cmd_select_window_parse(void **ptr, int argc, char **argv, char **cause) xasprintf(cause, "index %s", errstr); goto error; } - + return (0); usage: @@ -116,7 +116,7 @@ cmd_select_window_exec(void *ptr, struct cmd_ctx *ctx) ctx->error(ctx, "no window %d", data->idx); break; } - + if (ctx->cmdclient != NULL) server_write_client(ctx->cmdclient, MSG_EXIT, NULL, 0); } diff --git a/cmd-send-prefix.c b/cmd-send-prefix.c index 3d556675..eb13b673 100644 --- a/cmd-send-prefix.c +++ b/cmd-send-prefix.c @@ -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 @@ -44,6 +44,6 @@ cmd_send_prefix_exec(unused void *ptr, struct cmd_ctx *ctx) { window_key(ctx->client->session->curw->window, prefix_key); - if (ctx->cmdclient != NULL) + if (ctx->cmdclient != NULL) server_write_client(ctx->cmdclient, MSG_EXIT, NULL, 0); } diff --git a/cmd-set-option.c b/cmd-set-option.c index 70a4c3e4..d0e86c89 100644 --- a/cmd-set-option.c +++ b/cmd-set-option.c @@ -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 @@ -43,7 +43,7 @@ const struct cmd_entry cmd_set_option_entry = { "set-option", "set", "option value", CMD_NOCLIENT|CMD_NOSESSION, cmd_set_option_parse, - cmd_set_option_exec, + cmd_set_option_exec, cmd_set_option_send, cmd_set_option_recv, cmd_set_option_free @@ -64,7 +64,7 @@ cmd_set_option_parse(void **ptr, int argc, char **argv, char **cause) default: goto usage; } - } + } argc -= optind; argv += optind; if (argc != 1 && argc != 2) @@ -104,7 +104,7 @@ cmd_set_option_exec(void *ptr, unused struct cmd_ctx *ctx) number = -1; if (data->value != NULL) { number = strtonum(data->value, 0, INT_MAX, &errstr); - + bool = -1; if (number == 1 || strcasecmp(data->value, "on") == 0 || strcasecmp(data->value, "yes") == 0) @@ -171,10 +171,10 @@ cmd_set_option_exec(void *ptr, unused struct cmd_ctx *ctx) server_redraw_client(c); } } - } else if (strcmp(data->option, "bell-action") == 0) { + } else if (strcmp(data->option, "bell-action") == 0) { if (data->value == NULL) { ctx->error(ctx, "invalid value"); - return; + return; } if (strcmp(data->value, "any") == 0) bell_action = BELL_ANY; @@ -186,10 +186,10 @@ cmd_set_option_exec(void *ptr, unused struct cmd_ctx *ctx) ctx->error(ctx, "unknown bell-action: %s", data->value); return; } - } else if (strcmp(data->option, "default-command") == 0) { + } else if (strcmp(data->option, "default-command") == 0) { if (data->value == NULL) { ctx->error(ctx, "invalid value"); - return; + return; } xfree(default_command); default_command = xstrdup(data->value); diff --git a/cmd-swap-window.c b/cmd-swap-window.c index 66480ebf..6c4cac0f 100644 --- a/cmd-swap-window.c +++ b/cmd-swap-window.c @@ -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 @@ -44,7 +44,7 @@ const struct cmd_entry cmd_swap_window_entry = { "swap-window", "swapw", "[-i index] name index", CMD_NOCLIENT, cmd_swap_window_parse, - cmd_swap_window_exec, + cmd_swap_window_exec, cmd_swap_window_send, cmd_swap_window_recv, cmd_swap_window_free @@ -78,7 +78,7 @@ cmd_swap_window_parse(void **ptr, int argc, char **argv, char **cause) default: goto usage; } - } + } argc -= optind; argv += optind; if (argc != 2) @@ -112,7 +112,7 @@ cmd_swap_window_exec(void *ptr, struct cmd_ctx *ctx) if (data == NULL) return; - + if ((src = session_find(data->srcname)) == NULL) { ctx->error(ctx, "session not found: %s", data->srcname); return; diff --git a/cmd-switch-client.c b/cmd-switch-client.c index 2d3788b7..ca122879 100644 --- a/cmd-switch-client.c +++ b/cmd-switch-client.c @@ -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 @@ -42,7 +42,7 @@ const struct cmd_entry cmd_switch_client_entry = { "switch-client", "switchc", "session-name", CMD_NOSESSION, cmd_switch_client_parse, - cmd_switch_client_exec, + cmd_switch_client_exec, cmd_switch_client_send, cmd_switch_client_recv, cmd_switch_client_free @@ -62,7 +62,7 @@ cmd_switch_client_parse(void **ptr, int argc, char **argv, char **cause) default: goto usage; } - } + } argc -= optind; argv += optind; if (argc != 1) @@ -88,14 +88,14 @@ cmd_switch_client_exec(void *ptr, struct cmd_ctx *ctx) if (data == NULL) return; - + if ((s = session_find(data->name)) == NULL) { ctx->error(ctx, "session not found: %s", data->name); return; } ctx->client->session = s; - + recalculate_sizes(); server_redraw_client(ctx->client); diff --git a/cmd-unbind-key.c b/cmd-unbind-key.c index 86a795a4..fd4e775f 100644 --- a/cmd-unbind-key.c +++ b/cmd-unbind-key.c @@ -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 @@ -40,7 +40,7 @@ const struct cmd_entry cmd_unbind_key_entry = { "unbind-key", "unbind", "key", CMD_NOCLIENT|CMD_NOSESSION, cmd_unbind_key_parse, - cmd_unbind_key_exec, + cmd_unbind_key_exec, cmd_unbind_key_send, cmd_unbind_key_recv, cmd_unbind_key_free @@ -59,7 +59,7 @@ cmd_unbind_key_parse(void **ptr, int argc, char **argv, char **cause) default: goto usage; } - } + } argc -= optind; argv += optind; if (argc != 1) diff --git a/cmd-unlink-window.c b/cmd-unlink-window.c index 9ed48104..577a2e2d 100644 --- a/cmd-unlink-window.c +++ b/cmd-unlink-window.c @@ -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 @@ -41,7 +41,7 @@ const struct cmd_entry cmd_unlink_window_entry = { "unlink-window", "unlinkw", "[-i index]", CMD_NOCLIENT, cmd_unlink_window_parse, - cmd_unlink_window_exec, + cmd_unlink_window_exec, cmd_unlink_window_send, cmd_unlink_window_recv, cmd_unlink_window_free @@ -69,7 +69,7 @@ cmd_unlink_window_parse(void **ptr, int argc, char **argv, char **cause) default: goto usage; } - } + } argc -= optind; argv += optind; if (argc != 0) @@ -98,7 +98,7 @@ cmd_unlink_window_exec(void *ptr, struct cmd_ctx *ctx) if (data == NULL) return; - + if (data->idx < 0) data->idx = -1; if (data->idx == -1) diff --git a/cmd.c b/cmd.c index 6526fa90..8e46a92f 100644 --- a/cmd.c +++ b/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 @@ -48,7 +48,7 @@ const struct cmd_entry *cmd_table[] = { &cmd_scroll_mode_entry, &cmd_select_window_entry, &cmd_send_prefix_entry, - &cmd_set_option_entry, + &cmd_set_option_entry, &cmd_swap_window_entry, &cmd_switch_client_entry, &cmd_unbind_key_entry, @@ -70,7 +70,7 @@ cmd_parse(int argc, char **argv, char **cause) entry = NULL; for (entryp = cmd_table; *entryp != NULL; entryp++) { - if ((*entryp)->alias != NULL && + if ((*entryp)->alias != NULL && strcmp((*entryp)->alias, argv[0]) == 0) { entry = *entryp; break; @@ -165,7 +165,7 @@ cmd_recv(struct buffer *b) u_int m, n; buffer_read(b, &m, sizeof m); - + n = 0; for (entryp = cmd_table; *entryp != NULL; entryp++) { if (n == m) @@ -195,7 +195,7 @@ void cmd_send_string(struct buffer *b, const char *s) { size_t n; - + if (s == NULL) { n = 0; buffer_write(b, &n, sizeof n); @@ -218,7 +218,7 @@ cmd_recv_string(struct buffer *b) if (n == 0) return (NULL); - + s = xmalloc(n); buffer_read(b, s, n); s[n - 1] = '\0'; diff --git a/input.c b/input.c index 6ac6b54f..33c7f074 100644 --- a/input.c +++ b/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 @@ -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); } @@ -253,7 +239,7 @@ input_state_first(u_char ch, struct input_ctx *ictx) if (INPUT_C0CONTROL(ch)) { if (ch == 0x1b) input_state(ictx, input_state_escape); - else + else input_handle_c0_control(ch, ictx); return; } @@ -268,10 +254,10 @@ input_state_first(u_char ch, struct input_ctx *ictx) input_handle_c1_control(ch, ictx); return; } - + input_handle_character(ch, ictx); } - + void input_state_escape(u_char ch, struct input_ctx *ictx) { @@ -326,7 +312,7 @@ input_state_title_first(u_char ch, struct input_ctx *ictx) input_start_string(ictx, STRING_IGNORE); input_state(ictx, input_state_title_second); return; - } + } input_state(ictx, input_state_first); } @@ -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); @@ -440,7 +423,7 @@ input_state_sequence_next(u_char ch, struct input_ctx *ictx) } return; } - + input_state(ictx, input_state_first); } @@ -449,13 +432,13 @@ input_state_sequence_intermediate(u_char ch, struct input_ctx *ictx) { if (INPUT_INTERMEDIATE(ch)) return; - + if (INPUT_UPPERCASE(ch) || INPUT_LOWERCASE(ch)) { input_state(ictx, input_state_first); input_handle_sequence(ch, ictx); return; } - + 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,10 +623,10 @@ 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; - + log_debug2("-- sq %zu: %hhu (%c): %u [sx=%u, sy=%u, cx=%u, cy=%u, " "ru=%u, rl=%u]", ictx->off, ch, ch, ARRAY_LENGTH(&ictx->args), screen_size_x(s), screen_size_y(s), s->cx, s->cy, s->rupper, @@ -687,8 +651,7 @@ 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; + uint16_t n; if (ictx->private != '\0') return; @@ -697,21 +660,16 @@ 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; + uint16_t n; if (ictx->private != '\0') return; @@ -720,20 +678,16 @@ 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; + uint16_t n; if (ictx->private != '\0') return; @@ -742,20 +696,16 @@ 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; + uint16_t n; if (ictx->private != '\0') return; @@ -764,21 +714,16 @@ 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; + uint16_t n; if (ictx->private != '\0') return; @@ -787,20 +732,16 @@ 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; + uint16_t n; if (ictx->private != '\0') return; @@ -809,23 +750,16 @@ 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; + uint16_t n; if (ictx->private != '\0') return; @@ -834,20 +768,16 @@ 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; + uint16_t n; if (ictx->private != '\0') return; @@ -856,23 +786,17 @@ 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; - uint16_t n; + struct screen *s = ictx->ctx.s; + uint16_t n; if (ictx->private != '\0') return; @@ -881,20 +805,17 @@ 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; - uint16_t n; + struct screen *s = ictx->ctx.s; + uint16_t n; if (ictx->private != '\0') return; @@ -903,20 +824,16 @@ 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; + uint16_t n, m; if (ictx->private != '\0') return; @@ -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; + uint16_t n; 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,8 +880,7 @@ 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; + uint16_t n; if (ictx->private != '\0') return; @@ -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,8 +908,7 @@ 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; + uint16_t n; if (ARRAY_LENGTH(&ictx->args) > 1) return; @@ -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,9 +988,9 @@ input_handle_sequence_rm(struct input_ctx *ictx) void input_handle_sequence_dsr(struct input_ctx *ictx) { - struct screen *s = &ictx->w->screen; - uint16_t n; - char reply[32]; + struct screen *s = ictx->ctx.s; + uint16_t n; + char reply[32]; if (ARRAY_LENGTH(&ictx->args) > 1) return; @@ -1133,8 +1013,8 @@ input_handle_sequence_dsr(struct input_ctx *ictx) void input_handle_sequence_decstbm(struct input_ctx *ictx) { - struct screen *s = &ictx->w->screen; - uint16_t n, m; + struct screen *s = ictx->ctx.s; + uint16_t n, m; if (ictx->private != '\0') return; @@ -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; - u_int i, n; - uint16_t m; + 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); } diff --git a/key-bindings.c b/key-bindings.c index d2f51b25..8889d81a 100644 --- a/key-bindings.c +++ b/key-bindings.c @@ -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 @@ -84,7 +84,7 @@ key_bindings_init(void) { 'S', &cmd_list_sessions_entry, NULL }, { 's', &cmd_list_sessions_entry, NULL }, { 'W', &cmd_list_windows_entry, NULL }, - { 'w', &cmd_list_windows_entry, NULL }, + { 'w', &cmd_list_windows_entry, NULL }, { '?', &cmd_list_keys_entry, NULL }, { '/', &cmd_list_keys_entry, NULL }, { 'C', &cmd_new_window_entry, NULL }, @@ -140,7 +140,7 @@ key_bindings_free(void) cmd_free(bd->cmd); xfree(bd); } - + ARRAY_FREE(&key_bindings); } @@ -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); } diff --git a/resize.c b/resize.c index c69ef08d..94a7621b 100644 --- a/resize.c +++ b/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 @@ -33,7 +33,7 @@ * smallest client it is attached to, and resize it to that size. Then for * every window, find the smallest session it is attached to, resize it to that * size and clear and redraw every client with it as the current window. - * + * * This is quite inefficient - better/additional data structures are needed * to make it better. * @@ -50,7 +50,7 @@ recalculate_sizes(void) struct client *c; struct window *w; u_int i, j, ssx, ssy; - + for (i = 0; i < ARRAY_LENGTH(&sessions); i++) { s = ARRAY_ITEM(&sessions, i); if (s == NULL) @@ -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); diff --git a/screen-display.c b/screen-display.c index 1985570e..4124a61e 100644 --- a/screen-display.c +++ b/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 @@ -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. */ @@ -167,13 +79,13 @@ void screen_display_scroll_region_up(struct screen *s) { u_int ny, sy; - + /* * If the region is the entire screen, this is easy-peasy. Allocate * a new line and adjust the history size. * XXX should this be done somewhere else? */ - if (s->rupper == 0 && s->rlower == screen_last_y(s)) { + if (s->rupper == 0 && s->rlower == screen_last_y(s)) { if (s->hsize == s->hlimit) { /* If the limit is hit, free 10% and shift up. */ ny = s->hlimit / 10; @@ -197,7 +109,7 @@ screen_display_scroll_region_up(struct screen *s) return; } - /* + /* * Scroll scrolling region up: * - delete rupper * - move rupper + 1 to rlower to rupper @@ -213,7 +125,7 @@ screen_display_scroll_region_up(struct screen *s) screen_display_free_lines(s, s->rupper, 1); if (s->rupper != s->rlower) { - screen_display_move_lines(s, + screen_display_move_lines(s, s->rupper, s->rupper + 1, s->rlower - s->rupper); } @@ -224,7 +136,7 @@ screen_display_scroll_region_up(struct screen *s) void screen_display_scroll_region_down(struct screen *s) { - /* + /* * Scroll scrolling region down: * - delete rlower * - move rupper to rlower - 1 to rupper + 1 @@ -252,14 +164,14 @@ 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; if (ny == 0) - return; + return; /* * Insert range of ny lines at 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); + } + } +} diff --git a/screen-redraw.c b/screen-redraw.c new file mode 100644 index 00000000..76d7c96f --- /dev/null +++ b/screen-redraw.c @@ -0,0 +1,218 @@ +/* $Id: screen-redraw.c,v 1.1 2007-12-06 09:46:22 nicm Exp $ */ + +/* + * Copyright (c) 2007 Nicholas Marriott + * + * 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 + +#include + +#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); + } +} diff --git a/screen-write.c b/screen-write.c new file mode 100644 index 00000000..c033a782 --- /dev/null +++ b/screen-write.c @@ -0,0 +1,516 @@ +/* $Id: screen-write.c,v 1.1 2007-12-06 09:46:23 nicm Exp $ */ + +/* + * Copyright (c) 2007 Nicholas Marriott + * + * 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 + +#include + +#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; + } +} diff --git a/screen.c b/screen.c index 5643ece0..051d5ef5 100644 --- a/screen.c +++ b/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 @@ -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. */ @@ -122,11 +172,11 @@ screen_resize(struct screen *s, u_int sx, u_int sy) if (sx == ox && sy == oy) return; - /* + /* * X dimension. */ if (sx != ox) { - /* + /* * If getting smaller, nuke any data in lines over the new * size. */ @@ -163,10 +213,10 @@ screen_resize(struct screen *s, u_int sx, u_int sy) screen_free_lines(s, s->hsize, my); screen_move_lines(s, s->hsize, s->hsize + my, oy - my); - + s->cy -= my; oy -= my; - } + } ny = oy - sy; if (ny > 0) { @@ -178,7 +228,7 @@ screen_resize(struct screen *s, u_int sx, u_int sy) s->cy = sy - 1; } } - + /* Resize line arrays. */ ny = s->hsize + sy; s->grid_data = xrealloc(s->grid_data, ny, sizeof *s->grid_data); @@ -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); } diff --git a/server-fn.c b/server-fn.c index 8caea797..9da001f5 100644 --- a/server-fn.c +++ b/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 @@ -71,7 +71,7 @@ server_extract_session(struct msg_command_data *data, char *name, char **cause) xasprintf(cause, "multiple sessions and session not specified"); return (NULL); } - return (s); + return (s); } void @@ -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,36 +229,36 @@ server_status_window(struct window *w) void printflike2 server_write_message(struct client *c, const char *fmt, ...) { - struct screen_draw_ctx ctx; - va_list ap; - char *msg; - size_t size; + 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); va_end(ap); - + size = strlen(msg); if (size < c->sx - 1) { msg = xrealloc(msg, 1, c->sx); 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); + 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); } } diff --git a/server-msg.c b/server-msg.c index a9f77bc2..fec44099 100644 --- a/server-msg.c +++ b/server-msg.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 @@ -38,7 +38,7 @@ void printflike2 server_msg_fn_command_print( struct server_msg { enum hdrtype type; - + int (*fn)(struct hdr *, struct client *); }; const struct server_msg server_msg_table[] = { @@ -64,7 +64,7 @@ server_msg_dispatch(struct client *c) if (BUFFER_USED(c->in) < (sizeof hdr) + hdr.size) return (0); buffer_remove(c->in, sizeof hdr); - + for (i = 0; i < NSERVERMSG; i++) { msg = server_msg_table + i; if (msg->type == hdr.type) { @@ -72,7 +72,7 @@ server_msg_dispatch(struct client *c) return (n); break; } - } + } if (i == NSERVERMSG) fatalx("unexpected message"); } @@ -120,7 +120,7 @@ server_msg_fn_command(struct hdr *hdr, struct client *c) if (hdr->size < sizeof data) fatalx("bad MSG_COMMAND size"); buffer_read(c->in, &data, sizeof data); - name = cmd_recv_string(c->in); + name = cmd_recv_string(c->in); client = cmd_recv_string(c->in); cmd = cmd_recv(c->in); @@ -147,7 +147,7 @@ server_msg_fn_command(struct hdr *hdr, struct client *c) } } else { if (client == NULL) { - server_msg_fn_command_error(&ctx, + server_msg_fn_command_error(&ctx, "%s: must specify a client", cmd->entry->name); goto out; } @@ -167,7 +167,7 @@ server_msg_fn_command(struct hdr *hdr, struct client *c) ctx.session = NULL; if (cmd->entry->flags & CMD_NOSESSION) { if (name != NULL) { - server_msg_fn_command_error(&ctx, + server_msg_fn_command_error(&ctx, "%s: cannot specify a session", cmd->entry->name); goto out; } @@ -179,7 +179,7 @@ server_msg_fn_command(struct hdr *hdr, struct client *c) xfree(cause); goto out; } - } + } cmd_exec(cmd, &ctx); cmd_free(cmd); diff --git a/server.c b/server.c index 6c974264..89e5970b 100644 --- a/server.c +++ b/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 @@ -107,7 +107,7 @@ server_start(const char *path) if (fcntl(fd, F_SETFL, mode|O_NONBLOCK) == -1) fatal("fcntl failed"); if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1) - fatal("fcntl failed"); + fatal("fcntl failed"); if (daemon(1, 1) != 0) fatal("daemon failed"); @@ -231,7 +231,7 @@ server_handle_windows(struct pollfd **pfd) if ((w = ARRAY_ITEM(&windows, i)) != NULL) { if (buffer_poll(*pfd, w->in, w->out) != 0) server_lost_window(w); - else + else server_handle_window(w); } (*pfd)++; @@ -371,7 +371,7 @@ server_lost_client(struct client *c) if (ARRAY_ITEM(&clients, i) == c) ARRAY_SET(&clients, i, NULL); } - + tty_free(&c->tty); close(c->fd); diff --git a/session.c b/session.c index e4a543ec..2ba32499 100644 --- a/session.c +++ b/session.c @@ -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 @@ -26,7 +26,7 @@ #include "tmux.h" /* Global session list. */ -struct sessions sessions; +struct sessions sessions; void session_cancelbell(struct session *s, struct winlink *wl) @@ -78,7 +78,7 @@ session_find(const char *name) if (s != NULL && strcmp(s->name, name) == 0) return (s); } - + return (NULL); } @@ -131,7 +131,7 @@ session_destroy(struct session *s) ARRAY_SET(&sessions, i, NULL); while (!ARRAY_EMPTY(&sessions) && ARRAY_LAST(&sessions) == NULL) ARRAY_TRUNC(&sessions, 1); - + while (!RB_EMPTY(&s->windows)) winlink_remove(&s->windows, RB_ROOT(&s->windows)); @@ -163,7 +163,7 @@ session_new(struct session *s, const char *name, const char *cmd, int idx) fatalx("session not found"); xsnprintf(buf, sizeof buf, "TMUX=%ld,%u", (long) getpid(), i); env[0] = buf; - + if ((w = window_create(name, cmd, env, s->sx, s->sy)) == NULL) return (NULL); return (session_attach(s, w, idx)); @@ -227,7 +227,7 @@ session_next(struct session *s) return (0); } -/* Move session to previous window. */ +/* Move session to previous window. */ int session_previous(struct session *s) { @@ -247,7 +247,7 @@ session_previous(struct session *s) return (0); } -/* Move session to specific window. */ +/* Move session to specific window. */ int session_select(struct session *s, int idx) { @@ -264,7 +264,7 @@ session_select(struct session *s, int idx) return (0); } -/* Move session to last used window. */ +/* Move session to last used window. */ int session_last(struct session *s) { @@ -273,7 +273,7 @@ session_last(struct session *s) wl = s->lastw; if (wl == NULL) return (-1); - if (wl == s->curw) + if (wl == s->curw) return (1); s->lastw = s->curw; diff --git a/status.c b/status.c index f6b0a057..5ab5a6c5 100644 --- a/status.c +++ b/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 @@ -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 winlink *wl; - char flag; + 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++) { diff --git a/tmux.c b/tmux.c index 7f8a6272..c6424bd4 100644 --- a/tmux.c +++ b/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 @@ -141,10 +141,10 @@ void sigreset(void) { struct sigaction act; - + memset(&act, 0, sizeof act); sigemptyset(&act.sa_mask); - + act.sa_handler = SIG_DFL; if (sigaction(SIGPIPE, &act, NULL) != 0) fatal("sigaction failed"); @@ -283,7 +283,7 @@ main(int argc, char **argv) pfd.events = POLLIN; if (BUFFER_USED(cctx.srv_out) > 0) pfd.events |= POLLOUT; - + if (poll(&pfd, 1, INFTIM) == -1) { if (errno == EAGAIN || errno == EINTR) continue; @@ -316,7 +316,7 @@ main(int argc, char **argv) if (hdr.size > INT_MAX - 1) fatalx("bad MSG_ERROR size"); log_warnx("%.*s", - (int) hdr.size, BUFFER_OUT(cctx.srv_in)); + (int) hdr.size, BUFFER_OUT(cctx.srv_in)); buffer_remove(cctx.srv_in, hdr.size); n = 1; goto out; diff --git a/tmux.h b/tmux.h index 488a7d59..77901477 100644 --- a/tmux.h +++ b/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 @@ -281,7 +281,7 @@ struct buffer { #define TTY_KKEYPADON 23 #define TTY_TITLE 24 #define TTY_MOUSEON 25 -#define TTY_MOUSEOFF 26 /* XXX merge allon/off into 1 arg? */ +#define TTY_MOUSEOFF 26 /* XXX merge allon/off into 1 arg? */ /* Message codes. */ enum hdrtype { @@ -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; @@ -378,35 +380,29 @@ struct screen { u_int saved_cy; u_char saved_attr; 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,11 +419,20 @@ 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 #define SCREEN_DEFCOLR 0x88 - + /* Input parser sequence argument. */ struct input_arg { u_char data[64]; @@ -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 */ diff --git a/tty-keys.c b/tty-keys.c index 186bf819..42c3e34f 100644 --- a/tty-keys.c +++ b/tty-keys.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 @@ -259,7 +259,7 @@ tty_keys_next(struct tty *tty, int *code) } xfree(s); if (tk == NULL) { - /* + /* * XXX Pass through unchanged. */ *code = '\e'; diff --git a/tty-write.c b/tty-write.c index e796b3e1..a58f1b2e 100644 --- a/tty-write.c +++ b/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 @@ -24,8 +24,7 @@ void tty_write_client(void *ptr, int cmd, ...) { struct client *c = ptr; - - va_list ap; + va_list ap; va_start(ap, cmd); tty_vwrite_client(c, cmd, ap); @@ -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++) { @@ -68,8 +68,8 @@ tty_vwrite_window(void *ptr, int cmd, va_list ap) if (c->session->curw->window != w) continue; - va_copy(aq, ap); - tty_vwrite(&c->tty, cmd, aq); + va_copy(aq, ap); + 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); } } diff --git a/tty.c b/tty.c index 3944ff0a..ec7097c8 100644 --- a/tty.c +++ b/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 @@ -25,7 +25,7 @@ #include #define TTYDEFCHARS /* glibc requires unistd.h before termios.h for TTYDEFCHARS. */ -#include +#include #include #include "tmux.h" @@ -87,7 +87,7 @@ tty_open(struct tty *tty, char **cause) tty->colr = SCREEN_DEFCOLR; tty_keys_init(tty); - + tty_fill_acs(tty); if (tcgetattr(tty->fd, &tty->tio) != 0) @@ -95,7 +95,7 @@ tty_open(struct tty *tty, char **cause) memset(&tio, 0, sizeof tio); tio.c_iflag = TTYDEF_IFLAG & ~(IXON|IXOFF|ICRNL|INLCR); tio.c_oflag = TTYDEF_OFLAG & ~(OPOST|ONLCR|OCRNL|ONLRET); - tio.c_lflag = + tio.c_lflag = TTYDEF_LFLAG & ~(IEXTEN|ICANON|ECHO|ECHOE|ECHOKE|ECHOCTL|ISIG); tio.c_cflag = TTYDEF_CFLAG; memcpy(&tio.c_cc, ttydefchars, sizeof tio.c_cc); @@ -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: - tty_puts(tty, clr_eol); + 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: - tty_puts(tty, clr_bol); + 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) @@ -417,13 +440,13 @@ tty_attributes(struct tty *tty, u_char attr, u_char colr) if (fg == 8) fg = 7; } - + if (fg == 8) tty_puts(tty, "\e[39m"); else if (set_a_foreground != NULL) tty_puts(tty, tparm(set_a_foreground, fg)); } - + bg = colr & 0xf; if (bg != (tty->colr & 0xf)) { if (tigetflag("AX") == TRUE) { diff --git a/window-copy.c b/window-copy.c index e6c588c4..afbeb31d 100644 --- a/window-copy.c +++ b/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 @@ -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); + 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; - - w->screen.mode |= (MODE_BACKGROUND|MODE_BGCURSOR); + data->ox = 0; + data->oy = 0; + data->cx = w->base.cx; + data->cy = w->base.cy; + + 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); - } - - 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->screen = &w->base; + screen_destroy(&data->screen); + + 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 */ - break; + screen_clear_selection(&data->screen); + break; case '\027': /* C-w */ case '\r': /* enter */ - if (data->selflag) - window_copy_copy_selection(w); - goto done; - case '\001': /* C-a */ - window_copy_cursor_bol(w); - return; - case '\005': /* C-e */ - window_copy_cursor_eol(w); - return; - } - if (data->oy != oy) { + window_copy_copy_selection(w); + window_copy_free(w); server_redraw_window(w); - window_copy_move_cursor(w); + break; + case '\001': /* C-a */ + window_copy_cursor_start_of_line(w); + break; + case '\005': /* C-e */ + window_copy_cursor_end_of_line(w); + break; } - return; +} -done: - w->mode = NULL; - xfree(w->modedata); - - w->screen.mode &= ~MODE_BACKGROUND; - - recalculate_sizes(); - server_redraw_window(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); +} + +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; + + 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_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,8 +420,7 @@ 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; + u_char i, xx; if (sx > ex) return; @@ -296,11 +434,11 @@ 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)++; } } - + *buf = ensure_size(*buf, len, 1, *off + 1); (*buf)[*off] = '\n'; (*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; + 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) - window_copy_scroll_right(w, 1); - else { + if (data->cx == 0) { + if (data->ox > 0) + window_copy_scroll_right(w, 1); + else { + window_copy_cursor_up(w); + window_copy_cursor_end_of_line(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_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); + if (window_copy_update_selection(w)) + window_copy_redraw_lines(w, data->cy - 1, 2); + else + window_copy_update_cursor(w); } - window_copy_move_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; - - 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); + window_copy_update_selection(w); + + 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); } diff --git a/window-more.c b/window-more.c index 618b4f81..64e4f03f 100644 --- a/window-more.c +++ b/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 @@ -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; + u_int i; - 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); - } + w->screen = &w->base; + screen_destroy(&data->screen); - screen_draw_move_cursor(ctx, 0, 0); + for (i = 0; i < ARRAY_LENGTH(&data->list); i++) + xfree(ARRAY_ITEM(&data->list, i)); + ARRAY_FREE(&data->list); - 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); + w->mode = NULL; + xfree(w->modedata); } void -window_more_draw_line(struct window *w, struct screen_draw_ctx *ctx, u_int py) +window_more_resize(struct window *w, u_int sx, u_int sy) { struct window_more_mode_data *data = w->modedata; - u_int p; + struct screen *s = &data->screen; - 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); - } + 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; - u_int top, sy, i; - - sy = screen_size_y(&w->screen); - - top = data->top; + struct screen *s = &data->screen; 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(); + window_more_free(w); server_redraw_window(w); - return; + break; case 'k': case 'K': case KEYC_UP: - window_more_up_1(w); - return; + window_more_scroll_up(w); + break; case 'j': case 'J': case KEYC_DOWN: - window_more_down_1(w); - return; + window_more_scroll_down(w); + break; case '\025': /* C-u */ case KEYC_PPAGE: - if (data->top < sy) + if (data->top < screen_size_y(s)) data->top = 0; else - data->top -= sy; + data->top -= screen_size_y(s); + window_more_redraw_screen(w); break; case '\006': /* C-f */ case KEYC_NPAGE: - if (data->top + sy > ARRAY_LENGTH(&data->list)) + if (data->top + screen_size_y(s) > ARRAY_LENGTH(&data->list)) data->top = ARRAY_LENGTH(&data->list); else - data->top += sy; + data->top += screen_size_y(s); + window_more_redraw_screen(w); break; } - if (top != data->top) - server_redraw_window(w); } void -window_more_up_1(struct window *w) +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_draw_ctx ctx; + 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); } diff --git a/window-scroll.c b/window-scroll.c index d696dabe..60d3d9cd 100644 --- a/window-scroll.c +++ b/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 @@ -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 { - u_int ox; - u_int oy; - u_int size; + struct screen screen; + + u_int ox; + u_int oy; }; 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); - } - - 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->screen = &w->base; + screen_destroy(&data->screen); + + 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); } diff --git a/window.c b/window.c index a0dfdaf3..47d4f05d 100644 --- a/window.c +++ b/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 @@ -90,7 +90,7 @@ winlink_next_index(struct winlinks *wwl) if (winlink_find_by_index(wwl, i) == NULL) return (i); } - + fatalx("no free indexes"); } @@ -136,7 +136,7 @@ struct winlink * winlink_next(unused struct winlinks *wwl, struct winlink *wl) { return (RB_NEXT(winlinks, wwl, wl)); -} +} struct winlink * winlink_previous(struct winlinks *wwl, struct winlink *wl) @@ -153,7 +153,7 @@ winlink_previous(struct winlinks *wwl, struct winlink *wl) if (wl == NULL) return (NULL); return (wk); -} +} struct window * window_create( @@ -189,14 +189,15 @@ window_create( if (fcntl(fd, F_SETFL, mode|O_NONBLOCK) == -1) fatal("fcntl failed"); if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1) - fatal("fcntl failed"); + fatal("fcntl failed"); w = xmalloc(sizeof *w); w->fd = fd; 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) { @@ -238,12 +239,14 @@ window_destroy(struct window *w) break; } ARRAY_REMOVE(&windows, i); - + close(w->fd); 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,20 +282,11 @@ 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) { if (w->mode != NULL) w->mode->key(w, key); else - input_key(w, key); + input_key(w, key); }