From 162bacdcd91caf631db6979a21c27d208a66046b Mon Sep 17 00:00:00 2001 From: Nicholas Marriott Date: Sun, 11 Jan 2009 23:31:46 +0000 Subject: [PATCH] Window splitting. Two vertical panes fixed 50% each. This is a huge diff, still a couple of bugs (notably heap corruption somewhere causing segfault on exit). --- CHANGES | 17 +- GNUmakefile | 4 +- Makefile | 4 +- TODO | 21 +- cmd-clock-mode.c | 4 +- cmd-copy-mode.c | 4 +- cmd-list-windows.c | 43 ++-- cmd-paste-buffer.c | 6 +- cmd-respawn-window.c | 16 +- cmd-scroll-mode.c | 4 +- cmd-send-keys.c | 8 +- cmd-send-prefix.c | 4 +- cmd-split-window.c | 211 +++++++++++++++++++ cmd-switch-pane.c | 61 ++++++ cmd.c | 4 +- input-keys.c | 34 ++-- input.c | 54 ++--- key-bindings.c | 12 +- resize.c | 9 +- screen-redraw.c | 235 +++++++++++---------- screen-write.c | 181 ++++++---------- server-msg.c | 3 +- server.c | 245 +++++++++++----------- status.c | 158 +++++++------- tmux.h | 151 +++++++------- tty-write.c | 79 ++----- tty.c | 297 ++++++++++++--------------- window-clock.c | 55 ++--- window-copy.c | 476 +++++++++++++++++++++---------------------- window-more.c | 102 +++++----- window-scroll.c | 140 ++++++------- window.c | 271 +++++++++++++++--------- 32 files changed, 1608 insertions(+), 1305 deletions(-) create mode 100644 cmd-split-window.c create mode 100644 cmd-switch-pane.c diff --git a/CHANGES b/CHANGES index 4a002a8e..b1beefdf 100644 --- a/CHANGES +++ b/CHANGES @@ -1,5 +1,20 @@ 11 January 2009 +* Vertical window splitting. Currently can only split a window into two panes. + New split-window command splits (bound to ") and switch-pane command (bound to + o) switches between panes. + + close-pane, swap-pane commands are to follow. Also to come are pane resizing, + >2 panes, the ability to break a pane out to a full window and vice versa and + possibly horizontal splitting. + + Panes are subelements of windows rather than being windows in their own + right. I tried to make them windows (so the splitting was at the session or + client level) but this rapidly became very complex and invasive. So in the + interests of having something working, I just made it so each window can have + two child processes instead of one (and it still took me 12 hours straight + coding). Now the concept is proven and much of the support code is there, + this may change in future if more flexibility is needed. * save-buffer command, from Tiago Cunha. 10 January 2009 @@ -859,7 +874,7 @@ (including mutt, emacs). No status bar yet and no key remapping or other customisation. -$Id: CHANGES,v 1.192 2009-01-11 23:14:57 nicm Exp $ +$Id: CHANGES,v 1.193 2009-01-11 23:31:46 nicm Exp $ LocalWords: showw utf UTF fulvio ciriaco joshe OSC APC gettime abc DEF OA clr LocalWords: rivo nurges lscm Erdely eol smysession mysession ek dstname RB diff --git a/GNUmakefile b/GNUmakefile index 93c96151..9fe2321d 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -1,4 +1,4 @@ -# $Id: GNUmakefile,v 1.50 2009-01-11 23:14:57 nicm Exp $ +# $Id: GNUmakefile,v 1.51 2009-01-11 23:31:46 nicm Exp $ .PHONY: clean @@ -33,7 +33,7 @@ SRCS= tmux.c server.c server-msg.c server-fn.c buffer.c buffer-poll.c status.c \ cmd-list-commands.c cmd-move-window.c cmd-select-prompt.c \ cmd-respawn-window.c cmd-source-file.c cmd-server-info.c \ cmd-clock-mode.c cmd-lock-server.c cmd-set-password.c \ - cmd-save-buffer.c \ + cmd-save-buffer.c cmd-switch-pane.c cmd-split-window.c \ window-clock.c window-scroll.c window-more.c window-copy.c \ options.c options-cmd.c paste.c colour.c utf8.c clock.c \ tty.c tty-term.c tty-keys.c tty-write.c diff --git a/Makefile b/Makefile index 87b0b02c..a403378f 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.87 2009-01-11 23:14:57 nicm Exp $ +# $Id: Makefile,v 1.88 2009-01-11 23:31:46 nicm Exp $ .SUFFIXES: .c .o .y .h .PHONY: clean update-index.html upload-index.html @@ -37,7 +37,7 @@ SRCS= tmux.c server.c server-msg.c server-fn.c buffer.c buffer-poll.c status.c \ cmd-list-commands.c cmd-move-window.c cmd-select-prompt.c \ cmd-respawn-window.c cmd-source-file.c cmd-server-info.c \ cmd-clock-mode.c cmd-lock-server.c cmd-set-password.c \ - cmd-save-buffer.c \ + cmd-save-buffer.c cmd-switch-pane.c cmd-split-window.c \ window-clock.c window-scroll.c window-more.c window-copy.c \ options.c options-cmd.c paste.c colour.c utf8.c clock.c \ tty.c tty-term.c tty-keys.c tty-write.c diff --git a/TODO b/TODO index ba766d91..e7bc7497 100644 --- a/TODO +++ b/TODO @@ -13,7 +13,7 @@ - status-fg/status-bg should be able to set attributes: bold, etc - refer to windows by name etc (duplicates? fnmatch?) - commands: - command to run something without a window at all? + command to run something without a window at all - output to window-more command to purge window history extend list-clients to list clients attached to a session (-a for all?) bring back detach-session to detach all clients on a session? @@ -42,7 +42,7 @@ session not being watched? - tidy up window modes - problems with force-width when wrapping line in emacs? -- next prev word etc in command prompt; also ^K; also make is support modes +- next prev word etc in command prompt; also ^K; also make it support modes to support vi. is there something could use for this? editline(3)/readline? - many more info() displays for various things - vi half page scroll @@ -51,8 +51,8 @@ others do not. this might be hard: a flag for each grid line (top bit of size maybe)? a single flag is insufficient as can't then tell when to /stop/ unwrapping -- OPTIONS section in man page with description of new option handling -- update set/setw in man page with -g and -u flags +- document OPTIONS section in man page with description of new option handling +- document update set/setw in man page with -g and -u flags - more # commands in status-left,right eg #H for hostname. others? - input.c is too complicated. simplify? - try change from pass-though model to redraw model (use updated screen @@ -66,7 +66,9 @@ - document clock-mode - document password/locking commands - document lock-after-time +- document panes and window splitting: split-window and switch-pane - a command to display the status line briefly when it is turned off +- neww should support -k - FAQ "Can I have some examples of cool things I can do with tmux?" -- linkw, more?? 17:06 < NicM> tmux new then eg tmux linkw -s0:0 17:06 < simmel> NicM link-window? @@ -87,3 +89,14 @@ 17:09 < NicM> or kills it if it is only linked to one 17:09 < NicM> unlinkw only unlinks it - clone session command +- panes: + swap-panes + close-pane + move-pane (to window) + pane resizing + >2 panes per window +- would be nice if tmux could be the shell +- some sort of extension to command prompt so can do eg + bind m command-prompt 'split "man %%"' + bind r command-prompt 'renamew "%%"' + which then asks for a string, substitutes %% in command and executes it diff --git a/cmd-clock-mode.c b/cmd-clock-mode.c index 0e76135c..9c8e72d0 100644 --- a/cmd-clock-mode.c +++ b/cmd-clock-mode.c @@ -1,4 +1,4 @@ -/* $Id: cmd-clock-mode.c,v 1.1 2009-01-10 19:35:39 nicm Exp $ */ +/* $Id: cmd-clock-mode.c,v 1.2 2009-01-11 23:31:46 nicm Exp $ */ /* * Copyright (c) 2009 Nicholas Marriott @@ -48,7 +48,7 @@ cmd_clock_mode_exec(struct cmd *self, struct cmd_ctx *ctx) if ((wl = cmd_find_window(ctx, data->target, NULL)) == NULL) return; - window_set_mode(wl->window, &window_clock_mode); + window_pane_set_mode(wl->window->active, &window_clock_mode); if (ctx->cmdclient != NULL) server_write_client(ctx->cmdclient, MSG_EXIT, NULL, 0); diff --git a/cmd-copy-mode.c b/cmd-copy-mode.c index 3ddd4759..f342e3fe 100644 --- a/cmd-copy-mode.c +++ b/cmd-copy-mode.c @@ -1,4 +1,4 @@ -/* $Id: cmd-copy-mode.c,v 1.12 2009-01-10 18:08:55 nicm Exp $ */ +/* $Id: cmd-copy-mode.c,v 1.13 2009-01-11 23:31:46 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -48,7 +48,7 @@ cmd_copy_mode_exec(struct cmd *self, struct cmd_ctx *ctx) if ((wl = cmd_find_window(ctx, data->target, NULL)) == NULL) return; - window_set_mode(wl->window, &window_copy_mode); + window_pane_set_mode(wl->window->active, &window_copy_mode); if (ctx->cmdclient != NULL) server_write_client(ctx->cmdclient, MSG_EXIT, NULL, 0); diff --git a/cmd-list-windows.c b/cmd-list-windows.c index efc9d47e..56434f67 100644 --- a/cmd-list-windows.c +++ b/cmd-list-windows.c @@ -1,4 +1,4 @@ -/* $Id: cmd-list-windows.c,v 1.25 2008-09-26 06:45:25 nicm Exp $ */ +/* $Id: cmd-list-windows.c,v 1.26 2009-01-11 23:31:46 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -48,8 +48,9 @@ cmd_list_windows_exec(struct cmd *self, struct cmd_ctx *ctx) struct session *s; struct winlink *wl; struct window *w; + struct window_pane *wp; struct grid_data *gd; - u_int i; + u_int i, j; unsigned long long size; const char *name; @@ -58,23 +59,31 @@ cmd_list_windows_exec(struct cmd *self, struct cmd_ctx *ctx) RB_FOREACH(wl, winlinks, &s->windows) { w = wl->window; - gd = w->base.grid; - size = 0; - for (i = 0; i < gd->hsize; i++) - size += gd->size[i] * sizeof **gd->data; - size += gd->hsize * (sizeof *gd->data); - size += gd->hsize * (sizeof *gd->size); - - if (w->fd != -1) - name = ttyname(w->fd); - else - name = ""; ctx->print(ctx, - "%d: %s \"%s\" (%s) [%ux%u] [history %u/%u, %llu bytes]", - wl->idx, w->name, w->base.title, name, - screen_size_x(&w->base), screen_size_y(&w->base), - gd->hsize, gd->hlimit, size); + "%d: %s [%ux%u]", wl->idx, w->name, w->sx, w->sy); + for (i = 0; i < 2; i++) { + wp = w->panes[i]; + if (wp == NULL) + continue; + gd = wp->base.grid; + + size = 0; + for (j = 0; j < gd->hsize; j++) + size += gd->size[j] * sizeof **gd->data; + size += gd->hsize * (sizeof *gd->data); + size += gd->hsize * (sizeof *gd->size); + + if (wp->fd != -1) + name = ttyname(wp->fd); + else + name = ""; + + ctx->print(ctx, " pane %d:" + " %s [%ux%u] [history %u/%u, %llu bytes]", i, name, + screen_size_x(&wp->base), screen_size_y(&wp->base), + gd->hsize, gd->hlimit, size); + } } if (ctx->cmdclient != NULL) diff --git a/cmd-paste-buffer.c b/cmd-paste-buffer.c index 93ad57b5..5077b392 100644 --- a/cmd-paste-buffer.c +++ b/cmd-paste-buffer.c @@ -1,4 +1,4 @@ -/* $Id: cmd-paste-buffer.c,v 1.13 2009-01-11 00:48:42 nicm Exp $ */ +/* $Id: cmd-paste-buffer.c,v 1.14 2009-01-11 23:31:46 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -46,11 +46,13 @@ cmd_paste_buffer_exec(struct cmd *self, struct cmd_ctx *ctx) { struct cmd_buffer_data *data = self->data; struct winlink *wl; + struct window *w; struct session *s; struct paste_buffer *pb; if ((wl = cmd_find_window(ctx, data->target, &s)) == NULL) return; + w = wl->window; if (data->buffer == -1) pb = paste_get_top(&s->buffers); @@ -60,7 +62,7 @@ cmd_paste_buffer_exec(struct cmd *self, struct cmd_ctx *ctx) } if (pb != NULL) - buffer_write(wl->window->out, pb->data, strlen(pb->data)); + buffer_write(w->active->out, pb->data, strlen(pb->data)); /* Delete the buffer if -d. */ if (data->flags & CMD_DFLAG) { diff --git a/cmd-respawn-window.c b/cmd-respawn-window.c index 20002c3e..4590206c 100644 --- a/cmd-respawn-window.c +++ b/cmd-respawn-window.c @@ -1,4 +1,4 @@ -/* $Id: cmd-respawn-window.c,v 1.6 2009-01-10 19:37:35 nicm Exp $ */ +/* $Id: cmd-respawn-window.c,v 1.7 2009-01-11 23:31:46 nicm Exp $ */ /* * Copyright (c) 2008 Nicholas Marriott @@ -46,6 +46,7 @@ cmd_respawn_window_exec(struct cmd *self, struct cmd_ctx *ctx) { struct cmd_target_data *data = self->data; struct winlink *wl; + struct window *w; struct session *s; const char *env[] = { NULL /* TMUX= */, "TERM=screen", NULL @@ -55,8 +56,10 @@ cmd_respawn_window_exec(struct cmd *self, struct cmd_ctx *ctx) if ((wl = cmd_find_window(ctx, data->target, &s)) == NULL) return; + w = wl->window; - if (wl->window->fd != -1 && !(data->flags & CMD_KFLAG)) { + if ((w->panes[0]->fd != -1 || (w->panes[1] != NULL && + w->panes[1]->fd != -1)) && !(data->flags & CMD_KFLAG)) { ctx->error(ctx, "window still active: %s:%d", s->name, wl->idx); return; } @@ -66,14 +69,17 @@ cmd_respawn_window_exec(struct cmd *self, struct cmd_ctx *ctx) xsnprintf(buf, sizeof buf, "TMUX=%ld,%u", (long) getpid(), i); env[0] = buf; - if (window_spawn(wl->window, data->arg, wl->window->cwd, env) != 0) { + if (w->panes[1] != NULL) + window_remove_pane(w, 1); + + if (window_pane_spawn(w->panes[0], data->arg, NULL, env) != 0) { ctx->error(ctx, "respawn failed: %s:%d", s->name, wl->idx); return; } - screen_reinit(&wl->window->base); + screen_reinit(&w->panes[0]->base); recalculate_sizes(); - server_redraw_window(wl->window); + server_redraw_window(w); 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 b7e3c1aa..f1f448bd 100644 --- a/cmd-scroll-mode.c +++ b/cmd-scroll-mode.c @@ -1,4 +1,4 @@ -/* $Id: cmd-scroll-mode.c,v 1.13 2009-01-10 18:08:55 nicm Exp $ */ +/* $Id: cmd-scroll-mode.c,v 1.14 2009-01-11 23:31:46 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -48,7 +48,7 @@ cmd_scroll_mode_exec(struct cmd *self, struct cmd_ctx *ctx) if ((wl = cmd_find_window(ctx, data->target, NULL)) == NULL) return; - window_set_mode(wl->window, &window_scroll_mode); + window_pane_set_mode(wl->window->active, &window_scroll_mode); if (ctx->cmdclient != NULL) server_write_client(ctx->cmdclient, MSG_EXIT, NULL, 0); diff --git a/cmd-send-keys.c b/cmd-send-keys.c index ac03a5ec..afded43c 100644 --- a/cmd-send-keys.c +++ b/cmd-send-keys.c @@ -1,4 +1,4 @@ -/* $Id: cmd-send-keys.c,v 1.15 2008-12-10 20:25:41 nicm Exp $ */ +/* $Id: cmd-send-keys.c,v 1.16 2009-01-11 23:31:46 nicm Exp $ */ /* * Copyright (c) 2008 Nicholas Marriott @@ -119,8 +119,10 @@ cmd_send_keys_exec(struct cmd *self, struct cmd_ctx *ctx) if ((wl = cmd_find_window(ctx, data->target, NULL)) == NULL) return; - for (i = 0; i < data->nkeys; i++) - window_key(wl->window, ctx->curclient, data->keys[i]); + for (i = 0; i < data->nkeys; i++) { + window_pane_key( + wl->window->active, ctx->curclient, data->keys[i]); + } 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 78cd4afa..2d17bea1 100644 --- a/cmd-send-prefix.c +++ b/cmd-send-prefix.c @@ -1,4 +1,4 @@ -/* $Id: cmd-send-prefix.c,v 1.19 2008-09-26 06:45:25 nicm Exp $ */ +/* $Id: cmd-send-prefix.c,v 1.20 2009-01-11 23:31:46 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -51,7 +51,7 @@ cmd_send_prefix_exec(struct cmd *self, struct cmd_ctx *ctx) return; key = options_get_number(&s->options, "prefix"); - window_key(wl->window, ctx->curclient, key); + window_pane_key(wl->window->active, ctx->curclient, key); if (ctx->cmdclient != NULL) server_write_client(ctx->cmdclient, MSG_EXIT, NULL, 0); diff --git a/cmd-split-window.c b/cmd-split-window.c new file mode 100644 index 00000000..5e9c0693 --- /dev/null +++ b/cmd-split-window.c @@ -0,0 +1,211 @@ +/* $Id: cmd-split-window.c,v 1.1 2009-01-11 23:31:46 nicm Exp $ */ + +/* + * Copyright (c) 2009 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 + +#include "tmux.h" + +/* + * Create a new window. + */ + +int cmd_split_window_parse(struct cmd *, int, char **, char **); +void cmd_split_window_exec(struct cmd *, struct cmd_ctx *); +void cmd_split_window_send(struct cmd *, struct buffer *); +void cmd_split_window_recv(struct cmd *, struct buffer *); +void cmd_split_window_free(struct cmd *); +void cmd_split_window_init(struct cmd *, int); +void cmd_split_window_print(struct cmd *, char *, size_t); + +struct cmd_split_window_data { + char *target; + char *cmd; + int flag_detached; +}; + +const struct cmd_entry cmd_split_window_entry = { + "split-window", "splitw", + "[-d] [-t target-window] [command]", + 0, + cmd_split_window_init, + cmd_split_window_parse, + cmd_split_window_exec, + cmd_split_window_send, + cmd_split_window_recv, + cmd_split_window_free, + cmd_split_window_print +}; + +void +cmd_split_window_init(struct cmd *self, unused int arg) +{ + struct cmd_split_window_data *data; + + self->data = data = xmalloc(sizeof *data); + data->target = NULL; + data->cmd = NULL; + data->flag_detached = 0; +} + +int +cmd_split_window_parse(struct cmd *self, int argc, char **argv, char **cause) +{ + struct cmd_split_window_data *data; + int opt; + + self->entry->init(self, 0); + data = self->data; + + while ((opt = getopt(argc, argv, "dt:")) != -1) { + switch (opt) { + case 'd': + data->flag_detached = 1; + break; + case 't': + if (data->target == NULL) + data->target = xstrdup(optarg); + break; + default: + goto usage; + } + } + argc -= optind; + argv += optind; + if (argc != 0 && argc != 1) + goto usage; + + if (argc == 1) + data->cmd = xstrdup(argv[0]); + + return (0); + +usage: + xasprintf(cause, "usage: %s %s", self->entry->name, self->entry->usage); + + self->entry->free(self); + return (-1); +} + +void +cmd_split_window_exec(struct cmd *self, struct cmd_ctx *ctx) +{ + struct cmd_split_window_data *data = self->data; + struct session *s; + struct winlink *wl; + const char *env[] = { + NULL /* TMUX= */, "TERM=screen", NULL + }; + char buf[256]; + char *cmd, *cwd; + u_int i, sx, sy, hlimit; + + if ((wl = cmd_find_window(ctx, data->target, &s)) == NULL) + return; + + if (wl->window->panes[1] != NULL) { + ctx->error(ctx, "window is already split"); + return; + } + + if (session_index(s, &i) != 0) + fatalx("session not found"); + xsnprintf(buf, sizeof buf, "TMUX=%ld,%u", (long) getpid(), i); + env[0] = buf; + + cmd = data->cmd; + if (cmd == NULL) + cmd = options_get_string(&s->options, "default-command"); + if (ctx->cmdclient == NULL || ctx->cmdclient->cwd == NULL) + cwd = options_get_string(&global_options, "default-path"); + else + cwd = ctx->cmdclient->cwd; + + hlimit = options_get_number(&s->options, "history-limit"); + sx = wl->window->sx; + sy = wl->window->sy - (wl->window->sy / 2); + wl->window->panes[1] = window_pane_create(wl->window, sx, sy, hlimit); + if (window_pane_spawn(wl->window->panes[1], cmd, cwd, env) != 0) { + ctx->error(ctx, "command failed: %s", cmd); + return; + } + window_resize(wl->window, wl->window->sx, wl->window->sy); + server_redraw_window(wl->window); + + if (!data->flag_detached) { + wl->window->active = wl->window->panes[1]; + session_select(s, wl->idx); + server_redraw_session(s); + } else + server_status_window(s); + + if (ctx->cmdclient != NULL) + server_write_client(ctx->cmdclient, MSG_EXIT, NULL, 0); +} + +void +cmd_split_window_send(struct cmd *self, struct buffer *b) +{ + struct cmd_split_window_data *data = self->data; + + buffer_write(b, data, sizeof *data); + cmd_send_string(b, data->target); + cmd_send_string(b, data->cmd); +} + +void +cmd_split_window_recv(struct cmd *self, struct buffer *b) +{ + struct cmd_split_window_data *data; + + self->data = data = xmalloc(sizeof *data); + buffer_read(b, data, sizeof *data); + data->target = cmd_recv_string(b); + data->cmd = cmd_recv_string(b); +} + +void +cmd_split_window_free(struct cmd *self) +{ + struct cmd_split_window_data *data = self->data; + + if (data->target != NULL) + xfree(data->target); + if (data->cmd != NULL) + xfree(data->cmd); + xfree(data); +} + +void +cmd_split_window_print(struct cmd *self, char *buf, size_t len) +{ + struct cmd_split_window_data *data = self->data; + size_t off = 0; + + off += xsnprintf(buf, len, "%s", self->entry->name); + if (data == NULL) + return; + if (off < len && data->flag_detached) + off += xsnprintf(buf + off, len - off, " -d"); + if (off < len && data->target != NULL) + off += xsnprintf(buf + off, len - off, " -t %s", data->target); + if (off < len && data->cmd != NULL) + off += xsnprintf(buf + off, len - off, " %s", data->cmd); +} diff --git a/cmd-switch-pane.c b/cmd-switch-pane.c new file mode 100644 index 00000000..a84f01fa --- /dev/null +++ b/cmd-switch-pane.c @@ -0,0 +1,61 @@ +/* $Id: cmd-switch-pane.c,v 1.1 2009-01-11 23:31:46 nicm Exp $ */ + +/* + * Copyright (c) 2009 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 "tmux.h" + +/* + * Enter clock mode. + */ + +void cmd_switch_pane_exec(struct cmd *, struct cmd_ctx *); + +const struct cmd_entry cmd_switch_pane_entry = { + "switch-pane", "switchp", + CMD_TARGET_WINDOW_USAGE, + 0, + cmd_target_init, + cmd_target_parse, + cmd_switch_pane_exec, + cmd_target_send, + cmd_target_recv, + cmd_target_free, + cmd_target_print +}; + +void +cmd_switch_pane_exec(struct cmd *self, struct cmd_ctx *ctx) +{ + struct cmd_target_data *data = self->data; + struct winlink *wl; + + if ((wl = cmd_find_window(ctx, data->target, NULL)) == NULL) + return; + + if (wl->window->panes[1] != NULL) { + if (wl->window->active == wl->window->panes[0]) + wl->window->active = wl->window->panes[1]; + else + wl->window->active = wl->window->panes[0]; + server_redraw_window(wl->window); + } + + if (ctx->cmdclient != NULL) + server_write_client(ctx->cmdclient, MSG_EXIT, NULL, 0); +} diff --git a/cmd.c b/cmd.c index 5b1ce895..d1d5ffe1 100644 --- a/cmd.c +++ b/cmd.c @@ -1,4 +1,4 @@ -/* $Id: cmd.c,v 1.73 2009-01-11 23:14:57 nicm Exp $ */ +/* $Id: cmd.c,v 1.74 2009-01-11 23:31:46 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -71,9 +71,11 @@ const struct cmd_entry *cmd_table[] = { &cmd_show_options_entry, &cmd_show_window_options_entry, &cmd_source_file_entry, + &cmd_split_window_entry, &cmd_start_server_entry, &cmd_swap_window_entry, &cmd_switch_client_entry, + &cmd_switch_pane_entry, &cmd_unbind_key_entry, &cmd_unlink_window_entry, NULL diff --git a/input-keys.c b/input-keys.c index 98d0e001..efddf217 100644 --- a/input-keys.c +++ b/input-keys.c @@ -1,4 +1,4 @@ -/* $Id: input-keys.c,v 1.20 2009-01-10 18:28:09 nicm Exp $ */ +/* $Id: input-keys.c,v 1.21 2009-01-11 23:31:46 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -104,7 +104,7 @@ struct input_key_ent input_keys[] = { /* Translate a key code from client into an output key sequence. */ void -input_key(struct window *w, int key) +input_key(struct window_pane *wp, int key) { struct input_key_ent *ike; u_int i; @@ -115,8 +115,8 @@ input_key(struct window *w, int key) if (key != KEYC_NONE && KEYC_REMOVEESC(key) < KEYC_OFFSET) { if (KEYC_ISESC(key)) - buffer_write8(w->out, '\033'); - buffer_write8(w->out, (uint8_t) KEYC_REMOVEESC(key)); + buffer_write8(wp->out, '\033'); + buffer_write8(wp->out, (uint8_t) KEYC_REMOVEESC(key)); return; } @@ -124,10 +124,10 @@ input_key(struct window *w, int key) ike = &input_keys[i]; if ((ike->flags & INPUTKEY_KEYPAD) && - !(w->screen->mode & MODE_KKEYPAD)) + !(wp->screen->mode & MODE_KKEYPAD)) continue; if ((ike->flags & INPUTKEY_CURSOR) && - !(w->screen->mode & MODE_KCURSOR)) + !(wp->screen->mode & MODE_KCURSOR)) continue; if (ike->flags & INPUTKEY_MODIFIER) { @@ -150,7 +150,7 @@ input_key(struct window *w, int key) log_debug2("found key 0x%x: \"%s\"", key, ike->data); if (ike->flags & INPUTKEY_XTERM && - options_get_number(&w->options, "xterm-keys")) { + options_get_number(&wp->window->options, "xterm-keys")) { /* In xterm keys mode, append modifier argument. */ ch = '\0'; if (KEYC_ISSFT(key) && KEYC_ISESC(key) && KEYC_ISCTL(key)) @@ -169,12 +169,12 @@ input_key(struct window *w, int key) ch = '2'; if (ch != '\0') { log_debug("output argument is: %c", ch); - buffer_write(w->out, ike->data, dlen - 1); - buffer_write8(w->out, ';'); - buffer_write8(w->out, ch); - buffer_write8(w->out, ike->data[dlen - 1]); + buffer_write(wp->out, ike->data, dlen - 1); + buffer_write8(wp->out, ';'); + buffer_write8(wp->out, ch); + buffer_write8(wp->out, ike->data[dlen - 1]); } else - buffer_write(w->out, ike->data, dlen); + buffer_write(wp->out, ike->data, dlen); return; } if (ike->flags & INPUTKEY_MODIFIER) { @@ -183,15 +183,15 @@ input_key(struct window *w, int key) * control (shift not supported). */ if (KEYC_ISESC(key)) - buffer_write8(w->out, '\033'); + buffer_write8(wp->out, '\033'); if (!KEYC_ISCTL(key)) { - buffer_write(w->out, ike->data, dlen); + buffer_write(wp->out, ike->data, dlen); return; } - buffer_write(w->out, ike->data, dlen - 1); - buffer_write8(w->out, ike->data[dlen - 1] ^ 0x20); + buffer_write(wp->out, ike->data, dlen - 1); + buffer_write8(wp->out, ike->data[dlen - 1] ^ 0x20); return; } - buffer_write(w->out, ike->data, dlen); + buffer_write(wp->out, ike->data, dlen); } diff --git a/input.c b/input.c index 880462af..c073b6e2 100644 --- a/input.c +++ b/input.c @@ -1,4 +1,4 @@ -/* $Id: input.c,v 1.72 2009-01-10 01:51:22 nicm Exp $ */ +/* $Id: input.c,v 1.73 2009-01-11 23:31:46 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -217,9 +217,9 @@ input_state(struct input_ctx *ictx, void *state) } void -input_init(struct window *w) +input_init(struct window_pane *wp) { - struct input_ctx *ictx = &w->ictx; + struct input_ctx *ictx = &wp->ictx; ARRAY_INIT(&ictx->args); @@ -236,38 +236,38 @@ input_init(struct window *w) } void -input_free(struct window *w) +input_free(struct window_pane *wp) { - if (w->ictx.string_buf != NULL) - xfree(w->ictx.string_buf); + if (wp->ictx.string_buf != NULL) + xfree(wp->ictx.string_buf); - ARRAY_FREE(&w->ictx.args); + ARRAY_FREE(&wp->ictx.args); } void -input_parse(struct window *w) +input_parse(struct window_pane *wp) { - struct input_ctx *ictx = &w->ictx; + struct input_ctx *ictx = &wp->ictx; u_char ch; - if (BUFFER_USED(w->in) == 0) + if (BUFFER_USED(wp->in) == 0) return; - ictx->buf = BUFFER_OUT(w->in); - ictx->len = BUFFER_USED(w->in); + ictx->buf = BUFFER_OUT(wp->in); + ictx->len = BUFFER_USED(wp->in); ictx->off = 0; - ictx->w = w; + ictx->wp = wp; log_debug2("entry; buffer=%zu", ictx->len); - if (w->mode == NULL) - screen_write_start(&ictx->ctx, &w->base, tty_write_window, w); + if (wp->mode == NULL) + screen_write_start(&ictx->ctx, wp, &wp->base); else - screen_write_start(&ictx->ctx, &w->base, NULL, NULL); + screen_write_start(&ictx->ctx, NULL, &wp->base); if (ictx->off != ictx->len) - w->flags |= WINDOW_ACTIVITY; + wp->window->flags |= WINDOW_ACTIVITY; while (ictx->off < ictx->len) { ch = ictx->buf[ictx->off++]; ictx->state(ch, ictx); @@ -275,7 +275,7 @@ input_parse(struct window *w) screen_write_stop(&ictx->ctx); - buffer_remove(w->in, ictx->len); + buffer_remove(wp->in, ictx->len); } void @@ -499,7 +499,7 @@ input_state_string_escape(u_char ch, struct input_ctx *ictx) return; } screen_set_title(ictx->ctx.s, s + 2); - server_status_window(ictx->w); + server_status_window(ictx->wp->window); xfree(s); break; case STRING_APPLICATION: @@ -507,15 +507,15 @@ input_state_string_escape(u_char ch, struct input_ctx *ictx) return; s = input_get_string(ictx); screen_set_title(ictx->ctx.s, s); - server_status_window(ictx->w); + server_status_window(ictx->wp->window); xfree(s); break; case STRING_NAME: if (ch != '\\') return; - xfree(ictx->w->name); - ictx->w->name = input_get_string(ictx); - server_status_window(ictx->w); + xfree(ictx->wp->window->name); + ictx->wp->window->name = input_get_string(ictx); + server_status_window(ictx->wp->window); break; } return; @@ -548,7 +548,9 @@ input_state_utf8(u_char ch, struct input_ctx *ictx) void input_handle_character(u_char ch, struct input_ctx *ictx) { - if (ch > 0x7f && options_get_number(&ictx->w->options, "utf8")) { + struct window_pane *wp = ictx->wp; + + if (ch > 0x7f && options_get_number(&wp->window->options, "utf8")) { /* * UTF-8 sequence. * @@ -602,7 +604,7 @@ input_handle_c0_control(u_char ch, struct input_ctx *ictx) screen_write_carriagereturn(&ictx->ctx); break; case '\007': /* BELL */ - ictx->w->flags |= WINDOW_BELL; + ictx->wp->window->flags |= WINDOW_BELL; break; case '\010': /* BS */ screen_write_cursorleft(&ictx->ctx, 1); @@ -1128,7 +1130,7 @@ input_handle_sequence_dsr(struct input_ctx *ictx) xsnprintf(reply, sizeof reply, "\033[%u;%uR", s->cy + 1, s->cx + 1); log_debug("cursor request, reply: %s", reply); - buffer_write(ictx->w->out, reply, strlen(reply)); + buffer_write(ictx->wp->out, reply, strlen(reply)); break; } } diff --git a/key-bindings.c b/key-bindings.c index f7b8e75e..b4084526 100644 --- a/key-bindings.c +++ b/key-bindings.c @@ -1,4 +1,4 @@ -/* $Id: key-bindings.c,v 1.42 2009-01-10 19:35:39 nicm Exp $ */ +/* $Id: key-bindings.c,v 1.43 2009-01-11 23:31:46 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -77,6 +77,7 @@ key_bindings_init(void) int key; const struct cmd_entry *entry; } table[] = { + { '"', &cmd_split_window_entry }, { '#', &cmd_list_buffers_entry }, { '&', &cmd_kill_window_entry }, { '-', &cmd_delete_buffer_entry }, @@ -94,17 +95,18 @@ key_bindings_init(void) { '=', &cmd_scroll_mode_entry }, { '?', &cmd_list_keys_entry }, { '[', &cmd_copy_mode_entry }, + { '\'', &cmd_select_prompt_entry }, { ']', &cmd_paste_buffer_entry }, { 'c', &cmd_new_window_entry }, { 'd', &cmd_detach_client_entry }, { 'l', &cmd_last_window_entry }, { 'n', &cmd_next_window_entry }, + { 'o', &cmd_switch_pane_entry }, { 'p', &cmd_previous_window_entry }, { 'r', &cmd_refresh_client_entry }, { 's', &cmd_list_sessions_entry }, { 't', &cmd_clock_mode_entry }, { 'w', &cmd_list_windows_entry }, - { '\'', &cmd_select_prompt_entry }, { META, &cmd_send_prefix_entry }, }; u_int i; @@ -152,13 +154,13 @@ key_bindings_error(struct cmd_ctx *ctx, const char *fmt, ...) void printflike2 key_bindings_print(struct cmd_ctx *ctx, const char *fmt, ...) { - struct window *w = ctx->cursession->curw->window; + struct winlink *wl = ctx->cursession->curw; va_list ap; - window_set_mode(w, &window_more_mode); + window_pane_set_mode(wl->window->active, &window_more_mode); va_start(ap, fmt); - window_more_vadd(w, fmt, ap); + window_more_vadd(wl->window->active, fmt, ap); va_end(ap); } diff --git a/resize.c b/resize.c index 4068e471..2c2ee5fc 100644 --- a/resize.c +++ b/resize.c @@ -1,4 +1,4 @@ -/* $Id: resize.c,v 1.17 2008-12-08 16:19:51 nicm Exp $ */ +/* $Id: resize.c,v 1.18 2009-01-11 23:31:46 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -125,12 +125,11 @@ recalculate_sizes(void) if (limit != 0 && ssy > limit) ssy = limit; - if (screen_size_x(&w->base) == ssx && - screen_size_y(&w->base) == ssy) + if (w->sx == ssx && w->sy == ssy) continue; - log_debug("window size %u,%u (was %u,%u)", ssx, ssy, - screen_size_x(&w->base), screen_size_y(&w->base)); + log_debug( + "window size %u,%u (was %u,%u)", ssx, ssy, w->sx, w->sy); window_resize(w, ssx, ssy); server_redraw_window(w); diff --git a/screen-redraw.c b/screen-redraw.c index 7b3a8ec0..df57c7da 100644 --- a/screen-redraw.c +++ b/screen-redraw.c @@ -1,4 +1,4 @@ -/* $Id: screen-redraw.c,v 1.15 2009-01-09 23:57:42 nicm Exp $ */ +/* $Id: screen-redraw.c,v 1.16 2009-01-11 23:31:46 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -22,146 +22,143 @@ #include "tmux.h" -/* Initialise redrawing with a window. */ +void screen_redraw_blankx(struct client *, u_int, u_int); +void screen_redraw_blanky(struct client *, u_int, u_int); +void screen_redraw_line(struct client *, struct screen *, u_int, u_int); + +/* Redraw entire screen.. */ void -screen_redraw_start_window(struct screen_redraw_ctx *ctx, struct window *w) +screen_redraw_screen(struct client *c, struct screen *s) { - struct screen *t = w->screen; + struct winlink *wl = c->session->curw; + u_int i, cx, cy, sy; + int status; - screen_redraw_start(ctx, t, tty_write_window, w); -} + status = options_get_number(&c->session->options, "status"); -/* 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; + /* Override the normal screen if one is given. */ + if (s != NULL) { + for (i = 0; i < screen_size_y(s); i++) + screen_redraw_line(c, s, 0, i); + return; + } - 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 *, enum tty_cmd, ...), 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. XXX. + /* + * A normal client screen is made up of three parts: a top window, a + * bottom window and a status line. The bottom window may be turned + * off; the status line is always drawn. */ - ctx->saved_cx = s->cx; - ctx->saved_cy = s->cy; - ctx->write(ctx->data, TTY_SCROLLREGION, 0, screen_size_y(s) - 1); - ctx->write(ctx->data, TTY_CURSORMOVE, s->cx, s->cy); - ctx->write(ctx->data, TTY_CURSORMODE, 0); - ctx->write(ctx->data, TTY_MOUSEMODE, 0); + /* Draw the top window. */ + s = wl->window->panes[0]->screen; + sy = screen_size_y(s); + if (screen_size_y(s) == c->sy && wl->window->panes[1] == NULL) + sy--; + cx = s->cx; + cy = s->cy; + for (i = 0; i < sy; i++) + screen_redraw_line(c, s, 0, i); + s->cx = cx; + s->cy = cy; + + /* Draw the bottom window. */ + if (wl->window->panes[1] != NULL) { + s = wl->window->panes[1]->screen; + sy = screen_size_y(s); + if (!status && screen_size_y(s) == c->sy - (c->sy / 2) - 1) + sy--; + cx = s->cx; + cy = s->cy; + for (i = 0; i < sy; i++) + screen_redraw_line(c, s, wl->window->sy / 2, i); + s->cx = cx; + s->cy = cy; + } + + /* Fill in empty space. */ + if (wl->window->sx < c->sx) { + screen_redraw_blankx( + c, wl->window->sx, c->sx - wl->window->sx); + } + if (wl->window->sy < c->sy - status) { + screen_redraw_blanky( + c, wl->window->sy, c->sy - wl->window->sy); + } + + /* Draw separator line. */ + s = wl->window->panes[0]->screen; + if (screen_size_y(s) != wl->window->sy) + screen_redraw_blanky(c, screen_size_y(s), 1); + + /* Draw the status line. */ + screen_redraw_status(c); } -/* Finish redrawing. */ +/* Draw the status line. */ void -screen_redraw_stop(struct screen_redraw_ctx *ctx) +screen_redraw_status(struct client *c) { - struct screen *s = ctx->s; - - s->cx = ctx->saved_cx; - s->cy = ctx->saved_cy; - - ctx->write(ctx->data, TTY_SCROLLREGION, s->rupper, s->rlower); - ctx->write(ctx->data, TTY_CURSORMOVE, s->cx, s->cy); - if (s->mode & MODE_CURSOR) - ctx->write(ctx->data, TTY_CURSORMODE, 1); - if (s->mode & MODE_MOUSE) - ctx->write(ctx->data, TTY_MOUSEMODE, 1); + screen_redraw_line(c, &c->status, c->sy - 1, 0); } -/* Write character. */ +/* Draw blank columns. */ void -screen_redraw_putc( - struct screen_redraw_ctx *ctx, struct grid_cell *gc, u_char ch) +screen_redraw_blankx(struct client *c, u_int ox, u_int nx) { - gc->data = ch; - ctx->write(ctx->data, TTY_CELL, gc); - ctx->s->cx++; + u_int i, j; + + tty_putcode(&c->tty, TTYC_SGR0); + for (j = 0; j < c->sy; j++) { + tty_putcode2(&c->tty, TTYC_CUP, j, ox); + for (i = 0; i < nx; i++) + tty_putc(&c->tty, ' '); + } + + c->tty.cx = UINT_MAX; + c->tty.cy = UINT_MAX; + memcpy(&c->tty.cell, &grid_default_cell, sizeof c->tty.cell); } -/* Write string. */ -void printflike3 -screen_redraw_puts( - struct screen_redraw_ctx *ctx, struct grid_cell *gc, const char *fmt, ...) -{ - va_list ap; - char *msg, *ptr; - - va_start(ap, fmt); - xvasprintf(&msg, fmt, ap); - va_end(ap); - - for (ptr = msg; *ptr != '\0'; ptr++) - screen_redraw_putc(ctx, gc, (u_char) *ptr); - - xfree(msg); -} - -/* Redraw single cell. */ +/* Draw blank lines. */ void -screen_redraw_cell(struct screen_redraw_ctx *ctx, u_int px, u_int py) +screen_redraw_blanky(struct client *c, u_int oy, u_int ny) +{ + u_int i, j; + + tty_putcode(&c->tty, TTYC_SGR0); + for (j = 0; j < ny; j++) { + tty_putcode2(&c->tty, TTYC_CUP, oy + j, 0); + for (i = 0; i < c->sx; i++) { + if (j == 0) + tty_putc(&c->tty, '-'); + else + tty_putc(&c->tty, ' '); + } + } + + c->tty.cx = UINT_MAX; + c->tty.cy = UINT_MAX; + memcpy(&c->tty.cell, &grid_default_cell, sizeof c->tty.cell); +} + +/* Draw a line. */ +void +screen_redraw_line(struct client *c, struct screen *s, u_int oy, u_int py) { const struct grid_cell *gc; struct grid_cell tc; + u_int i; - 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->cx, ctx->s->cy); - } + for (i = 0; i < screen_size_x(s); i++) { + s->cx = i; + s->cy = py; - gc = grid_view_peek_cell(ctx->s->grid, px, py); - if (screen_check_selection(ctx->s, px, py)) { - memcpy(&tc, &ctx->s->sel.cell, sizeof tc); - tc.data = gc->data; - ctx->write(ctx->data, TTY_CELL, &tc); - } else - ctx->write(ctx->data, TTY_CELL, gc); - ctx->s->cx++; -} - -/* Draw set of lines. */ -void -screen_redraw_lines(struct screen_redraw_ctx *ctx, u_int py, u_int ny) -{ - u_int i, j; - - for (j = py; j < py + ny; j++) { - for (i = 0; i < screen_size_x(ctx->s); i++) - screen_redraw_cell(ctx, i, j); - } -} - -/* Draw set of columns. */ -void -screen_redraw_columns(struct screen_redraw_ctx *ctx, u_int px, u_int nx) -{ - u_int i, j; - - for (j = 0; j < screen_size_y(ctx->s); j++) { - for (i = px; i < px + nx; i++) - screen_redraw_cell(ctx, i, j); + gc = grid_view_peek_cell(s->grid, i, py); + if (screen_check_selection(s, i, py)) { + memcpy(&tc, &s->sel.cell, sizeof tc); + tc.data = gc->data; + tty_write(&c->tty, s, oy, TTY_CELL, &tc); + } else + tty_write(&c->tty, s, oy, TTY_CELL, gc); } } diff --git a/screen-write.c b/screen-write.c index 2b3a7c17..e6d9cb88 100644 --- a/screen-write.c +++ b/screen-write.c @@ -1,4 +1,4 @@ -/* $Id: screen-write.c,v 1.23 2009-01-10 01:51:22 nicm Exp $ */ +/* $Id: screen-write.c,v 1.24 2009-01-11 23:31:46 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -24,53 +24,28 @@ /* Initialise writing with a window. */ void -screen_write_start_window(struct screen_write_ctx *ctx, struct window *w) +screen_write_start( + struct screen_write_ctx *ctx, struct window_pane *wp, struct screen *s) { - 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 *, enum tty_cmd, ...), void *data) -{ - ctx->write = write; - ctx->data = data; - ctx->s = s; - + if (wp != NULL) { + ctx->write = tty_write_window; + ctx->data = wp; + if (ctx->s == NULL) + ctx->s = wp->screen; + } else { + ctx->write = NULL; + ctx->data = NULL; + } + if (ctx->write != NULL) ctx->write(ctx->data, TTY_CURSORMODE, 0); } /* Finish writing. */ void -screen_write_stop(struct screen_write_ctx *ctx) +screen_write_stop(unused struct screen_write_ctx *ctx) { - struct screen *s = ctx->s; - - if (ctx->write != NULL && s->mode & MODE_CURSOR) - ctx->write(ctx->data, TTY_CURSORMODE, 1); } /* Write character. */ @@ -140,9 +115,6 @@ screen_write_cursorup(struct screen_write_ctx *ctx, u_int ny) return; s->cy -= ny; - - if (ctx->write != NULL) - ctx->write(ctx->data, TTY_CURSORUP, ny); } /* Cursor down by ny. */ @@ -160,9 +132,6 @@ screen_write_cursordown(struct screen_write_ctx *ctx, u_int ny) return; s->cy += ny; - - if (ctx->write != NULL) - ctx->write(ctx->data, TTY_CURSORDOWN, ny); } /* Cursor right by nx. */ @@ -180,9 +149,6 @@ screen_write_cursorright(struct screen_write_ctx *ctx, u_int nx) return; s->cx += nx; - - if (ctx->write != NULL) - ctx->write(ctx->data, TTY_CURSORRIGHT, nx); } /* Cursor left by nx. */ @@ -200,9 +166,6 @@ screen_write_cursorleft(struct screen_write_ctx *ctx, u_int nx) return; s->cx -= nx; - - if (ctx->write != NULL) - ctx->write(ctx->data, TTY_CURSORLEFT, nx); } /* Insert nx characters. */ @@ -219,11 +182,11 @@ screen_write_insertcharacter(struct screen_write_ctx *ctx, u_int nx) if (nx == 0) return; - if (s->cx <= screen_size_x(s) - 1) - grid_view_insert_cells(s->grid, s->cx, s->cy, nx); - if (ctx->write != NULL) ctx->write(ctx->data, TTY_INSERTCHARACTER, nx); + + if (s->cx <= screen_size_x(s) - 1) + grid_view_insert_cells(s->grid, s->cx, s->cy, nx); } /* Delete nx characters. */ @@ -240,11 +203,11 @@ screen_write_deletecharacter(struct screen_write_ctx *ctx, u_int nx) if (nx == 0) return; - if (s->cx <= screen_size_x(s) - 1) - grid_view_delete_cells(s->grid, s->cx, s->cy, nx); - if (ctx->write != NULL) ctx->write(ctx->data, TTY_DELETECHARACTER, nx); + + if (s->cx <= screen_size_x(s) - 1) + grid_view_delete_cells(s->grid, s->cx, s->cy, nx); } /* Insert ny lines. */ @@ -261,15 +224,15 @@ screen_write_insertline(struct screen_write_ctx *ctx, u_int ny) if (ny == 0) return; + if (ctx->write != NULL) + ctx->write(ctx->data, TTY_INSERTLINE, ny); + if (s->cy < s->rupper || s->cy > s->rlower) grid_view_insert_lines(s->grid, s->cy, ny); else { grid_view_insert_lines_region( s->grid, s->rupper, s->rlower, s->cy, ny); } - - if (ctx->write != NULL) - ctx->write(ctx->data, TTY_INSERTLINE, ny); } /* Delete ny lines. */ @@ -286,15 +249,15 @@ screen_write_deleteline(struct screen_write_ctx *ctx, u_int ny) if (ny == 0) return; + if (ctx->write != NULL) + ctx->write(ctx->data, TTY_DELETELINE, ny); + if (s->cy < s->rupper || s->cy > s->rlower) grid_view_delete_lines(s->grid, s->cy, ny); else { grid_view_delete_lines_region( s->grid, s->rupper, s->rlower, s->cy, ny); } - - if (ctx->write != NULL) - ctx->write(ctx->data, TTY_DELETELINE, ny); } /* Clear line at cursor. */ @@ -303,10 +266,10 @@ screen_write_clearline(struct screen_write_ctx *ctx) { struct screen *s = ctx->s; - grid_view_clear(s->grid, 0, s->cy, screen_size_x(s), 1); - if (ctx->write != NULL) ctx->write(ctx->data, TTY_CLEARLINE); + + grid_view_clear(s->grid, 0, s->cy, screen_size_x(s), 1); } /* Clear to end of line from cursor. */ @@ -318,11 +281,11 @@ screen_write_clearendofline(struct screen_write_ctx *ctx) sx = screen_size_x(s); - if (s->cx <= sx - 1) - grid_view_clear(s->grid, s->cx, s->cy, sx - s->cx, 1); - if (ctx->write != NULL) ctx->write(ctx->data, TTY_CLEARENDOFLINE); + + if (s->cx <= sx - 1) + grid_view_clear(s->grid, s->cx, s->cy, sx - s->cx, 1); } /* Clear to start of line from cursor. */ @@ -334,13 +297,13 @@ screen_write_clearstartofline(struct screen_write_ctx *ctx) sx = screen_size_x(s); + if (ctx->write != NULL) + ctx->write(ctx->data, TTY_CLEARSTARTOFLINE); + if (s->cx > sx - 1) grid_view_clear(s->grid, 0, s->cy, sx, 1); else grid_view_clear(s->grid, 0, s->cy, s->cx + 1, 1); - - if (ctx->write != NULL) - ctx->write(ctx->data, TTY_CLEARSTARTOFLINE); } /* Move cursor to px,py. */ @@ -356,9 +319,6 @@ screen_write_cursormove(struct screen_write_ctx *ctx, u_int px, u_int py) s->cx = px; s->cy = py; - - if (ctx->write != NULL) - ctx->write(ctx->data, TTY_CURSORMOVE, px, py); } /* Set cursor mode. */ @@ -371,9 +331,6 @@ screen_write_cursormode(struct screen_write_ctx *ctx, int state) s->mode |= MODE_CURSOR; else s->mode &= ~MODE_CURSOR; - - if (ctx->write != NULL) - ctx->write(ctx->data, TTY_CURSORMODE, state); } /* Reverse index (up with scroll). */ @@ -382,13 +339,13 @@ screen_write_reverseindex(struct screen_write_ctx *ctx) { struct screen *s = ctx->s; + if (ctx->write != NULL) + ctx->write(ctx->data, TTY_REVERSEINDEX); + if (s->cy == s->rupper) grid_view_scroll_region_down(s->grid, s->rupper, s->rlower); else if (s->cy > 0) s->cy--; - - if (ctx->write != NULL) - ctx->write(ctx->data, TTY_REVERSEINDEX); } /* Set scroll region. */ @@ -411,9 +368,6 @@ screen_write_scrollregion( s->rupper = rupper; s->rlower = rlower; - - if (ctx->write != NULL) - ctx->write(ctx->data, TTY_SCROLLREGION, rupper, rlower); } /* Set insert mode. */ @@ -422,13 +376,13 @@ screen_write_insertmode(struct screen_write_ctx *ctx, int state) { struct screen *s = ctx->s; + if (ctx->write != NULL) + ctx->write(ctx->data, TTY_INSERTMODE, state); + if (state) s->mode |= MODE_INSERT; else s->mode &= ~MODE_INSERT; - - if (ctx->write != NULL) - ctx->write(ctx->data, TTY_INSERTMODE, state); } /* Set mouse mode. */ @@ -437,13 +391,13 @@ screen_write_mousemode(struct screen_write_ctx *ctx, int state) { struct screen *s = ctx->s; + if (ctx->write != NULL) + ctx->write(ctx->data, TTY_MOUSEMODE, state); + if (state) s->mode |= MODE_MOUSE; else s->mode &= ~MODE_MOUSE; - - if (ctx->write != NULL) - ctx->write(ctx->data, TTY_MOUSEMODE, state); } /* Line feed (down with scroll). */ @@ -452,13 +406,13 @@ screen_write_linefeed(struct screen_write_ctx *ctx) { struct screen *s = ctx->s; + if (ctx->write != NULL) + ctx->write(ctx->data, TTY_LINEFEED); + if (s->cy == s->rlower) grid_view_scroll_region_up(s->grid, s->rupper, s->rlower); else if (s->cy < screen_size_x(s) - 1) s->cy++; - - if (ctx->write != NULL) - ctx->write(ctx->data, TTY_LINEFEED); } /* Carriage return (cursor to start of line). */ @@ -468,9 +422,6 @@ screen_write_carriagereturn(struct screen_write_ctx *ctx) struct screen *s = ctx->s; s->cx = 0; - - if (ctx->write != NULL) - ctx->write(ctx->data, TTY_CARRIAGERETURN); } /* Set keypad cursor keys mode. */ @@ -479,13 +430,13 @@ screen_write_kcursormode(struct screen_write_ctx *ctx, int state) { struct screen *s = ctx->s; + if (ctx->write != NULL) + ctx->write(ctx->data, TTY_KCURSORMODE); + if (state) s->mode |= MODE_KCURSOR; else s->mode &= ~MODE_KCURSOR; - - if (ctx->write != NULL) - ctx->write(ctx->data, TTY_KCURSORMODE); } /* Set keypad number keys mode. */ @@ -494,13 +445,13 @@ screen_write_kkeypadmode(struct screen_write_ctx *ctx, int state) { struct screen *s = ctx->s; + if (ctx->write != NULL) + ctx->write(ctx->data, TTY_KKEYPADMODE); + if (state) s->mode |= MODE_KKEYPAD; else s->mode &= ~MODE_KKEYPAD; - - if (ctx->write != NULL) - ctx->write(ctx->data, TTY_KKEYPADMODE); } /* Clear to end of screen from cursor. */ @@ -513,12 +464,12 @@ screen_write_clearendofscreen(struct screen_write_ctx *ctx) sx = screen_size_x(s); sy = screen_size_y(s); + if (ctx->write != NULL) + ctx->write(ctx->data, TTY_CLEARENDOFSCREEN); + if (s->cx <= sx - 1) grid_view_clear(s->grid, s->cx, s->cy, sx - s->cx, 1); grid_view_clear(s->grid, 0, s->cy + 1, sx, sy - (s->cy + 1)); - - if (ctx->write != NULL) - ctx->write(ctx->data, TTY_CLEARENDOFSCREEN); } /* Clear to start of screen. */ @@ -530,15 +481,15 @@ screen_write_clearstartofscreen(struct screen_write_ctx *ctx) sx = screen_size_x(s); + if (ctx->write != NULL) + ctx->write(ctx->data, TTY_CLEARSTARTOFSCREEN); + if (s->cy > 0) grid_view_clear(s->grid, 0, 0, sx, s->cy - 1); if (s->cx > sx - 1) grid_view_clear(s->grid, 0, s->cy, sx, 1); else grid_view_clear(s->grid, 0, s->cy, s->cx, 1); - - if (ctx->write != NULL) - ctx->write(ctx->data, TTY_CLEARSTARTOFSCREEN); } /* Clear entire screen. */ @@ -547,10 +498,10 @@ screen_write_clearscreen(struct screen_write_ctx *ctx) { struct screen *s = ctx->s; - grid_view_clear(s->grid, 0, 0, screen_size_x(s), screen_size_y(s)); - if (ctx->write != NULL) ctx->write(ctx->data, TTY_CLEARSCREEN); + + grid_view_clear(s->grid, 0, 0, screen_size_x(s), screen_size_y(s)); } /* Write cell data. */ @@ -600,8 +551,8 @@ screen_write_cell(struct screen_write_ctx *ctx, const struct grid_cell *gc) * cells back to the character. Don't overwrite the current * cell as that happens later anyway. */ - xx = s->cx; - while (xx-- > 0) { + xx = s->cx + 1; + while (--xx > 0) { hc = grid_view_peek_cell(gd, xx, s->cy); if (!(hc->flags & GRID_FLAG_PADDING)) break; @@ -643,14 +594,16 @@ screen_write_cell(struct screen_write_ctx *ctx, const struct grid_cell *gc) /* Write the actual cell. */ grid_view_set_cell(gd, s->cx, s->cy, gc); - s->cx += width; if (ctx->write != NULL) { - if (screen_check_selection(ctx->s, s->cx, s->cy)) { - memcpy(&tc, &ctx->s->sel.cell, sizeof tc); + if (screen_check_selection(s, s->cx, s->cy)) { + memcpy(&tc, &s->sel.cell, sizeof tc); tc.data = gc->data; ctx->write(ctx->data, TTY_CELL, &tc); } else ctx->write(ctx->data, TTY_CELL, gc); } + + /* Move the cursor. */ + s->cx += width; } diff --git a/server-msg.c b/server-msg.c index 1912a829..43293a13 100644 --- a/server-msg.c +++ b/server-msg.c @@ -1,4 +1,4 @@ -/* $Id: server-msg.c,v 1.56 2009-01-11 00:48:42 nicm Exp $ */ +/* $Id: server-msg.c,v 1.57 2009-01-11 23:31:46 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -21,6 +21,7 @@ #include #include #include +#include #include #include "tmux.h" diff --git a/server.c b/server.c index 1c617092..c9139ba9 100644 --- a/server.c +++ b/server.c @@ -1,4 +1,4 @@ -/* $Id: server.c,v 1.94 2009-01-11 00:48:42 nicm Exp $ */ +/* $Id: server.c,v 1.95 2009-01-11 23:31:46 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -49,12 +49,11 @@ void server_fill_clients(struct pollfd **); void server_handle_clients(struct pollfd **); struct client *server_accept_client(int); void server_handle_client(struct client *); -void server_handle_window(struct window *); +void server_handle_window(struct window *, int); void server_lost_client(struct client *); -void server_lost_window(struct window *); +int server_lost_window(struct window *, int); void server_check_redraw(struct client *); -void server_do_redraw_client(struct client *); -void server_do_redraw_locked(struct client *); +void server_redraw_locked(struct client *); void server_check_timers(struct client *); void server_second_timers(void); int server_update_socket(const char *); @@ -184,7 +183,9 @@ server_main(const char *srv_path, int srv_fd) pfds = NULL; while (!sigterm) { /* Initialise pollfd array. */ - nfds = 1 + ARRAY_LENGTH(&windows) + ARRAY_LENGTH(&clients) * 2; + nfds = 1; + nfds += ARRAY_LENGTH(&windows) * 2; + nfds += ARRAY_LENGTH(&clients) * 2; pfds = xrealloc(pfds, nfds, sizeof *pfds); pfd = pfds; @@ -279,19 +280,25 @@ server_main(const char *srv_path, int srv_fd) void server_fill_windows(struct pollfd **pfd) { - struct window *w; - u_int i; + struct window *w; + struct window_pane *wp; + u_int i, j; for (i = 0; i < ARRAY_LENGTH(&windows); i++) { - if ((w = ARRAY_ITEM(&windows, i)) == NULL || w->fd == -1) - (*pfd)->fd = -1; - else { - (*pfd)->fd = w->fd; - (*pfd)->events = POLLIN; - if (BUFFER_USED(w->out) > 0) - (*pfd)->events |= POLLOUT; + w = ARRAY_ITEM(&windows, i); + for (j = 0; j < 2; j++) { + if (w != NULL) + wp = w->panes[j]; + if (w == NULL || wp == NULL || wp->fd == -1) { + (*pfd)->fd = -1; + } else { + (*pfd)->fd = wp->fd; + (*pfd)->events = POLLIN; + if (BUFFER_USED(wp->out) > 0) + (*pfd)->events |= POLLOUT; + } + (*pfd)++; } - (*pfd)++; } } @@ -299,17 +306,24 @@ server_fill_windows(struct pollfd **pfd) void server_handle_windows(struct pollfd **pfd) { - struct window *w; - u_int i; + struct window *w; + struct window_pane *wp; + u_int i, j; for (i = 0; i < ARRAY_LENGTH(&windows); i++) { - if ((w = ARRAY_ITEM(&windows, i)) != NULL && w->fd != -1) { - if (buffer_poll(*pfd, w->in, w->out) != 0) - server_lost_window(w); - else - server_handle_window(w); + w = ARRAY_ITEM(&windows, i); + for (j = 0; j < 2; j++) { + if (w != NULL) + wp = w->panes[j]; + if (w != NULL && wp != NULL && wp->fd != -1) { + if (buffer_poll(*pfd, wp->in, wp->out) != 0) { + if (server_lost_window(w, j) != 0) + break; + } else + server_handle_window(w, j); + } + (*pfd)++; } - (*pfd)++; } } @@ -329,7 +343,7 @@ server_check_redraw(struct client *c) c->tty.flags &= ~TTY_FREEZE; if (options_get_number(&s->options, "set-titles")) { - title = s->curw->window->base.title; + title = s->curw->window->active->screen->title; if (c->title == NULL || strcmp(title, c->title) != 0) { if (c->title != NULL) xfree(c->title); @@ -338,16 +352,7 @@ server_check_redraw(struct client *c) } } - if (c->flags & CLIENT_REDRAW) { - if (server_locked) - server_do_redraw_locked(c); - else - server_do_redraw_client(c); - - c->flags |= CLIENT_STATUS; - } - - if (c->flags & CLIENT_STATUS) { + if (c->flags & (CLIENT_REDRAW|CLIENT_STATUS)) { if (c->message_string != NULL) status_message_redraw(c); else if (c->prompt_string != NULL) @@ -356,78 +361,47 @@ server_check_redraw(struct client *c) status_redraw(c); } + if (c->flags & CLIENT_REDRAW) { + if (server_locked) + server_redraw_locked(c); + else + screen_redraw_screen(c, NULL); + } + + if (c->flags & CLIENT_STATUS) + screen_redraw_status(c); + c->tty.flags |= flags; c->flags &= ~(CLIENT_REDRAW|CLIENT_STATUS); } -/* Redraw client normally. */ -void -server_do_redraw_client(struct client *c) -{ - struct session *s = c->session; - struct screen_redraw_ctx ctx; - struct screen screen; - struct grid_cell gc; - u_int xx, yy, sx, sy; - - xx = c->sx; - yy = c->sy - 1; - - sx = screen_size_x(s->curw->window->screen); - sy = screen_size_y(s->curw->window->screen); - - if (sx < xx || sy < yy) { - /* - * Fake up a blank(ish) screen and use it to draw the empty - * regions. NOTE: because this uses tty_write_client but - * doesn't write the client's screen, this can't use anything - * which relies on cursor position. - */ - - screen_init(&screen, xx, yy, 0); - screen_redraw_start(&ctx, &screen, tty_write_client, c); - if (sx < xx) - screen_redraw_columns(&ctx, sx, xx - sx); - if (sy < yy) { - memcpy(&gc, &grid_default_cell, sizeof gc); - gc.data = '-'; - grid_view_fill(screen.grid, &gc, 0, sy, xx, 1); - screen_redraw_lines(&ctx, sy, yy - sy); - } - screen_redraw_stop(&ctx); - screen_free(&screen); - } - - screen_redraw_start_client(&ctx, c); - screen_redraw_lines(&ctx, 0, screen_size_y(ctx.s)); - screen_redraw_stop(&ctx); -} - /* Redraw client when locked. */ void -server_do_redraw_locked(struct client *c) +server_redraw_locked(struct client *c) { - struct session *s = c->session; - struct window *w = s->curw->window; - struct screen_write_ctx ctx; - struct screen screen; - u_int colour, xx, yy; - int style; + struct screen_write_ctx ctx; + struct screen screen; + u_int colour, xx, yy; + int style; xx = c->sx; yy = c->sy - 1; if (xx == 0 || yy == 0) return; - colour = options_get_number(&w->options, "clock-mode-colour"); - style = options_get_number(&w->options, "clock-mode-style"); + colour = options_get_number( + &global_window_options, "clock-mode-colour"); + style = options_get_number( + &global_window_options, "clock-mode-style"); screen_init(&screen, xx, yy, 0); - screen_write_start(&ctx, &screen, tty_write_client, c); + screen_write_start(&ctx, NULL, &screen); clock_draw(&ctx, colour, style); screen_write_stop(&ctx); + screen_redraw_screen(c, &screen); + screen_free(&screen); } @@ -567,6 +541,7 @@ server_accept_client(int srv_fd) c->session = NULL; c->sx = 80; c->sy = 25; + screen_init(&c->status, c->sx, 1, 0); c->message_string = NULL; @@ -588,9 +563,12 @@ server_accept_client(int srv_fd) void server_handle_client(struct client *c) { - struct window *w = c->session->curw->window; - int key, prefix; + struct winlink *wl = c->session->curw; + struct window_pane *wp = wl->window->active; + int key, prefix; + u_int oy; + /* Process keys. */ prefix = options_get_number(&c->session->options, "prefix"); while (tty_keys_next(&c->tty, &key) == 0) { server_activity = time(NULL); @@ -610,8 +588,20 @@ server_handle_client(struct client *c) } else if (key == prefix) c->flags |= CLIENT_PREFIX; else - window_key(w, c, key); + window_pane_key(wp, c, key); } + + /* Ensure the cursor is in the right place and correctly on or off. */ + if (c->prompt_string == NULL && c->message_string == NULL && + !server_locked && wp->screen->mode & MODE_CURSOR) { + oy = 0; + if (wp == wl->window->panes[1]) + oy = wp->window->sy / 2; + + tty_write(&c->tty, wp->screen, 0, TTY_CURSORMODE, 1); + tty_cursor(&c->tty, wp->screen->cx, wp->screen->cy, oy); + } else + tty_write(&c->tty, wp->screen, 0, TTY_CURSORMODE, 0); } /* Lost a client. */ @@ -654,13 +644,14 @@ server_lost_client(struct client *c) /* Handle window data. */ void -server_handle_window(struct window *w) +server_handle_window(struct window *w, int pane) { struct session *s; + struct client *c; u_int i; int action, update; - window_parse(w); + window_pane_parse(w->panes[pane]); if (!(w->flags & WINDOW_BELL) && !(w->flags & WINDOW_ACTIVITY)) return; @@ -678,12 +669,22 @@ server_handle_window(struct window *w) action = options_get_number(&s->options, "bell-action"); switch (action) { case BELL_ANY: - tty_write_session(s, TTY_BELL); + if (s->flags & SESSION_UNATTACHED) + break; + for (i = 0; i < ARRAY_LENGTH(&clients); i++) { + c = ARRAY_ITEM(&clients, i); + if (c != NULL && c->session == s) + tty_putcode(&c->tty, TTYC_BEL); + } break; case BELL_CURRENT: - if (s->curw->window != w) + if (w->active != w->panes[pane]) break; - tty_write_session(s, TTY_BELL); + for (i = 0; i < ARRAY_LENGTH(&clients); i++) { + c = ARRAY_ITEM(&clients, i); + if (c != NULL && c->session == s) + tty_putcode(&c->tty, TTYC_BEL); + } break; } update = 1; @@ -703,20 +704,27 @@ server_handle_window(struct window *w) } /* Lost window: move clients on to next window. */ -void -server_lost_window(struct window *w) +int +server_lost_window(struct window *w, int pane) { - struct client *c; - struct session *s; - struct winlink *wl; - u_int i, j; - int destroyed; + struct client *c; + struct session *s; + struct winlink *wl; + struct window_pane *wp; + u_int i, j; + int destroyed; - log_debug("lost window %d", w->fd); + wp = w->panes[pane]; + log_debug("lost window %d (%s pane %d)", wp->fd, w->name, pane); + + if (window_remove_pane(w, pane) == 0) { + server_redraw_window(w); + return (0); + } if (options_get_number(&w->options, "remain-on-exit")) { - w->fd = -1; - return; + wp->fd = -1; + return (0); } for (i = 0; i < ARRAY_LENGTH(&sessions); i++) { @@ -751,18 +759,20 @@ server_lost_window(struct window *w) } recalculate_sizes(); + return (1); } /* Call any once-per-second timers. */ void server_second_timers(void) { - struct window *w; - u_int i; - int xtimeout; - struct tm now, then; - static time_t last_t = 0; - time_t t; + struct window *w; + struct window_pane *wp; + u_int i, j; + int xtimeout; + struct tm now, then; + static time_t last_t = 0; + time_t t; t = time(NULL); xtimeout = options_get_number(&global_options, "lock-after-time"); @@ -771,8 +781,15 @@ server_second_timers(void) for (i = 0; i < ARRAY_LENGTH(&windows); i++) { w = ARRAY_ITEM(&windows, i); - if (w->mode != NULL && w->mode->timer != NULL) - w->mode->timer(w); + if (w == NULL) + continue; + for (j = 0; j < 2; j++) { + wp = w->panes[j]; + if (wp == NULL) + continue; + if (wp->mode != NULL && wp->mode->timer != NULL) + wp->mode->timer(wp); + } } gmtime_r(&t, &now); diff --git a/status.c b/status.c index 2a8a7efa..6efe6f51 100644 --- a/status.c +++ b/status.c @@ -1,4 +1,4 @@ -/* $Id: status.c,v 1.59 2009-01-11 00:48:42 nicm Exp $ */ +/* $Id: status.c,v 1.60 2009-01-11 23:31:46 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -39,11 +39,12 @@ char *status_prompt_complete(const char *); void status_redraw(struct client *c) { - struct screen_redraw_ctx ctx; + struct screen_write_ctx ctx; struct session *s = c->session; struct winlink *wl; + struct window_pane *wp; char *left, *right, *text, *ptr; - size_t llen, rlen, offset, xx, yy; + size_t llen, rlen, offset, xx, yy, sy; size_t size, start, width; struct grid_cell gc; int larrow, rarrow; @@ -144,22 +145,28 @@ status_redraw(struct client *c) width = xx; draw: + /* Resize the target screen. */ + if (screen_size_x(&c->status) != c->sx) { + screen_free(&c->status); + screen_init(&c->status, c->sx, 1, 0); + } + /* Bail here if anything is too small too. XXX. */ if (width == 0 || xx == 0) goto blank; /* Begin drawing and move to the starting position. */ - screen_redraw_start_client(&ctx, c); + screen_write_start(&ctx, NULL, &c->status); if (llen != 0) { - ctx.write(ctx.data, TTY_CURSORMOVE, 0, yy); - screen_redraw_puts(&ctx, &gc, "%s ", left); + screen_write_cursormove(&ctx, 0, yy); + screen_write_puts(&ctx, &gc, "%s ", left); if (larrow) - screen_redraw_putc(&ctx, &gc, ' '); + screen_write_putc(&ctx, &gc, ' '); } else { if (larrow) - ctx.write(ctx.data, TTY_CURSORMOVE, 1, yy); + screen_write_cursormove(&ctx, 1, yy); else - ctx.write(ctx.data, TTY_CURSORMOVE, 0, yy); + screen_write_cursormove(&ctx, 0, yy); } /* Draw each character in succession. */ @@ -176,7 +183,7 @@ draw: for (ptr = text; *ptr != '\0'; ptr++) { if (offset >= start && offset < start + width) - screen_redraw_putc(&ctx, &gc, *ptr); + screen_write_putc(&ctx, &gc, *ptr); offset++; } @@ -190,7 +197,7 @@ draw: gc.attr &= ~GRID_ATTR_REVERSE; if (offset < start + width) { if (offset >= start) { - screen_redraw_putc(&ctx, &gc, ' '); + screen_write_putc(&ctx, &gc, ' '); } offset++; } @@ -200,12 +207,12 @@ draw: /* Fill the remaining space if any. */ while (offset++ < xx) - screen_redraw_putc(&ctx, &gc, ' '); + screen_write_putc(&ctx, &gc, ' '); /* Draw the last item. */ if (rlen != 0) { - ctx.write(ctx.data, TTY_CURSORMOVE, c->sx - rlen - 1, yy); - screen_redraw_puts(&ctx, &gc, " %s", right); + screen_write_cursormove(&ctx, c->sx - rlen - 1, yy); + screen_write_puts(&ctx, &gc, " %s", right); } /* Draw the arrows. */ @@ -215,10 +222,10 @@ draw: else gc.attr &= ~GRID_ATTR_REVERSE; if (llen != 0) - ctx.write(ctx.data, TTY_CURSORMOVE, llen + 1, yy); + screen_write_cursormove(&ctx, llen + 1, yy); else - ctx.write(ctx.data, TTY_CURSORMOVE, 0, yy); - screen_redraw_putc(&ctx, &gc, '<'); + screen_write_cursormove(&ctx, 0, yy); + screen_write_putc(&ctx, &gc, '<'); gc.attr &= ~GRID_ATTR_REVERSE; } if (rarrow != 0) { @@ -226,12 +233,11 @@ draw: gc.attr |= GRID_ATTR_REVERSE; else gc.attr &= ~GRID_ATTR_REVERSE; - if (rlen != 0) { - ctx.write( - ctx.data, TTY_CURSORMOVE, c->sx - rlen - 2, yy); - } else - ctx.write(ctx.data, TTY_CURSORMOVE, c->sx - 1, yy); - screen_redraw_putc(&ctx, &gc, '>'); + if (rlen != 0) + screen_write_cursormove(&ctx, c->sx - rlen - 2, yy); + else + screen_write_cursormove(&ctx, c->sx - 1, yy); + screen_write_putc(&ctx, &gc, '>'); gc.attr &= ~GRID_ATTR_REVERSE; } @@ -239,10 +245,10 @@ draw: blank: /* Just draw the whole line as blank. */ - screen_redraw_start_client(&ctx, c); - ctx.write(ctx.data, TTY_CURSORMOVE, 0, yy); + screen_write_start(&ctx, NULL, &c->status); + screen_write_cursormove(&ctx, 0, yy); for (offset = 0; offset < c->sx; offset++) - screen_redraw_putc(&ctx, &gc, ' '); + screen_write_putc(&ctx, &gc, ' '); goto out; @@ -251,17 +257,26 @@ off: * Draw the real window last line. Necessary to wipe over message if * status is off. Not sure this is the right place for this. */ - screen_redraw_start_client(&ctx, c); - /* If the screen is too small, use blank. */ - if (screen_size_y(c->session->curw->window->screen) < c->sy) { - ctx.write(ctx.data, TTY_CURSORMOVE, 0, c->sy - 1); + screen_write_start(&ctx, NULL, &c->status); + wp = s->curw->window->panes[1]; + sy = c->sy - (c->sy / 2); + if (wp == NULL) { + wp = s->curw->window->panes[0]; + sy = c->sy; + } + screen_write_cursormove(&ctx, 0, 0); + if (screen_size_y(wp->screen) < sy) { + /* If the screen is too small, use blank. */ for (offset = 0; offset < c->sx; offset++) - screen_redraw_putc(&ctx, &gc, ' '); - } else - screen_redraw_lines(&ctx, c->sy - 1, 1); + screen_write_putc(&ctx, &gc, ' '); + abort(); + } else { + screen_write_copy(&ctx, wp->screen, 0, wp->screen->grid->hsize + + screen_size_y(wp->screen) - 1, c->sx, 1); + } out: - screen_redraw_stop(&ctx); + screen_write_stop(&ctx); if (left != NULL) xfree(left); @@ -272,6 +287,7 @@ out: char * status_replace(struct session *s, char *fmt, time_t t) { + struct winlink *wl = s->curw; static char out[BUFSIZ]; char in[BUFSIZ], ch, *iptr, *optr, *ptr, *endptr; size_t len; @@ -300,7 +316,7 @@ status_replace(struct session *s, char *fmt, time_t t) switch (*iptr++) { case 'T': - ptr = s->curw->window->base.title; + ptr = wl->window->active->base.title; len = strlen(ptr); if ((size_t) n < len) len = n; @@ -333,7 +349,7 @@ status_width(struct winlink *wl) return (xsnprintf(NULL, 0, "%d:%s ", wl->idx, wl->window->name)); #else char *s; - size_t n; + size_t n; xasprintf(&s, "%d:%s ", wl->idx, wl->window->name); n = strlen(s); @@ -372,64 +388,68 @@ status_print(struct session *s, struct winlink *wl, struct grid_cell *gc) void status_message_redraw(struct client *c) { - struct screen_redraw_ctx ctx; + struct screen_write_ctx ctx; struct session *s = c->session; - size_t xx, yy; + size_t len; struct grid_cell gc; if (c->sx == 0 || c->sy == 0) return; + if (screen_size_x(&c->status) != c->sx) { + screen_free(&c->status); + screen_init(&c->status, c->sx, 1, 0); + } - xx = strlen(c->message_string); - if (xx > c->sx) - xx = c->sx; - yy = c->sy - 1; + len = strlen(c->message_string); + if (len > c->sx) + len = c->sx; memcpy(&gc, &grid_default_cell, sizeof gc); gc.fg = options_get_number(&s->options, "message-fg"); gc.bg = options_get_number(&s->options, "message-bg"); - screen_redraw_start_client(&ctx, c); + screen_write_start(&ctx, NULL, &c->status); - ctx.write(ctx.data, TTY_CURSORMOVE, 0, yy); - screen_redraw_puts(&ctx, &gc, "%.*s", (int) xx, c->message_string); - for (; xx < c->sx; xx++) - screen_redraw_putc(&ctx, &gc, ' '); + screen_write_cursormove(&ctx, 0, 0); + screen_write_puts(&ctx, &gc, "%.*s", (int) len, c->message_string); + for (; len < c->sx; len++) + screen_write_putc(&ctx, &gc, ' '); - screen_redraw_stop(&ctx); - - tty_write_client(c, TTY_CURSORMODE, 0); + screen_write_stop(&ctx); } /* Draw client prompt on status line of present else on last line. */ void status_prompt_redraw(struct client *c) { - struct screen_redraw_ctx ctx; + struct screen_write_ctx ctx; struct session *s = c->session; - size_t i, xx, yy, left, size, offset, n; + size_t i, size, left, len, offset, n; char ch; struct grid_cell gc; if (c->sx == 0 || c->sy == 0) return; + if (screen_size_x(&c->status) != c->sx) { + screen_free(&c->status); + screen_init(&c->status, c->sx, 1, 0); + } offset = 0; - xx = strlen(c->prompt_string); - if (xx > c->sx) - xx = c->sx; - yy = c->sy - 1; + len = strlen(c->prompt_string); + if (len > c->sx) + len = c->sx; memcpy(&gc, &grid_default_cell, sizeof gc); gc.fg = options_get_number(&s->options, "message-fg"); gc.bg = options_get_number(&s->options, "message-bg"); - screen_redraw_start_client(&ctx, c); + screen_write_start(&ctx, NULL, &c->status); - ctx.write(ctx.data, TTY_CURSORMOVE, 0, yy); - screen_redraw_puts(&ctx, &gc, "%.*s", (int) xx, c->prompt_string); + screen_write_cursormove(&ctx, 0, 0); + screen_write_puts(&ctx, &gc, "%.*s", (int) len, c->prompt_string); - left = c->sx - xx; + left = c->sx - len; if (left != 0) { if (c->prompt_index < left) size = strlen(c->prompt_buffer); @@ -444,20 +464,18 @@ status_prompt_redraw(struct client *c) if (n > left) n = left; for (i = 0; i < n; i++) - screen_redraw_putc(&ctx, &gc, '*'); + screen_write_putc(&ctx, &gc, '*'); } else { - screen_redraw_puts(&ctx, &gc, + screen_write_puts(&ctx, &gc, "%.*s", (int) left, c->prompt_buffer + offset); } - for (i = xx + size; i < c->sx; i++) { - screen_redraw_putc(&ctx, &gc, ' '); - ctx.s->cx++; - } + for (i = len + size; i < c->sx; i++) + screen_write_putc(&ctx, &gc, ' '); } /* Draw a fake cursor. */ - ctx.write(ctx.data, TTY_CURSORMOVE, xx + c->prompt_index - offset, yy); + screen_write_cursormove(&ctx, len + c->prompt_index - offset, 0); if (c->prompt_index == strlen(c->prompt_buffer)) ch = ' '; else @@ -466,11 +484,9 @@ status_prompt_redraw(struct client *c) ch = ' '; gc.bg = gc.fg; gc.fg = options_get_number(&s->options, "message-bg"); - screen_redraw_putc(&ctx, &gc, ch); + screen_write_putc(&ctx, &gc, ch); - screen_redraw_stop(&ctx); - - tty_write_client(c, TTY_CURSORMODE, 0); + screen_write_stop(&ctx); } /* Handle keys in prompt. */ diff --git a/tmux.h b/tmux.h index 6725ddab..3a0d8b1e 100644 --- a/tmux.h +++ b/tmux.h @@ -1,4 +1,4 @@ -/* $Id: tmux.h,v 1.222 2009-01-11 23:14:57 nicm Exp $ */ +/* $Id: tmux.h,v 1.223 2009-01-11 23:31:46 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -330,8 +330,6 @@ struct tty_term_code_entry { /* Output commands. */ enum tty_cmd { - TTY_BELL, - TTY_CARRIAGERETURN, TTY_CELL, TTY_CLEARENDOFLINE, TTY_CLEARENDOFSCREEN, @@ -339,12 +337,7 @@ enum tty_cmd { TTY_CLEARSCREEN, TTY_CLEARSTARTOFLINE, TTY_CLEARSTARTOFSCREEN, - TTY_CURSORDOWN, - TTY_CURSORLEFT, TTY_CURSORMODE, - TTY_CURSORMOVE, - TTY_CURSORRIGHT, - TTY_CURSORUP, TTY_DELETECHARACTER, TTY_DELETELINE, TTY_INSERTCHARACTER, @@ -355,7 +348,6 @@ enum tty_cmd { TTY_LINEFEED, TTY_MOUSEMODE, TTY_REVERSEINDEX, - TTY_SCROLLREGION, }; /* Message codes. */ @@ -514,17 +506,6 @@ struct screen { struct screen_sel sel; }; -/* Screen redraw context. */ -struct screen_redraw_ctx { - void *data; - void (*write)(void *, enum tty_cmd, ...); - - u_int saved_cx; - u_int saved_cy; - - struct screen *s; -}; - /* Screen write context. */ struct screen_write_ctx { void *data; @@ -547,7 +528,7 @@ struct input_arg { /* Input parser context. */ struct input_ctx { - struct window *w; + struct window_pane *wp; struct screen_write_ctx ctx; u_char *buf; @@ -584,17 +565,19 @@ struct input_ctx { * right function to handle input and output. */ struct client; +struct window; struct window_mode { - struct screen *(*init)(struct window *); - void (*free)(struct window *); - void (*resize)(struct window *, u_int, u_int); - void (*key)(struct window *, struct client *, int); - void (*timer)(struct window *); + struct screen *(*init)(struct window_pane *); + void (*free)(struct window_pane *); + void (*resize)(struct window_pane *, u_int, u_int); + void (*key)(struct window_pane *, struct client *, int); + void (*timer)(struct window_pane *); }; -/* Window structure. */ -struct window { - char *name; +/* Child window structure. */ +struct window_pane { + struct window *window; + char *cmd; char *cwd; @@ -604,18 +587,29 @@ struct window { struct input_ctx ictx; - struct options options; + struct screen *screen; + struct screen base; + + const struct window_mode *mode; + void *modedata; +}; + +/* Window structure. */ +struct window { + char *name; + + struct window_pane *active; + struct window_pane *panes[2]; + + u_int sx; + u_int sy; int flags; #define WINDOW_BELL 0x1 #define WINDOW_HIDDEN 0x2 #define WINDOW_ACTIVITY 0x4 - struct screen *screen; - struct screen base; - - const struct window_mode *mode; - void *modedata; + struct options options; u_int references; }; @@ -698,6 +692,14 @@ SLIST_HEAD(tty_terms, tty_term); struct tty { char *path; + u_int cx; + u_int cy; + + int cursor; + + u_int rlower; + u_int rupper; + char *termname; struct tty_term *term; @@ -742,6 +744,8 @@ struct client { u_int sx; u_int sy; + struct screen status; + #define CLIENT_TERMINAL 0x1 #define CLIENT_PREFIX 0x2 #define CLIENT_MOUSE 0x4 @@ -973,14 +977,21 @@ void options_set_number(struct options *, const char *, long long); long long options_get_number(struct options *, const char *); /* tty.c */ +void tty_cursor(struct tty *, u_int, u_int, u_int); +void tty_putcode(struct tty *, enum tty_code_code); +void tty_putcode1(struct tty *, enum tty_code_code, int); +void tty_putcode2(struct tty *, enum tty_code_code, int, int); +void tty_puts(struct tty *, const char *); +void tty_putc(struct tty *, char); void tty_init(struct tty *, char *, char *); void tty_set_title(struct tty *, const char *); int tty_open(struct tty *, char **); void tty_close(struct tty *); void tty_free(struct tty *); -void tty_write(struct tty *, struct screen *, enum tty_cmd, ...); -void tty_vwrite( - struct tty *, struct screen *s, enum tty_cmd, va_list); +void tty_write(struct tty *, + struct screen *, u_int, enum tty_cmd, ...); +void tty_vwrite(struct tty *, + struct screen *s, u_int, enum tty_cmd, va_list); /* tty-term.c */ extern struct tty_terms tty_terms; @@ -1003,12 +1014,8 @@ void tty_keys_free(struct tty *); int tty_keys_next(struct tty *, int *); /* tty-write.c */ -void tty_write_client(void *, enum tty_cmd, ...); -void tty_vwrite_client(void *, enum tty_cmd, va_list); void tty_write_window(void *, enum tty_cmd, ...); void tty_vwrite_window(void *, enum tty_cmd, va_list); -void tty_write_session(void *, enum tty_cmd, ...); -void tty_vwrite_session(void *, enum tty_cmd, va_list); /* options-cmd.c */ void set_option_string(struct cmd_ctx *, @@ -1102,9 +1109,11 @@ extern const struct cmd_entry cmd_show_buffer_entry; extern const struct cmd_entry cmd_show_options_entry; extern const struct cmd_entry cmd_show_window_options_entry; extern const struct cmd_entry cmd_source_file_entry; +extern const struct cmd_entry cmd_split_window_entry; extern const struct cmd_entry cmd_start_server_entry; extern const struct cmd_entry cmd_swap_window_entry; extern const struct cmd_entry cmd_switch_client_entry; +extern const struct cmd_entry cmd_switch_pane_entry; extern const struct cmd_entry cmd_unbind_key_entry; extern const struct cmd_entry cmd_unlink_window_entry; @@ -1200,12 +1209,13 @@ void server_set_client_prompt(struct client *, void server_clear_client_prompt(struct client *); struct session *server_extract_session( struct msg_command_data *, char *, char **); +void server_write(struct client *, enum hdrtype, const void *, size_t); void server_write_client( struct client *, enum hdrtype, const void *, size_t); void server_write_session( struct session *, enum hdrtype, const void *, size_t); void server_write_window( - struct window *, enum hdrtype, const void *, size_t); + struct window *, enum hdrtype, const void *, size_t); void server_redraw_client(struct client *); void server_status_client(struct client *); void server_redraw_session(struct session *); @@ -1225,12 +1235,12 @@ void status_prompt_key(struct client *, int); void recalculate_sizes(void); /* input.c */ -void input_init(struct window *); -void input_free(struct window *); -void input_parse(struct window *); +void input_init(struct window_pane *); +void input_free(struct window_pane *); +void input_parse(struct window_pane *); /* input-key.c */ -void input_key(struct window *, int); +void input_key(struct window_pane *, int); /* colour.c */ const char *colour_tostring(u_char); @@ -1278,12 +1288,8 @@ void grid_view_insert_cells(struct grid_data *, u_int, u_int, u_int); void grid_view_delete_cells(struct grid_data *, 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 *, enum tty_cmd, ...), void *); +void screen_write_start( + struct screen_write_ctx *, struct window_pane *, struct screen *); void screen_write_stop(struct screen_write_ctx *); void printflike3 screen_write_puts( struct screen_write_ctx *, struct grid_cell *, const char *, ...); @@ -1318,20 +1324,8 @@ void screen_write_clearscreen(struct screen_write_ctx *); void screen_write_cell(struct screen_write_ctx *, const struct grid_cell *); /* 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 *, enum tty_cmd, ...), void *); -void screen_redraw_stop(struct screen_redraw_ctx *); -void printflike3 screen_redraw_puts( - struct screen_redraw_ctx *, struct grid_cell *, const char *, ...); -void screen_redraw_putc( - struct screen_redraw_ctx *, struct grid_cell *, u_char); -void screen_redraw_cell(struct screen_redraw_ctx *, u_int, u_int); -void screen_redraw_lines(struct screen_redraw_ctx *, u_int, u_int); -void screen_redraw_columns(struct screen_redraw_ctx *, u_int, u_int); +void screen_redraw_screen(struct client *, struct screen *); +void screen_redraw_status(struct client *); /* screen.c */ void screen_init(struct screen *, u_int, u_int, u_int); @@ -1364,14 +1358,19 @@ void winlink_stack_push(struct winlink_stack *, struct winlink *); void winlink_stack_remove(struct winlink_stack *, struct winlink *); struct window *window_create(const char *, const char *, const char *, const char **, u_int, u_int, u_int); -int window_spawn(struct window *, - const char *, const char *, const char **); void window_destroy(struct window *); int window_resize(struct window *, u_int, u_int); -int window_set_mode(struct window *, const struct window_mode *); -void window_reset_mode(struct window *); -void window_parse(struct window *); -void window_key(struct window *, struct client *, int); +int window_remove_pane(struct window *, int); +struct window_pane *window_pane_create(struct window *, u_int, u_int, u_int); +void window_pane_destroy(struct window_pane *); +int window_pane_spawn(struct window_pane *, + const char *, const char *, const char **); +int window_pane_resize(struct window_pane *, u_int, u_int); +int window_pane_set_mode( + struct window_pane *, const struct window_mode *); +void window_pane_reset_mode(struct window_pane *); +void window_pane_parse(struct window_pane *); +void window_pane_key(struct window_pane *, struct client *, int); /* window-clock.c */ extern const struct window_mode window_clock_mode; @@ -1384,8 +1383,8 @@ extern const struct window_mode window_scroll_mode; /* window-more.c */ extern const struct window_mode window_more_mode; -void window_more_vadd(struct window *, const char *, va_list); -void printflike2 window_more_add(struct window *, const char *, ...); +void window_more_vadd(struct window_pane *, const char *, va_list); +void printflike2 window_more_add(struct window_pane *, const char *, ...); /* session.c */ extern struct sessions sessions; @@ -1399,7 +1398,7 @@ struct session *session_create( void session_destroy(struct session *); int session_index(struct session *, u_int *); struct winlink *session_new(struct session *, - const char *, const char *, const char *, int); + const char *, const char *, const char *, int); struct winlink *session_attach(struct session *, struct window *, int); int session_detach(struct session *, struct winlink *); int session_has(struct session *, struct window *); diff --git a/tty-write.c b/tty-write.c index a8d22c0b..7151f895 100644 --- a/tty-write.c +++ b/tty-write.c @@ -1,4 +1,4 @@ -/* $Id: tty-write.c,v 1.3 2009-01-09 23:57:42 nicm Exp $ */ +/* $Id: tty-write.c,v 1.4 2009-01-11 23:31:46 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -20,26 +20,6 @@ #include "tmux.h" -void -tty_write_client(void *ptr, enum tty_cmd cmd, ...) -{ - struct client *c = ptr; - va_list ap; - - va_start(ap, cmd); - tty_vwrite_client(c, cmd, ap); - va_end(ap); -} - -void -tty_vwrite_client(void *ptr, enum tty_cmd cmd, va_list ap) -{ - struct client *c = ptr; - struct screen *s = c->session->curw->window->screen; - - tty_vwrite(&c->tty, s, cmd, ap); -} - void tty_write_window(void *ptr, enum tty_cmd cmd, ...) { @@ -53,55 +33,28 @@ tty_write_window(void *ptr, enum tty_cmd cmd, ...) void tty_vwrite_window(void *ptr, enum tty_cmd cmd, va_list ap) { - struct window *w = ptr; - struct client *c; - va_list aq; - u_int i; + struct window_pane *wp = ptr; + struct client *c; + va_list aq; + u_int i, oy; - if (w->flags & WINDOW_HIDDEN) + if (wp->window->flags & WINDOW_HIDDEN) return; for (i = 0; i < ARRAY_LENGTH(&clients); i++) { c = ARRAY_ITEM(&clients, i); if (c == NULL || c->session == NULL) continue; - if (c->session->curw->window != w) - continue; - va_copy(aq, ap); - tty_vwrite_client(c, cmd, aq); - va_end(aq); - } -} - -void -tty_write_session(void *ptr, enum tty_cmd cmd, ...) -{ - va_list ap; - - va_start(ap, cmd); - tty_vwrite_session(ptr, cmd, ap); - va_end(ap); -} - -void -tty_vwrite_session(void *ptr, enum tty_cmd cmd, va_list ap) -{ - struct session *s = ptr; - struct client *c; - va_list aq; - u_int i; - - if (s->flags & SESSION_UNATTACHED) - return; - - for (i = 0; i < ARRAY_LENGTH(&clients); i++) { - c = ARRAY_ITEM(&clients, i); - if (c == NULL || c->session != s) - continue; - - va_copy(aq, ap); - tty_vwrite_client(c, cmd, aq); - va_end(aq); + if (c->session->curw->window == wp->window) { + if (wp == wp->window->panes[0]) + oy = 0; + else + oy = wp->window->sy / 2; + + va_copy(aq, ap); + tty_vwrite(&c->tty, wp->screen, oy, cmd, aq); + va_end(aq); + } } } diff --git a/tty.c b/tty.c index c3ae5b5c..79f7a616 100644 --- a/tty.c +++ b/tty.c @@ -1,4 +1,4 @@ -/* $Id: tty.c,v 1.57 2009-01-10 22:28:40 nicm Exp $ */ +/* $Id: tty.c,v 1.58 2009-01-11 23:31:46 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -34,47 +34,35 @@ void tty_emulate_repeat( struct tty *, enum tty_code_code, enum tty_code_code, u_int); void tty_raw(struct tty *, const char *); -void tty_putcode(struct tty *, enum tty_code_code); -void tty_putcode1(struct tty *, enum tty_code_code, int); -void tty_putcode2(struct tty *, enum tty_code_code, int, int); -void tty_puts(struct tty *, const char *); -void tty_putc(struct tty *, char); void tty_reset(struct tty *); +void tty_region(struct tty *, struct screen *, u_int); void tty_attributes(struct tty *, const struct grid_cell *); void tty_attributes_fg(struct tty *, const struct grid_cell *); void tty_attributes_bg(struct tty *, const struct grid_cell *); -void tty_cmd_bell(struct tty *, struct screen *, va_list); -void tty_cmd_carriagereturn(struct tty *, struct screen *, va_list); -void tty_cmd_cell(struct tty *, struct screen *, va_list); -void tty_cmd_clearendofline(struct tty *, struct screen *, va_list); -void tty_cmd_clearendofscreen(struct tty *, struct screen *, va_list); -void tty_cmd_clearline(struct tty *, struct screen *, va_list); -void tty_cmd_clearscreen(struct tty *, struct screen *, va_list); -void tty_cmd_clearstartofline(struct tty *, struct screen *, va_list); -void tty_cmd_clearstartofscreen(struct tty *, struct screen *, va_list); -void tty_cmd_cursordown(struct tty *, struct screen *, va_list); -void tty_cmd_cursorleft(struct tty *, struct screen *, va_list); -void tty_cmd_cursormode(struct tty *, struct screen *, va_list); -void tty_cmd_cursormove(struct tty *, struct screen *, va_list); -void tty_cmd_cursorright(struct tty *, struct screen *, va_list); -void tty_cmd_cursorup(struct tty *, struct screen *, va_list); -void tty_cmd_deletecharacter(struct tty *, struct screen *, va_list); -void tty_cmd_deleteline(struct tty *, struct screen *, va_list); -void tty_cmd_insertcharacter(struct tty *, struct screen *, va_list); -void tty_cmd_insertline(struct tty *, struct screen *, va_list); -void tty_cmd_insertmode(struct tty *, struct screen *, va_list); -void tty_cmd_kcursormode(struct tty *, struct screen *, va_list); -void tty_cmd_kkeypadmode(struct tty *, struct screen *, va_list); -void tty_cmd_linefeed(struct tty *, struct screen *, va_list); -void tty_cmd_mousemode(struct tty *, struct screen *, va_list); -void tty_cmd_reverseindex(struct tty *, struct screen *, va_list); -void tty_cmd_scrollregion(struct tty *, struct screen *, va_list); +void tty_cmd_bell(struct tty *, struct screen *, u_int, va_list); +void tty_cmd_carriagereturn(struct tty *, struct screen *, u_int, va_list); +void tty_cmd_cell(struct tty *, struct screen *, u_int, va_list); +void tty_cmd_clearendofline(struct tty *, struct screen *, u_int, va_list); +void tty_cmd_clearendofscreen(struct tty *, struct screen *, u_int, va_list); +void tty_cmd_clearline(struct tty *, struct screen *, u_int, va_list); +void tty_cmd_clearscreen(struct tty *, struct screen *, u_int, va_list); +void tty_cmd_clearstartofline(struct tty *, struct screen *, u_int, va_list); +void tty_cmd_clearstartofscreen(struct tty *, struct screen *, u_int, va_list); +void tty_cmd_cursormode(struct tty *, struct screen *, u_int, va_list); +void tty_cmd_deletecharacter(struct tty *, struct screen *, u_int, va_list); +void tty_cmd_deleteline(struct tty *, struct screen *, u_int, va_list); +void tty_cmd_insertcharacter(struct tty *, struct screen *, u_int, va_list); +void tty_cmd_insertline(struct tty *, struct screen *, u_int, va_list); +void tty_cmd_insertmode(struct tty *, struct screen *, u_int, va_list); +void tty_cmd_kcursormode(struct tty *, struct screen *, u_int, va_list); +void tty_cmd_kkeypadmode(struct tty *, struct screen *, u_int, va_list); +void tty_cmd_linefeed(struct tty *, struct screen *, u_int, va_list); +void tty_cmd_mousemode(struct tty *, struct screen *, u_int, va_list); +void tty_cmd_reverseindex(struct tty *, struct screen *, u_int, va_list); -void (*tty_cmds[])(struct tty *, struct screen *, va_list) = { - tty_cmd_bell, - tty_cmd_carriagereturn, +void (*tty_cmds[])(struct tty *, struct screen *, u_int, va_list) = { tty_cmd_cell, tty_cmd_clearendofline, tty_cmd_clearendofscreen, @@ -82,12 +70,7 @@ void (*tty_cmds[])(struct tty *, struct screen *, va_list) = { tty_cmd_clearscreen, tty_cmd_clearstartofline, tty_cmd_clearstartofscreen, - tty_cmd_cursordown, - tty_cmd_cursorleft, tty_cmd_cursormode, - tty_cmd_cursormove, - tty_cmd_cursorright, - tty_cmd_cursorup, tty_cmd_deletecharacter, tty_cmd_deleteline, tty_cmd_insertcharacter, @@ -98,7 +81,6 @@ void (*tty_cmds[])(struct tty *, struct screen *, va_list) = { tty_cmd_linefeed, tty_cmd_mousemode, tty_cmd_reverseindex, - tty_cmd_scrollregion, }; void @@ -138,6 +120,9 @@ tty_open(struct tty *tty, char **cause) else tty->log_fd = -1; + tty->cx = UINT_MAX; + tty->cy = UINT_MAX; + if ((tty->term = tty_term_find(tty->termname, tty->fd, cause)) == NULL) goto error; @@ -314,6 +299,8 @@ tty_putc(struct tty *tty, char ch) ch = tty_get_acs(tty, ch); buffer_write8(tty->out, ch); + tty->cx++; /* This is right most of the time. */ + if (tty->log_fd != -1) write(tty->log_fd, &ch, 1); } @@ -344,72 +331,35 @@ tty_emulate_repeat( } void -tty_write(struct tty *tty, struct screen *s, enum tty_cmd cmd, ...) +tty_write(struct tty *tty, struct screen *s, u_int oy, enum tty_cmd cmd, ...) { va_list ap; va_start(ap, cmd); - tty_vwrite(tty, s, cmd, ap); + tty_vwrite(tty, s, oy, cmd, ap); va_end(ap); } void -tty_vwrite(struct tty *tty, struct screen *s, enum tty_cmd cmd, va_list ap) +tty_vwrite( + struct tty *tty, struct screen *s, u_int oy, enum tty_cmd cmd, va_list ap) { if (tty->flags & TTY_FREEZE || tty->term == NULL) return; if (tty_cmds[cmd] != NULL) - tty_cmds[cmd](tty, s, ap); + tty_cmds[cmd](tty, s, oy, ap); } void -tty_cmd_cursorup(struct tty *tty, unused struct screen *s, va_list ap) -{ - u_int ua; - - ua = va_arg(ap, u_int); - - tty_emulate_repeat(tty, TTYC_CUU, TTYC_CUU1, ua); -} - -void -tty_cmd_cursordown(struct tty *tty, unused struct screen *s, va_list ap) -{ - u_int ua; - - ua = va_arg(ap, u_int); - - tty_emulate_repeat(tty, TTYC_CUD, TTYC_CUD1, ua); -} - -void -tty_cmd_cursorright(struct tty *tty, unused struct screen *s, va_list ap) -{ - u_int ua; - - ua = va_arg(ap, u_int); - - tty_emulate_repeat(tty, TTYC_CUF, TTYC_CUF1, ua); -} - -void -tty_cmd_cursorleft(struct tty *tty, unused struct screen *s, va_list ap) -{ - u_int ua; - - ua = va_arg(ap, u_int); - - tty_emulate_repeat(tty, TTYC_CUB, TTYC_CUB1, ua); -} - -void -tty_cmd_insertcharacter(struct tty *tty, unused struct screen *s, va_list ap) +tty_cmd_insertcharacter( + struct tty *tty, unused struct screen *s, u_int oy, va_list ap) { u_int ua; ua = va_arg(ap, u_int); tty_reset(tty); + tty_cursor(tty, s->cx, s->cy, oy); if (tty_term_has(tty->term, TTYC_ICH) || tty_term_has(tty->term, TTYC_ICH1)) @@ -419,117 +369,125 @@ tty_cmd_insertcharacter(struct tty *tty, unused struct screen *s, va_list ap) while (ua-- > 0) tty_putc(tty, ' '); tty_putcode(tty, TTYC_RMIR); - tty_putcode2(tty, TTYC_CUP, s->cy, s->cx); + tty_putcode2(tty, TTYC_CUP, oy + s->cy, s->cx); } } void -tty_cmd_deletecharacter(struct tty *tty, unused struct screen *s, va_list ap) +tty_cmd_deletecharacter( + struct tty *tty, unused struct screen *s, u_int oy, va_list ap) { u_int ua; ua = va_arg(ap, u_int); tty_reset(tty); + tty_cursor(tty, s->cx, s->cy, oy); tty_emulate_repeat(tty, TTYC_DCH, TTYC_DCH1, ua); } void -tty_cmd_insertline(struct tty *tty, unused struct screen *s, va_list ap) +tty_cmd_insertline( + struct tty *tty, unused struct screen *s, u_int oy, va_list ap) { u_int ua; ua = va_arg(ap, u_int); tty_reset(tty); + tty_region(tty, s, oy); + tty_cursor(tty, s->cx, s->cy, oy); tty_emulate_repeat(tty, TTYC_IL, TTYC_IL1, ua); } void -tty_cmd_deleteline(struct tty *tty, unused struct screen *s, va_list ap) +tty_cmd_deleteline( + struct tty *tty, unused struct screen *s, u_int oy, va_list ap) { u_int ua; ua = va_arg(ap, u_int); tty_reset(tty); + tty_region(tty, s, oy); + tty_cursor(tty, s->cx, s->cy, oy); tty_emulate_repeat(tty, TTYC_DL, TTYC_DL1, ua); } void -tty_cmd_clearline(struct tty *tty, struct screen *s, unused va_list ap) +tty_cmd_clearline( + struct tty *tty, struct screen *s, u_int oy, unused va_list ap) { u_int i; tty_reset(tty); + tty_cursor(tty, s->cx, s->cy, oy); if (tty_term_has(tty->term, TTYC_EL)) { - tty_putcode2(tty, TTYC_CUP, s->cy, 0); + tty_putcode2(tty, TTYC_CUP, oy + s->cy, 0); tty_putcode(tty, TTYC_EL); - tty_putcode2(tty, TTYC_CUP, s->cy, s->cx); + tty_putcode2(tty, TTYC_CUP, oy + s->cy, s->cx); } else { - tty_putcode2(tty, TTYC_CUP, s->cy, 0); + tty_putcode2(tty, TTYC_CUP, oy + s->cy, 0); for (i = 0; i < screen_size_x(s); i++) tty_putc(tty, ' '); - tty_putcode2(tty, TTYC_CUP, s->cy, s->cx); + tty_putcode2(tty, TTYC_CUP, oy + s->cy, s->cx); } } void -tty_cmd_clearendofline(struct tty *tty, struct screen *s, unused va_list ap) +tty_cmd_clearendofline( + struct tty *tty, struct screen *s, u_int oy, unused va_list ap) { u_int i; tty_reset(tty); + tty_cursor(tty, s->cx, s->cy, oy); if (tty_term_has(tty->term, TTYC_EL)) tty_putcode(tty, TTYC_EL); else { - tty_putcode2(tty, TTYC_CUP, s->cy, s->cx); + tty_putcode2(tty, TTYC_CUP, oy + s->cy, s->cx); for (i = s->cx; i < screen_size_x(s); i++) tty_putc(tty, ' '); - tty_putcode2(tty, TTYC_CUP, s->cy, s->cx); + tty_putcode2(tty, TTYC_CUP, oy + s->cy, s->cx); } } void -tty_cmd_clearstartofline(struct tty *tty, struct screen *s, unused va_list ap) +tty_cmd_clearstartofline( + struct tty *tty, struct screen *s, u_int oy, unused va_list ap) { u_int i; tty_reset(tty); + tty_cursor(tty, s->cx, s->cy, oy); if (tty_term_has(tty->term, TTYC_EL1)) tty_putcode(tty, TTYC_EL1); else { - tty_putcode2(tty, TTYC_CUP, s->cy, 0); + tty_putcode2(tty, TTYC_CUP, oy + s->cy, 0); for (i = 0; i < s->cx + 1; i++) tty_putc(tty, ' '); - tty_putcode2(tty, TTYC_CUP, s->cy, s->cx); + tty_putcode2(tty, TTYC_CUP, oy + s->cy, s->cx); } } void -tty_cmd_cursormove(struct tty *tty, unused struct screen *s, va_list ap) +tty_cmd_cursormode( + struct tty *tty, unused struct screen *s, unused u_int oy, va_list ap) { - u_int ua, ub; - - ua = va_arg(ap, u_int); - ub = va_arg(ap, u_int); - - tty_putcode2(tty, TTYC_CUP, ub, ua); -} - -void -tty_cmd_cursormode(struct tty *tty, unused struct screen *s, va_list ap) -{ - u_int ua; + int ua; ua = va_arg(ap, int); + if (tty->cursor == ua) + return; + tty->cursor = ua; + if (ua && !(tty->flags & TTY_NOCURSOR)) tty_putcode(tty, TTYC_CNORM); else @@ -538,28 +496,21 @@ tty_cmd_cursormode(struct tty *tty, unused struct screen *s, va_list ap) void tty_cmd_reverseindex( - struct tty *tty, unused struct screen *s, unused va_list ap) + struct tty *tty, struct screen *s, u_int oy, unused va_list ap) { tty_reset(tty); + tty_region(tty, s, oy); + tty_cursor(tty, s->cx, s->cy, oy); tty_putcode(tty, TTYC_RI); + } void -tty_cmd_scrollregion(struct tty *tty, unused struct screen *s, va_list ap) +tty_cmd_insertmode(unused struct tty *tty, + unused struct screen *s, unused u_int oy, va_list ap) { - u_int ua, ub; - - ua = va_arg(ap, u_int); - ub = va_arg(ap, u_int); - - tty_putcode2(tty, TTYC_CSR, ua, ub); -} - -void -tty_cmd_insertmode(unused struct tty *tty, unused struct screen *s, va_list ap) -{ - u_int ua; + int ua; ua = va_arg(ap, int); @@ -573,9 +524,10 @@ tty_cmd_insertmode(unused struct tty *tty, unused struct screen *s, va_list ap) } void -tty_cmd_mousemode(struct tty *tty, unused struct screen *s, va_list ap) +tty_cmd_mousemode( + struct tty *tty, unused struct screen *s, unused u_int oy, va_list ap) { - u_int ua; + int ua; if (!tty_term_has(tty->term, TTYC_KMOUS)) return; @@ -589,52 +541,45 @@ tty_cmd_mousemode(struct tty *tty, unused struct screen *s, va_list ap) } void -tty_cmd_kcursormode( - unused struct tty *tty, unused struct screen *s, unused va_list ap) +tty_cmd_kcursormode(unused struct tty *tty, + unused struct screen *s, unused u_int oy, unused va_list ap) { } void -tty_cmd_kkeypadmode( - unused struct tty *tty, unused struct screen *s, unused va_list ap) +tty_cmd_kkeypadmode(unused struct tty *tty, + unused struct screen *s, unused u_int oy, unused va_list ap) { } void -tty_cmd_linefeed(struct tty *tty, unused struct screen *s, unused va_list ap) +tty_cmd_linefeed(struct tty *tty, struct screen *s, u_int oy, unused va_list ap) { tty_reset(tty); + tty_region(tty, s, oy); + tty_cursor(tty, s->cx, s->cy, oy); tty_putc(tty, '\n'); } void -tty_cmd_carriagereturn( - struct tty *tty, unused struct screen *s, unused va_list ap) -{ - tty_reset(tty); - - if (tty_term_has(tty->term, TTYC_CR)) - tty_putcode(tty, TTYC_CR); - else - tty_putc(tty, '\r'); -} - -void -tty_cmd_bell(struct tty *tty, unused struct screen *s, unused va_list ap) +tty_cmd_bell(struct tty *tty, + unused struct screen *s, unused u_int oy, unused va_list ap) { tty_putcode(tty, TTYC_BEL); } void -tty_cmd_clearendofscreen(struct tty *tty, struct screen *s, unused va_list ap) +tty_cmd_clearendofscreen( + struct tty *tty, struct screen *s, u_int oy, unused va_list ap) { u_int i, j; tty_reset(tty); + tty_cursor(tty, s->cx, s->cy, oy); if (tty_term_has(tty->term, TTYC_EL)) { - for (i = s->cy; i < screen_size_y(s); i++) { + for (i = oy + s->cy; i < oy + screen_size_y(s); i++) { tty_putcode(tty, TTYC_EL); if (i != screen_size_y(s) - 1) tty_emulate_repeat(tty, TTYC_CUD, TTYC_CUD1, 1); @@ -642,47 +587,51 @@ tty_cmd_clearendofscreen(struct tty *tty, struct screen *s, unused va_list ap) } else { for (i = s->cx; i < screen_size_y(s); i++) tty_putc(tty, ' '); - for (j = s->cy; j < screen_size_y(s); j++) { + for (j = oy + s->cy; j < oy + screen_size_y(s); j++) { for (i = 0; i < screen_size_x(s); i++) tty_putc(tty, ' '); } } - tty_putcode2(tty, TTYC_CUP, s->cy, s->cx); + tty_putcode2(tty, TTYC_CUP, oy + s->cy, s->cx); } void -tty_cmd_clearstartofscreen(struct tty *tty, struct screen *s, unused va_list ap) +tty_cmd_clearstartofscreen( + struct tty *tty, struct screen *s, u_int oy, unused va_list ap) { u_int i, j; tty_reset(tty); + tty_cursor(tty, s->cx, s->cy, oy); - tty_putcode2(tty, TTYC_CUP, 0, 0); + tty_putcode2(tty, TTYC_CUP, oy, 0); if (tty_term_has(tty->term, TTYC_EL)) { - for (i = 0; i < s->cy; i++) { + for (i = 0; i < oy + s->cy; i++) { tty_putcode(tty, TTYC_EL); tty_emulate_repeat(tty, TTYC_CUD, TTYC_CUD1, 1); } - tty_putcode2(tty, TTYC_CUP, s->cy, 0); + tty_putcode2(tty, TTYC_CUP, oy + s->cy, 0); } else { - for (j = 0; j < s->cy; j++) { + for (j = 0; j < oy + s->cy; j++) { for (i = 0; i < screen_size_x(s); i++) tty_putc(tty, ' '); } } for (i = 0; i < s->cx; i++) tty_putc(tty, ' '); - tty_putcode2(tty, TTYC_CUP, s->cy, s->cx); + tty_putcode2(tty, TTYC_CUP, oy + s->cy, s->cx); } void -tty_cmd_clearscreen(struct tty *tty, struct screen *s, unused va_list ap) +tty_cmd_clearscreen( + struct tty *tty, struct screen *s, u_int oy, unused va_list ap) { u_int i, j; tty_reset(tty); + tty_cursor(tty, s->cx, s->cy, oy); - tty_putcode2(tty, TTYC_CUP, 0, 0); + tty_putcode2(tty, TTYC_CUP, oy, 0); if (tty_term_has(tty->term, TTYC_EL)) { for (i = 0; i < screen_size_y(s); i++) { tty_putcode(tty, TTYC_EL); @@ -695,16 +644,18 @@ tty_cmd_clearscreen(struct tty *tty, struct screen *s, unused va_list ap) tty_putc(tty, ' '); } } - tty_putcode2(tty, TTYC_CUP, s->cy, s->cx); + tty_putcode2(tty, TTYC_CUP, oy + s->cy, s->cx); } void -tty_cmd_cell(struct tty *tty, unused struct screen *s, va_list ap) +tty_cmd_cell(struct tty *tty, struct screen *s, u_int oy, va_list ap) { struct grid_cell *gc; u_int i, width; u_char out[4]; + tty_cursor(tty, s->cx, s->cy, oy); + gc = va_arg(ap, struct grid_cell *); /* If this is a padding character, do nothing. */ @@ -756,6 +707,28 @@ tty_reset(struct tty *tty) memcpy(tc, &grid_default_cell, sizeof *tc); } +void +tty_region(struct tty *tty, struct screen *s, u_int oy) +{ + if (tty->rlower != oy + s->rlower || tty->rupper != oy + s->rupper) { + tty->rlower = oy + s->rlower; + tty->rupper = oy + s->rupper; + tty->cx = 0; + tty->cy = 0; + tty_putcode2(tty, TTYC_CSR, tty->rupper, tty->rlower); + } +} + +void +tty_cursor(struct tty *tty, u_int cx, u_int cy, u_int oy) +{ + if (tty->cx != cx || tty->cy != oy + cy) { + tty->cx = cx; + tty->cy = oy + cy; + tty_putcode2(tty, TTYC_CUP, tty->cy, tty->cx); + } +} + void tty_attributes(struct tty *tty, const struct grid_cell *gc) { diff --git a/window-clock.c b/window-clock.c index 0462142d..84435396 100644 --- a/window-clock.c +++ b/window-clock.c @@ -1,4 +1,4 @@ -/* $Id: window-clock.c,v 1.3 2009-01-11 00:48:42 nicm Exp $ */ +/* $Id: window-clock.c,v 1.4 2009-01-11 23:31:46 nicm Exp $ */ /* * Copyright (c) 2009 Nicholas Marriott @@ -23,13 +23,13 @@ #include "tmux.h" -struct screen *window_clock_init(struct window *); -void window_clock_free(struct window *); -void window_clock_resize(struct window *, u_int, u_int); -void window_clock_key(struct window *, struct client *, int); -void window_clock_timer(struct window *); +struct screen *window_clock_init(struct window_pane *); +void window_clock_free(struct window_pane *); +void window_clock_resize(struct window_pane *, u_int, u_int); +void window_clock_key(struct window_pane *, struct client *, int); +void window_clock_timer(struct window_pane *); -void window_clock_draw_screen(struct window *); +void window_clock_draw_screen(struct window_pane *); const struct window_mode window_clock_mode = { window_clock_init, @@ -45,52 +45,53 @@ struct window_clock_mode_data { }; struct screen * -window_clock_init(struct window *w) +window_clock_init(struct window_pane *wp) { struct window_clock_mode_data *data; struct screen *s; - w->modedata = data = xmalloc(sizeof *data); + wp->modedata = data = xmalloc(sizeof *data); data->tim = time(NULL); s = &data->screen; - screen_init(s, screen_size_x(&w->base), screen_size_y(&w->base), 0); + screen_init(s, screen_size_x(&wp->base), screen_size_y(&wp->base), 0); s->mode &= ~MODE_CURSOR; - window_clock_draw_screen(w); + window_clock_draw_screen(wp); return (s); } void -window_clock_free(struct window *w) +window_clock_free(struct window_pane *wp) { - struct window_clock_mode_data *data = w->modedata; + struct window_clock_mode_data *data = wp->modedata; screen_free(&data->screen); xfree(data); } void -window_clock_resize(struct window *w, u_int sx, u_int sy) +window_clock_resize(struct window_pane *wp, u_int sx, u_int sy) { - struct window_clock_mode_data *data = w->modedata; + struct window_clock_mode_data *data = wp->modedata; struct screen *s = &data->screen; screen_resize(s, sx, sy); - window_clock_draw_screen(w); + window_clock_draw_screen(wp); } void -window_clock_key(struct window *w, unused struct client *c, unused int key) +window_clock_key( + struct window_pane *wp, unused struct client *c, unused int key) { - window_reset_mode(w); + window_pane_reset_mode(wp); } void -window_clock_timer(struct window *w) +window_clock_timer(struct window_pane *wp) { - struct window_clock_mode_data *data = w->modedata; + struct window_clock_mode_data *data = wp->modedata; struct tm *now, *then; time_t t; @@ -101,22 +102,22 @@ window_clock_timer(struct window *w) return; data->tim = t; - window_clock_draw_screen(w); - server_redraw_window(w); + window_clock_draw_screen(wp); + server_redraw_window(wp->window); } void -window_clock_draw_screen(struct window *w) +window_clock_draw_screen(struct window_pane *wp) { - struct window_clock_mode_data *data = w->modedata; + struct window_clock_mode_data *data = wp->modedata; struct screen_write_ctx ctx; u_int colour; int style; - colour = options_get_number(&w->options, "clock-mode-colour"); - style = options_get_number(&w->options, "clock-mode-style"); + colour = options_get_number(&wp->window->options, "clock-mode-colour"); + style = options_get_number(&wp->window->options, "clock-mode-style"); - screen_write_start(&ctx, &data->screen, NULL, NULL); + screen_write_start(&ctx, NULL, &data->screen); clock_draw(&ctx, colour, style); screen_write_stop(&ctx); } diff --git a/window-copy.c b/window-copy.c index c23ca07e..bdafbce2 100644 --- a/window-copy.c +++ b/window-copy.c @@ -1,4 +1,4 @@ -/* $Id: window-copy.c,v 1.37 2009-01-10 19:35:40 nicm Exp $ */ +/* $Id: window-copy.c,v 1.38 2009-01-11 23:31:46 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -22,42 +22,42 @@ #include "tmux.h" -struct screen *window_copy_init(struct window *); -void window_copy_free(struct window *); -void window_copy_resize(struct window *, u_int, u_int); -void window_copy_key(struct window *, struct client *, int); +struct screen *window_copy_init(struct window_pane *); +void window_copy_free(struct window_pane *); +void window_copy_resize(struct window_pane *, u_int, u_int); +void window_copy_key(struct window_pane *, struct client *, int); -void window_copy_redraw_lines(struct window *, u_int, u_int); -void window_copy_redraw_screen(struct window *); +void window_copy_redraw_lines(struct window_pane *, u_int, u_int); +void window_copy_redraw_screen(struct window_pane *); void window_copy_write_line( - struct window *, struct screen_write_ctx *, u_int); + struct window_pane *, struct screen_write_ctx *, u_int); void window_copy_write_lines( - struct window *, struct screen_write_ctx *, u_int, u_int); + struct window_pane *, struct screen_write_ctx *, u_int, u_int); void window_copy_write_column( - struct window *, struct screen_write_ctx *, u_int); + struct window_pane *, struct screen_write_ctx *, u_int); void window_copy_write_columns( - struct window *, struct screen_write_ctx *, u_int, u_int); + struct window_pane *, 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 *, struct client *); +void window_copy_update_cursor(struct window_pane *); +void window_copy_start_selection(struct window_pane *); +int window_copy_update_selection(struct window_pane *); +void window_copy_copy_selection(struct window_pane *, struct client *); void window_copy_copy_line( - struct window *, char **, size_t *, u_int, u_int, u_int); -int window_copy_is_space(struct window *, u_int, u_int); -u_int window_copy_find_length(struct window *, u_int); -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_cursor_next_word(struct window *); -void window_copy_cursor_previous_word(struct window *); -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); -void window_copy_scroll_down(struct window *, u_int); + struct window_pane *, char **, size_t *, u_int, u_int, u_int); +int window_copy_is_space(struct window_pane *, u_int, u_int); +u_int window_copy_find_length(struct window_pane *, u_int); +void window_copy_cursor_start_of_line(struct window_pane *); +void window_copy_cursor_end_of_line(struct window_pane *); +void window_copy_cursor_left(struct window_pane *); +void window_copy_cursor_right(struct window_pane *); +void window_copy_cursor_up(struct window_pane *); +void window_copy_cursor_down(struct window_pane *); +void window_copy_cursor_next_word(struct window_pane *); +void window_copy_cursor_previous_word(struct window_pane *); +void window_copy_scroll_left(struct window_pane *, u_int); +void window_copy_scroll_right(struct window_pane *, u_int); +void window_copy_scroll_up(struct window_pane *, u_int); +void window_copy_scroll_down(struct window_pane *, u_int); const struct window_mode window_copy_mode = { window_copy_init, @@ -81,27 +81,27 @@ struct window_copy_mode_data { }; struct screen * -window_copy_init(struct window *w) +window_copy_init(struct window_pane *wp) { struct window_copy_mode_data *data; struct screen *s; struct screen_write_ctx ctx; u_int i; - w->modedata = data = xmalloc(sizeof *data); + wp->modedata = data = xmalloc(sizeof *data); data->ox = 0; data->oy = 0; - data->cx = w->base.cx; - data->cy = w->base.cy; + data->cx = wp->base.cx; + data->cy = wp->base.cy; s = &data->screen; - screen_init(s, screen_size_x(&w->base), screen_size_y(&w->base), 0); + screen_init(s, screen_size_x(&wp->base), screen_size_y(&wp->base), 0); s->cx = data->cx; s->cy = data->cy; - screen_write_start(&ctx, s, NULL, NULL); + screen_write_start(&ctx, NULL, s); for (i = 0; i < screen_size_y(s); i++) - window_copy_write_line(w, &ctx, i); + window_copy_write_line(wp, &ctx, i); screen_write_cursormove(&ctx, data->cx, data->cy); screen_write_stop(&ctx); @@ -109,92 +109,92 @@ window_copy_init(struct window *w) } void -window_copy_free(struct window *w) +window_copy_free(struct window_pane *wp) { - struct window_copy_mode_data *data = w->modedata; + struct window_copy_mode_data *data = wp->modedata; screen_free(&data->screen); xfree(data); } void -window_copy_resize(struct window *w, u_int sx, u_int sy) +window_copy_resize(struct window_pane *wp, u_int sx, u_int sy) { - struct window_copy_mode_data *data = w->modedata; + struct window_copy_mode_data *data = wp->modedata; struct screen *s = &data->screen; struct screen_write_ctx ctx; screen_resize(s, sx, sy); - screen_write_start(&ctx, s, NULL, NULL); - window_copy_write_lines(w, &ctx, 0, screen_size_y(s) - 1); + screen_write_start(&ctx, NULL, s); + window_copy_write_lines(wp, &ctx, 0, screen_size_y(s) - 1); screen_write_stop(&ctx); - window_copy_update_selection(w); + window_copy_update_selection(wp); } void -window_copy_key(struct window *w, struct client *c, int key) +window_copy_key(struct window_pane *wp, struct client *c, int key) { - struct window_copy_mode_data *data = w->modedata; + struct window_copy_mode_data *data = wp->modedata; struct screen *s = &data->screen; int table; - table = options_get_number(&w->options, "mode-keys"); + table = options_get_number(&wp->window->options, "mode-keys"); switch (mode_key_lookup(table, key)) { case MODEKEY_QUIT: - window_reset_mode(w); + window_pane_reset_mode(wp); break; case MODEKEY_LEFT: - window_copy_cursor_left(w); + window_copy_cursor_left(wp); return; case MODEKEY_RIGHT: - window_copy_cursor_right(w); + window_copy_cursor_right(wp); return; case MODEKEY_UP: - window_copy_cursor_up(w); + window_copy_cursor_up(wp); return; case MODEKEY_DOWN: - window_copy_cursor_down(w); + window_copy_cursor_down(wp); return; case MODEKEY_PPAGE: - if (data->oy + screen_size_y(s) > screen_hsize(&w->base)) - data->oy = screen_hsize(&w->base); + if (data->oy + screen_size_y(s) > screen_hsize(&wp->base)) + data->oy = screen_hsize(&wp->base); else data->oy += screen_size_y(s); - window_copy_update_selection(w); - window_copy_redraw_screen(w); + window_copy_update_selection(wp); + window_copy_redraw_screen(wp); break; case MODEKEY_NPAGE: if (data->oy < screen_size_y(s)) data->oy = 0; else data->oy -= screen_size_y(s); - window_copy_update_selection(w); - window_copy_redraw_screen(w); + window_copy_update_selection(wp); + window_copy_redraw_screen(wp); break; case MODEKEY_STARTSEL: - window_copy_start_selection(w); + window_copy_start_selection(wp); break; case MODEKEY_CLEARSEL: screen_clear_selection(&data->screen); - window_copy_redraw_screen(w); + window_copy_redraw_screen(wp); break; case MODEKEY_COPYSEL: if (c != NULL && c->session != NULL) { - window_copy_copy_selection(w, c); - window_reset_mode(w); + window_copy_copy_selection(wp, c); + window_pane_reset_mode(wp); } break; case MODEKEY_BOL: - window_copy_cursor_start_of_line(w); + window_copy_cursor_start_of_line(wp); break; case MODEKEY_EOL: - window_copy_cursor_end_of_line(w); + window_copy_cursor_end_of_line(wp); break; case MODEKEY_NWORD: - window_copy_cursor_next_word(w); + window_copy_cursor_next_word(wp); break; case MODEKEY_PWORD: - window_copy_cursor_previous_word(w); + window_copy_cursor_previous_word(wp); break; default: break; @@ -202,9 +202,9 @@ window_copy_key(struct window *w, struct client *c, int key) } void -window_copy_write_line(struct window *w, struct screen_write_ctx *ctx, u_int py) +window_copy_write_line(struct window_pane *wp, struct screen_write_ctx *ctx, u_int py) { - struct window_copy_mode_data *data = w->modedata; + struct window_copy_mode_data *data = wp->modedata; struct screen *s = &data->screen; struct grid_cell gc; char hdr[32]; @@ -213,9 +213,9 @@ window_copy_write_line(struct window *w, struct screen_write_ctx *ctx, u_int py) if (py == 0) { memcpy(&gc, &grid_default_cell, sizeof gc); size = xsnprintf(hdr, sizeof hdr, - "[%u,%u/%u]", data->ox, data->oy, screen_hsize(&w->base)); - gc.fg = options_get_number(&w->options, "mode-fg"); - gc.bg = options_get_number(&w->options, "mode-bg"); + "[%u,%u/%u]", data->ox, data->oy, screen_hsize(&wp->base)); + gc.fg = options_get_number(&wp->window->options, "mode-fg"); + gc.bg = options_get_number(&wp->window->options, "mode-bg"); screen_write_cursormove(ctx, screen_size_x(s) - size, 0); screen_write_puts(ctx, &gc, "%s", hdr); screen_write_puts(ctx, &gc, "%s", hdr); @@ -223,92 +223,92 @@ window_copy_write_line(struct window *w, struct screen_write_ctx *ctx, u_int py) size = 0; screen_write_cursormove(ctx, 0, py); - screen_write_copy(ctx, &w->base, data->ox, (screen_hsize(&w->base) - + screen_write_copy(ctx, &wp->base, data->ox, (screen_hsize(&wp->base) - data->oy) + py, screen_size_x(s) - size, 1); } void window_copy_write_lines( - struct window *w, struct screen_write_ctx *ctx, u_int py, u_int ny) + struct window_pane *wp, struct screen_write_ctx *ctx, u_int py, u_int ny) { u_int yy; for (yy = py; yy < py + ny; yy++) - window_copy_write_line(w, ctx, py); + window_copy_write_line(wp, ctx, py); } void window_copy_write_column( - struct window *w, struct screen_write_ctx *ctx, u_int px) + struct window_pane *wp, struct screen_write_ctx *ctx, u_int px) { - struct window_copy_mode_data *data = w->modedata; + struct window_copy_mode_data *data = wp->modedata; struct screen *s = &data->screen; screen_write_cursormove(ctx, px, 0); - screen_write_copy(ctx, &w->base, - data->ox, screen_hsize(&w->base) - data->oy, 1, screen_size_y(s)); + screen_write_copy(ctx, &wp->base, + data->ox, screen_hsize(&wp->base) - data->oy, 1, screen_size_y(s)); } void window_copy_write_columns( - struct window *w, struct screen_write_ctx *ctx, u_int px, u_int nx) + struct window_pane *wp, struct screen_write_ctx *ctx, u_int px, u_int nx) { u_int xx; for (xx = px; xx < px + nx; xx++) - window_copy_write_column(w, ctx, px); + window_copy_write_column(wp, ctx, px); } void -window_copy_redraw_lines(struct window *w, u_int py, u_int ny) +window_copy_redraw_lines(struct window_pane *wp, u_int py, u_int ny) { - struct window_copy_mode_data *data = w->modedata; + struct window_copy_mode_data *data = wp->modedata; struct screen_write_ctx ctx; u_int i; - screen_write_start_window(&ctx, w); + screen_write_start(&ctx, wp, NULL); for (i = py; i < py + ny; i++) - window_copy_write_line(w, &ctx, i); + window_copy_write_line(wp, &ctx, i); screen_write_cursormove(&ctx, data->cx, data->cy); screen_write_stop(&ctx); } void -window_copy_redraw_screen(struct window *w) +window_copy_redraw_screen(struct window_pane *wp) { - struct window_copy_mode_data *data = w->modedata; + struct window_copy_mode_data *data = wp->modedata; - window_copy_redraw_lines(w, 0, screen_size_y(&data->screen)); + window_copy_redraw_lines(wp, 0, screen_size_y(&data->screen)); } void -window_copy_update_cursor(struct window *w) +window_copy_update_cursor(struct window_pane *wp) { - struct window_copy_mode_data *data = w->modedata; + struct window_copy_mode_data *data = wp->modedata; struct screen_write_ctx ctx; - screen_write_start_window(&ctx, w); + screen_write_start(&ctx, wp, NULL); screen_write_cursormove(&ctx, data->cx, data->cy); screen_write_stop(&ctx); } void -window_copy_start_selection(struct window *w) +window_copy_start_selection(struct window_pane *wp) { - struct window_copy_mode_data *data = w->modedata; + struct window_copy_mode_data *data = wp->modedata; struct screen *s = &data->screen; data->selx = data->cx + data->ox; - data->sely = screen_hsize(&w->base) + data->cy - data->oy; + data->sely = screen_hsize(&wp->base) + data->cy - data->oy; s->sel.flag = 1; - window_copy_update_selection(w); + window_copy_update_selection(wp); } int -window_copy_update_selection(struct window *w) +window_copy_update_selection(struct window_pane *wp) { - struct window_copy_mode_data *data = w->modedata; + struct window_copy_mode_data *data = wp->modedata; struct screen *s = &data->screen; struct grid_cell gc; u_int sx, sy, tx, ty; @@ -318,12 +318,12 @@ window_copy_update_selection(struct window *w) /* Set colours. */ memcpy(&gc, &grid_default_cell, sizeof gc); - gc.fg = options_get_number(&w->options, "mode-fg"); - gc.bg = options_get_number(&w->options, "mode-bg"); + gc.fg = options_get_number(&wp->window->options, "mode-fg"); + gc.bg = options_get_number(&wp->window->options, "mode-bg"); /* Find top-left of screen. */ tx = data->ox; - ty = screen_hsize(&w->base) - data->oy; + ty = screen_hsize(&wp->base) - data->oy; /* Adjust the selection. */ sx = data->selx; @@ -357,9 +357,9 @@ window_copy_update_selection(struct window *w) } void -window_copy_copy_selection(struct window *w, struct client *c) +window_copy_copy_selection(struct window_pane *wp, struct client *c) { - struct window_copy_mode_data *data = w->modedata; + struct window_copy_mode_data *data = wp->modedata; struct screen *s = &data->screen; char *buf; size_t off; @@ -380,7 +380,7 @@ window_copy_copy_selection(struct window *w, struct client *c) /* Find start and end. */ xx = data->cx + data->ox; - yy = screen_hsize(&w->base) + data->cy - data->oy; + yy = screen_hsize(&wp->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; @@ -390,23 +390,23 @@ window_copy_copy_selection(struct window *w, struct client *c) } /* Trim ex to end of line. */ - xx = window_copy_find_length(w, ey); + xx = window_copy_find_length(wp, ey); if (ex > xx) ex = xx; /* Copy the lines. */ if (sy == ey) - window_copy_copy_line(w, &buf, &off, sy, sx, ex); + window_copy_copy_line(wp, &buf, &off, sy, sx, ex); else { - xx = window_copy_find_length(w, sy); - window_copy_copy_line(w, &buf, &off, sy, sx, xx); + xx = window_copy_find_length(wp, sy); + window_copy_copy_line(wp, &buf, &off, sy, sx, xx); if (ey - sy > 1) { for (i = sy + 1; i < ey - 1; i++) { - xx = window_copy_find_length(w, i); - window_copy_copy_line(w, &buf, &off, i, 0, xx); + xx = window_copy_find_length(wp, i); + window_copy_copy_line(wp, &buf, &off, i, 0, xx); } } - window_copy_copy_line(w, &buf, &off, ey, 0, ex); + window_copy_copy_line(wp, &buf, &off, ey, 0, ex); } /* Terminate buffer, overwriting final \n. */ @@ -421,7 +421,7 @@ window_copy_copy_selection(struct window *w, struct client *c) void window_copy_copy_line( - struct window *w, char **buf, size_t *off, u_int sy, u_int sx, u_int ex) + struct window_pane *wp, char **buf, size_t *off, u_int sy, u_int sx, u_int ex) { const struct grid_cell *gc; u_char i, j, xx, data[4]; @@ -429,7 +429,7 @@ window_copy_copy_line( if (sx > ex) return; - xx = window_copy_find_length(w, sy); + xx = window_copy_find_length(wp, sy); if (ex > xx) ex = xx; if (sx > xx) @@ -437,7 +437,7 @@ window_copy_copy_line( if (sx < ex) { for (i = sx; i < ex; i++) { - gc = grid_peek_cell(w->base.grid, i, sy); + gc = grid_peek_cell(wp->base.grid, i, sy); utf8_split(gc->data, data); *buf = xrealloc(*buf, 1, (*off) + 4); @@ -455,12 +455,12 @@ window_copy_copy_line( } int -window_copy_is_space(struct window *w, u_int px, u_int py) +window_copy_is_space(struct window_pane *wp, u_int px, u_int py) { const struct grid_cell *gc; const char *spaces = " -_@"; - gc = grid_peek_cell(w->base.grid, px, py); + gc = grid_peek_cell(wp->base.grid, px, py); if (gc->flags & GRID_FLAG_PADDING) return (0); if (gc->data == 0x00 || gc->data > 0xff) @@ -469,14 +469,14 @@ window_copy_is_space(struct window *w, u_int px, u_int py) } u_int -window_copy_find_length(struct window *w, u_int py) +window_copy_find_length(struct window_pane *wp, u_int py) { const struct grid_cell *gc; u_int px; - px = w->base.grid->size[py]; + px = wp->base.grid->size[py]; while (px > 0) { - gc = grid_peek_cell(w->base.grid, px - 1, py); + gc = grid_peek_cell(wp->base.grid, px - 1, py); if (gc->data != 0x20) break; px--; @@ -485,29 +485,29 @@ window_copy_find_length(struct window *w, u_int py) } void -window_copy_cursor_start_of_line(struct window *w) +window_copy_cursor_start_of_line(struct window_pane *wp) { - struct window_copy_mode_data *data = w->modedata; + struct window_copy_mode_data *data = wp->modedata; if (data->ox != 0) - window_copy_scroll_right(w, data->ox); + window_copy_scroll_right(wp, data->ox); data->cx = 0; - if (window_copy_update_selection(w)) - window_copy_redraw_lines(w, data->cy, 1); + if (window_copy_update_selection(wp)) + window_copy_redraw_lines(wp, data->cy, 1); else - window_copy_update_cursor(w); + window_copy_update_cursor(wp); } void -window_copy_cursor_end_of_line(struct window *w) +window_copy_cursor_end_of_line(struct window_pane *wp) { - struct window_copy_mode_data *data = w->modedata; + struct window_copy_mode_data *data = wp->modedata; struct screen *s = &data->screen; u_int px, py; - py = screen_hsize(&w->base) + data->cy - data->oy; - px = window_copy_find_length(w, py); + py = screen_hsize(&wp->base) + data->cy - data->oy; + px = window_copy_find_length(wp, py); /* On screen. */ if (px > data->ox && px <= data->ox + screen_size_x(s) - 1) @@ -517,7 +517,7 @@ window_copy_cursor_end_of_line(struct window *w) if (px > data->ox + screen_size_x(s) - 1) { /* Move cursor to last and scroll screen. */ window_copy_scroll_left( - w, px - data->ox - (screen_size_x(s) - 1)); + wp, px - data->ox - (screen_size_x(s) - 1)); data->cx = screen_size_x(s) - 1; } @@ -525,132 +525,132 @@ window_copy_cursor_end_of_line(struct window *w) if (px <= data->ox) { if (px < screen_size_x(s) - 1) { /* Short enough to fit on screen. */ - window_copy_scroll_right(w, data->ox); + window_copy_scroll_right(wp, data->ox); data->cx = px; } else { /* Too long to fit on screen. */ window_copy_scroll_right( - w, data->ox - (px - (screen_size_x(s) - 1))); + wp, data->ox - (px - (screen_size_x(s) - 1))); data->cx = screen_size_x(s) - 1; } } - if (window_copy_update_selection(w)) - window_copy_redraw_lines(w, data->cy, 1); + if (window_copy_update_selection(wp)) + window_copy_redraw_lines(wp, data->cy, 1); else - window_copy_update_cursor(w); + window_copy_update_cursor(wp); } void -window_copy_cursor_left(struct window *w) +window_copy_cursor_left(struct window_pane *wp) { - struct window_copy_mode_data *data = w->modedata; + struct window_copy_mode_data *data = wp->modedata; if (data->cx == 0) { if (data->ox > 0) - window_copy_scroll_right(w, 1); + window_copy_scroll_right(wp, 1); else { - window_copy_cursor_up(w); - window_copy_cursor_end_of_line(w); + window_copy_cursor_up(wp); + window_copy_cursor_end_of_line(wp); } } else { data->cx--; - if (window_copy_update_selection(w)) - window_copy_redraw_lines(w, data->cy, 1); + if (window_copy_update_selection(wp)) + window_copy_redraw_lines(wp, data->cy, 1); else - window_copy_update_cursor(w); + window_copy_update_cursor(wp); } } void -window_copy_cursor_right(struct window *w) +window_copy_cursor_right(struct window_pane *wp) { - struct window_copy_mode_data *data = w->modedata; + struct window_copy_mode_data *data = wp->modedata; u_int px, py; - py = screen_hsize(&w->base) + data->cy - data->oy; - px = window_copy_find_length(w, py); + py = screen_hsize(&wp->base) + data->cy - data->oy; + px = window_copy_find_length(wp, py); if (data->cx >= px) { - window_copy_cursor_start_of_line(w); - window_copy_cursor_down(w); + window_copy_cursor_start_of_line(wp); + window_copy_cursor_down(wp); } else { data->cx++; - if (window_copy_update_selection(w)) - window_copy_redraw_lines(w, data->cy, 1); + if (window_copy_update_selection(wp)) + window_copy_redraw_lines(wp, data->cy, 1); else - window_copy_update_cursor(w); + window_copy_update_cursor(wp); } } void -window_copy_cursor_up(struct window *w) +window_copy_cursor_up(struct window_pane *wp) { - struct window_copy_mode_data *data = w->modedata; + struct window_copy_mode_data *data = wp->modedata; u_int ox, oy, px, py; - oy = screen_hsize(&w->base) + data->cy - data->oy; - ox = window_copy_find_length(w, oy); + oy = screen_hsize(&wp->base) + data->cy - data->oy; + ox = window_copy_find_length(wp, oy); if (data->cy == 0) - window_copy_scroll_down(w, 1); + window_copy_scroll_down(wp, 1); else { data->cy--; - if (window_copy_update_selection(w)) - window_copy_redraw_lines(w, data->cy, 2); + if (window_copy_update_selection(wp)) + window_copy_redraw_lines(wp, data->cy, 2); else - window_copy_update_cursor(w); + window_copy_update_cursor(wp); } - py = screen_hsize(&w->base) + data->cy - data->oy; - px = window_copy_find_length(w, py); + py = screen_hsize(&wp->base) + data->cy - data->oy; + px = window_copy_find_length(wp, py); if (data->cx + data->ox >= px || data->cx + data->ox >= ox) - window_copy_cursor_end_of_line(w); + window_copy_cursor_end_of_line(wp); } void -window_copy_cursor_down(struct window *w) +window_copy_cursor_down(struct window_pane *wp) { - struct window_copy_mode_data *data = w->modedata; + struct window_copy_mode_data *data = wp->modedata; struct screen *s = &data->screen; u_int ox, oy, px, py; - oy = screen_hsize(&w->base) + data->cy - data->oy; - ox = window_copy_find_length(w, oy); + oy = screen_hsize(&wp->base) + data->cy - data->oy; + ox = window_copy_find_length(wp, oy); if (data->cy == screen_size_y(s) - 1) - window_copy_scroll_up(w, 1); + window_copy_scroll_up(wp, 1); else { data->cy++; - if (window_copy_update_selection(w)) - window_copy_redraw_lines(w, data->cy - 1, 2); + if (window_copy_update_selection(wp)) + window_copy_redraw_lines(wp, data->cy - 1, 2); else - window_copy_update_cursor(w); + window_copy_update_cursor(wp); } - py = screen_hsize(&w->base) + data->cy - data->oy; - px = window_copy_find_length(w, py); + py = screen_hsize(&wp->base) + data->cy - data->oy; + px = window_copy_find_length(wp, py); if (data->cx + data->ox >= px || data->cx + data->ox >= ox) - window_copy_cursor_end_of_line(w); + window_copy_cursor_end_of_line(wp); } void -window_copy_cursor_next_word(struct window *w) +window_copy_cursor_next_word(struct window_pane *wp) { - struct window_copy_mode_data *data = w->modedata; + struct window_copy_mode_data *data = wp->modedata; struct screen *s = &data->screen; u_int px, py, xx, skip; px = data->ox + data->cx; - py = screen_hsize(&w->base) + data->cy - data->oy; - xx = window_copy_find_length(w, py); + py = screen_hsize(&wp->base) + data->cy - data->oy; + xx = window_copy_find_length(wp, py); skip = 1; if (px < xx) { /* If currently on a space, skip space. */ - if (window_copy_is_space(w, px, py)) + if (window_copy_is_space(wp, px, py)) skip = 0; } else skip = 0; @@ -668,21 +668,21 @@ window_copy_cursor_next_word(struct window *w) } px = 0; - window_copy_cursor_down(w); + window_copy_cursor_down(wp); py =screen_hsize( - &w->base) + data->cy - data->oy; - xx = window_copy_find_length(w, py); + &wp->base) + data->cy - data->oy; + xx = window_copy_find_length(wp, py); } } if (skip) { /* Currently skipping non-space (until space). */ - if (window_copy_is_space(w, px, py)) + if (window_copy_is_space(wp, px, py)) break; } else { /* Currently skipping space (until non-space). */ - if (!window_copy_is_space(w, px, py)) + if (!window_copy_is_space(wp, px, py)) skip = 1; } @@ -698,7 +698,7 @@ out: if (px > data->ox + screen_size_x(s) - 1) { /* Move cursor to last and scroll screen. */ window_copy_scroll_left( - w, px - data->ox - (screen_size_x(s) - 1)); + wp, px - data->ox - (screen_size_x(s) - 1)); data->cx = screen_size_x(s) - 1; } @@ -706,36 +706,36 @@ out: if (px <= data->ox) { if (px < screen_size_x(s) - 1) { /* Short enough to fit on screen. */ - window_copy_scroll_right(w, data->ox); + window_copy_scroll_right(wp, data->ox); data->cx = px; } else { /* Too long to fit on screen. */ window_copy_scroll_right( - w, data->ox - (px - (screen_size_x(s) - 1))); + wp, data->ox - (px - (screen_size_x(s) - 1))); data->cx = screen_size_x(s) - 1; } } - if (window_copy_update_selection(w)) - window_copy_redraw_lines(w, data->cy, 1); + if (window_copy_update_selection(wp)) + window_copy_redraw_lines(wp, data->cy, 1); else - window_copy_update_cursor(w); + window_copy_update_cursor(wp); } void -window_copy_cursor_previous_word(struct window *w) +window_copy_cursor_previous_word(struct window_pane *wp) { - struct window_copy_mode_data *data = w->modedata; + struct window_copy_mode_data *data = wp->modedata; struct screen *s = &data->screen; u_int ox, px, py, skip; ox = px = data->ox + data->cx; - py = screen_hsize(&w->base) + data->cy - data->oy; + py = screen_hsize(&wp->base) + data->cy - data->oy; skip = 1; if (px != 0) { /* If currently on a space, skip space. */ - if (window_copy_is_space(w, px - 1, py)) + if (window_copy_is_space(wp, px - 1, py)) skip = 0; } for (;;) { @@ -745,26 +745,26 @@ window_copy_cursor_previous_word(struct window *w) while (px == 0) { if (data->cy == 0 && - (screen_hsize(&w->base) == 0 || - data->oy >= screen_hsize(&w->base) - 1)) + (screen_hsize(&wp->base) == 0 || + data->oy >= screen_hsize(&wp->base) - 1)) goto out; - window_copy_cursor_up(w); + window_copy_cursor_up(wp); py = screen_hsize( - &w->base) + data->cy - data->oy; - px = window_copy_find_length(w, py); + &wp->base) + data->cy - data->oy; + px = window_copy_find_length(wp, py); } goto out; } if (skip) { /* Currently skipping non-space (until space). */ - if (window_copy_is_space(w, px - 1, py)) + if (window_copy_is_space(wp, px - 1, py)) skip = 0; } else { /* Currently skipping space (until non-space). */ - if (!window_copy_is_space(w, px - 1, py)) + if (!window_copy_is_space(wp, px - 1, py)) break; } @@ -780,7 +780,7 @@ out: if (px > data->ox + screen_size_x(s) - 1) { /* Move cursor to last and scroll screen. */ window_copy_scroll_left( - w, px - data->ox - (screen_size_x(s) - 1)); + wp, px - data->ox - (screen_size_x(s) - 1)); data->cx = screen_size_x(s) - 1; } @@ -788,26 +788,26 @@ out: if (px <= data->ox) { if (px < screen_size_x(s) - 1) { /* Short enough to fit on screen. */ - window_copy_scroll_right(w, data->ox); + window_copy_scroll_right(wp, data->ox); data->cx = px; } else { /* Too long to fit on screen. */ window_copy_scroll_right( - w, data->ox - (px - (screen_size_x(s) - 1))); + wp, data->ox - (px - (screen_size_x(s) - 1))); data->cx = screen_size_x(s) - 1; } } - if (window_copy_update_selection(w)) - window_copy_redraw_lines(w, data->cy, 1); + if (window_copy_update_selection(wp)) + window_copy_redraw_lines(wp, data->cy, 1); else - window_copy_update_cursor(w); + window_copy_update_cursor(wp); } void -window_copy_scroll_left(struct window *w, u_int nx) +window_copy_scroll_left(struct window_pane *wp, u_int nx) { - struct window_copy_mode_data *data = w->modedata; + struct window_copy_mode_data *data = wp->modedata; struct screen *s = &data->screen; struct screen_write_ctx ctx; u_int i; @@ -817,27 +817,27 @@ window_copy_scroll_left(struct window *w, u_int nx) if (nx == 0) return; data->ox += nx; - window_copy_update_selection(w); + window_copy_update_selection(wp); - screen_write_start_window(&ctx, w); + screen_write_start(&ctx, wp, NULL); for (i = 1; i < screen_size_y(s); i++) { screen_write_cursormove(&ctx, 0, i); screen_write_deletecharacter(&ctx, nx); } - window_copy_write_columns(w, &ctx, screen_size_x(s) - nx, nx); - window_copy_write_line(w, &ctx, 0); + window_copy_write_columns(wp, &ctx, screen_size_x(s) - nx, nx); + window_copy_write_line(wp, &ctx, 0); if (s->sel.flag) { - window_copy_update_selection(w); - window_copy_write_lines(w, &ctx, data->cy, 1); + window_copy_update_selection(wp); + window_copy_write_lines(wp, &ctx, data->cy, 1); } screen_write_cursormove(&ctx, data->cx, data->cy); screen_write_stop(&ctx); } void -window_copy_scroll_right(struct window *w, u_int nx) +window_copy_scroll_right(struct window_pane *wp, u_int nx) { - struct window_copy_mode_data *data = w->modedata; + struct window_copy_mode_data *data = wp->modedata; struct screen *s = &data->screen; struct screen_write_ctx ctx; u_int i; @@ -847,25 +847,25 @@ window_copy_scroll_right(struct window *w, u_int nx) if (nx == 0) return; data->ox -= nx; - window_copy_update_selection(w); + window_copy_update_selection(wp); - screen_write_start_window(&ctx, w); + screen_write_start(&ctx, wp, NULL); for (i = 1; i < screen_size_y(s); i++) { screen_write_cursormove(&ctx, 0, i); screen_write_insertcharacter(&ctx, nx); } - window_copy_write_columns(w, &ctx, 0, nx); - window_copy_write_line(w, &ctx, 0); + window_copy_write_columns(wp, &ctx, 0, nx); + window_copy_write_line(wp, &ctx, 0); if (s->sel.flag) - window_copy_write_line(w, &ctx, data->cy); + window_copy_write_line(wp, &ctx, data->cy); screen_write_cursormove(&ctx, data->cx, data->cy); screen_write_stop(&ctx); } void -window_copy_scroll_up(struct window *w, u_int ny) +window_copy_scroll_up(struct window_pane *wp, u_int ny) { - struct window_copy_mode_data *data = w->modedata; + struct window_copy_mode_data *data = wp->modedata; struct screen *s = &data->screen; struct screen_write_ctx ctx; @@ -874,45 +874,45 @@ window_copy_scroll_up(struct window *w, u_int ny) if (ny == 0) return; data->oy -= ny; - window_copy_update_selection(w); + window_copy_update_selection(wp); - screen_write_start_window(&ctx, w); + screen_write_start(&ctx, wp, NULL); screen_write_cursormove(&ctx, 0, 0); screen_write_deleteline(&ctx, ny); - window_copy_write_lines(w, &ctx, screen_size_y(s) - ny, ny); - window_copy_write_line(w, &ctx, 0); - window_copy_write_line(w, &ctx, 1); + window_copy_write_lines(wp, &ctx, screen_size_y(s) - ny, ny); + window_copy_write_line(wp, &ctx, 0); + window_copy_write_line(wp, &ctx, 1); if (s->sel.flag && screen_size_y(s) > ny) - window_copy_write_line(w, &ctx, screen_size_y(s) - ny - 1); + window_copy_write_line(wp, &ctx, screen_size_y(s) - ny - 1); screen_write_cursormove(&ctx, data->cx, data->cy); screen_write_stop(&ctx); } void -window_copy_scroll_down(struct window *w, u_int ny) +window_copy_scroll_down(struct window_pane *wp, u_int ny) { - struct window_copy_mode_data *data = w->modedata; + struct window_copy_mode_data *data = wp->modedata; struct screen *s = &data->screen; struct screen_write_ctx ctx; - if (ny > screen_hsize(&w->base)) + if (ny > screen_hsize(&wp->base)) return; - if (data->oy > screen_hsize(&w->base) - ny) - ny = screen_hsize(&w->base) - data->oy; + if (data->oy > screen_hsize(&wp->base) - ny) + ny = screen_hsize(&wp->base) - data->oy; if (ny == 0) return; data->oy += ny; - window_copy_update_selection(w); + window_copy_update_selection(wp); - screen_write_start_window(&ctx, w); + screen_write_start(&ctx, wp, NULL); screen_write_cursormove(&ctx, 0, 0); screen_write_insertline(&ctx, ny); - window_copy_write_lines(w, &ctx, 0, ny); + window_copy_write_lines(wp, &ctx, 0, ny); if (s->sel.flag && screen_size_y(s) > ny) - window_copy_write_line(w, &ctx, ny); + window_copy_write_line(wp, &ctx, ny); else if (ny == 1) /* nuke position */ - window_copy_write_line(w, &ctx, 1); + window_copy_write_line(wp, &ctx, 1); screen_write_cursormove(&ctx, data->cx, data->cy); screen_write_stop(&ctx); } diff --git a/window-more.c b/window-more.c index 25eeca4b..7a586386 100644 --- a/window-more.c +++ b/window-more.c @@ -1,4 +1,4 @@ -/* $Id: window-more.c,v 1.23 2009-01-10 19:35:40 nicm Exp $ */ +/* $Id: window-more.c,v 1.24 2009-01-11 23:31:46 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -22,17 +22,17 @@ #include "tmux.h" -struct screen *window_more_init(struct window *); -void window_more_free(struct window *); -void window_more_resize(struct window *, u_int, u_int); -void window_more_key(struct window *, struct client *, int); +struct screen *window_more_init(struct window_pane *); +void window_more_free(struct window_pane *); +void window_more_resize(struct window_pane *, u_int, u_int); +void window_more_key(struct window_pane *, struct client *, int); -void window_more_redraw_screen(struct window *); +void window_more_redraw_screen(struct window_pane *); void window_more_write_line( - struct window *, struct screen_write_ctx *, u_int); + struct window_pane *, struct screen_write_ctx *, u_int); -void window_more_scroll_up(struct window *); -void window_more_scroll_down(struct window *); +void window_more_scroll_up(struct window_pane *); +void window_more_scroll_down(struct window_pane *); const struct window_mode window_more_mode = { window_more_init, @@ -50,9 +50,9 @@ struct window_more_mode_data { }; void -window_more_vadd(struct window *w, const char *fmt, va_list ap) +window_more_vadd(struct window_pane *wp, const char *fmt, va_list ap) { - struct window_more_mode_data *data = w->modedata; + struct window_more_mode_data *data = wp->modedata; struct screen *s = &data->screen; struct screen_write_ctx ctx; char *msg; @@ -61,48 +61,48 @@ window_more_vadd(struct window *w, const char *fmt, va_list ap) xvasprintf(&msg, fmt, ap); ARRAY_ADD(&data->list, msg); - screen_write_start_window(&ctx, w); + screen_write_start(&ctx, wp, NULL); size = ARRAY_LENGTH(&data->list) - 1; if (size >= data->top && size <= data->top + screen_size_y(s) - 1) { - window_more_write_line(w, &ctx, size - data->top); + window_more_write_line(wp, &ctx, size - data->top); if (size != data->top) - window_more_write_line(w, &ctx, 0); + window_more_write_line(wp, &ctx, 0); } else - window_more_write_line(w, &ctx, 0); + window_more_write_line(wp, &ctx, 0); screen_write_stop(&ctx); } void -window_more_add(struct window *w, const char *fmt, ...) +window_more_add(struct window_pane *wp, const char *fmt, ...) { va_list ap; va_start(ap, fmt); - window_more_vadd(w, fmt, ap); + window_more_vadd(wp, fmt, ap); va_end(ap); } struct screen * -window_more_init(struct window *w) +window_more_init(struct window_pane *wp) { struct window_more_mode_data *data; struct screen *s; - w->modedata = data = xmalloc(sizeof *data); + wp->modedata = data = xmalloc(sizeof *data); ARRAY_INIT(&data->list); data->top = 0; s = &data->screen; - screen_init(s, screen_size_x(&w->base), screen_size_y(&w->base), 0); + screen_init(s, screen_size_x(&wp->base), screen_size_y(&wp->base), 0); s->mode &= ~MODE_CURSOR; return (s); } void -window_more_free(struct window *w) +window_more_free(struct window_pane *wp) { - struct window_more_mode_data *data = w->modedata; + struct window_more_mode_data *data = wp->modedata; u_int i; for (i = 0; i < ARRAY_LENGTH(&data->list); i++) @@ -114,39 +114,39 @@ window_more_free(struct window *w) } void -window_more_resize(struct window *w, u_int sx, u_int sy) +window_more_resize(struct window_pane *wp, u_int sx, u_int sy) { - struct window_more_mode_data *data = w->modedata; + struct window_more_mode_data *data = wp->modedata; struct screen *s = &data->screen; screen_resize(s, sx, sy); - window_more_redraw_screen(w); + window_more_redraw_screen(wp); } void -window_more_key(struct window *w, unused struct client *c, int key) +window_more_key(struct window_pane *wp, unused struct client *c, int key) { - struct window_more_mode_data *data = w->modedata; + struct window_more_mode_data *data = wp->modedata; struct screen *s = &data->screen; int table; - table = options_get_number(&w->options, "mode-keys"); + table = options_get_number(&wp->window->options, "mode-keys"); switch (mode_key_lookup(table, key)) { case MODEKEY_QUIT: - window_reset_mode(w); + window_pane_reset_mode(wp); break; case MODEKEY_UP: - window_more_scroll_up(w); + window_more_scroll_up(wp); break; case MODEKEY_DOWN: - window_more_scroll_down(w); + window_more_scroll_down(wp); break; case MODEKEY_PPAGE: if (data->top < screen_size_y(s)) data->top = 0; else data->top -= screen_size_y(s); - window_more_redraw_screen(w); + window_more_redraw_screen(wp); break; case MODEKEY_NONE: if (key != ' ') @@ -157,7 +157,7 @@ window_more_key(struct window *w, unused struct client *c, int key) data->top = ARRAY_LENGTH(&data->list); else data->top += screen_size_y(s); - window_more_redraw_screen(w); + window_more_redraw_screen(wp); break; default: break; @@ -165,9 +165,9 @@ window_more_key(struct window *w, unused struct client *c, int key) } void -window_more_write_line(struct window *w, struct screen_write_ctx *ctx, u_int py) +window_more_write_line(struct window_pane *wp, struct screen_write_ctx *ctx, u_int py) { - struct window_more_mode_data *data = w->modedata; + struct window_more_mode_data *data = wp->modedata; struct screen *s = &data->screen; struct grid_cell gc; char *msg, hdr[32]; @@ -179,8 +179,8 @@ window_more_write_line(struct window *w, struct screen_write_ctx *ctx, u_int py) size = xsnprintf(hdr, sizeof hdr, "[%u/%u]", data->top, ARRAY_LENGTH(&data->list)); screen_write_cursormove(ctx, screen_size_x(s) - size, 0); - gc.fg = options_get_number(&w->options, "mode-fg"); - gc.bg = options_get_number(&w->options, "mode-bg"); + gc.fg = options_get_number(&wp->window->options, "mode-fg"); + gc.bg = options_get_number(&wp->window->options, "mode-bg"); screen_write_puts(ctx, &gc, "%s", hdr); memcpy(&gc, &grid_default_cell, sizeof gc); } else @@ -197,41 +197,41 @@ window_more_write_line(struct window *w, struct screen_write_ctx *ctx, u_int py) } void -window_more_redraw_screen(struct window *w) +window_more_redraw_screen(struct window_pane *wp) { - struct window_more_mode_data *data = w->modedata; + struct window_more_mode_data *data = wp->modedata; struct screen *s = &data->screen; struct screen_write_ctx ctx; u_int i; - screen_write_start_window(&ctx, w); + screen_write_start(&ctx, wp, NULL); for (i = 0; i < screen_size_y(s); i++) - window_more_write_line(w, &ctx, i); + window_more_write_line(wp, &ctx, i); screen_write_stop(&ctx); } void -window_more_scroll_up(struct window *w) +window_more_scroll_up(struct window_pane *wp) { - struct window_more_mode_data *data = w->modedata; + struct window_more_mode_data *data = wp->modedata; struct screen_write_ctx ctx; if (data->top == 0) return; data->top--; - screen_write_start_window(&ctx, w); + screen_write_start(&ctx, wp, NULL); screen_write_cursormove(&ctx, 0, 0); screen_write_insertline(&ctx, 1); - window_more_write_line(w, &ctx, 0); - window_more_write_line(w, &ctx, 1); + window_more_write_line(wp, &ctx, 0); + window_more_write_line(wp, &ctx, 1); screen_write_stop(&ctx); } void -window_more_scroll_down(struct window *w) +window_more_scroll_down(struct window_pane *wp) { - struct window_more_mode_data *data = w->modedata; + struct window_more_mode_data *data = wp->modedata; struct screen *s = &data->screen; struct screen_write_ctx ctx; @@ -239,10 +239,10 @@ window_more_scroll_down(struct window *w) return; data->top++; - screen_write_start_window(&ctx, w); + screen_write_start(&ctx, wp, NULL); screen_write_cursormove(&ctx, 0, 0); screen_write_deleteline(&ctx, 1); - window_more_write_line(w, &ctx, screen_size_y(s) - 1); - window_more_write_line(w, &ctx, 0); + window_more_write_line(wp, &ctx, screen_size_y(s) - 1); + window_more_write_line(wp, &ctx, 0); screen_write_stop(&ctx); } diff --git a/window-scroll.c b/window-scroll.c index 7d49036c..d3f7d244 100644 --- a/window-scroll.c +++ b/window-scroll.c @@ -1,4 +1,4 @@ -/* $Id: window-scroll.c,v 1.26 2009-01-10 19:35:40 nicm Exp $ */ +/* $Id: window-scroll.c,v 1.27 2009-01-11 23:31:46 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -22,21 +22,21 @@ #include "tmux.h" -struct screen *window_scroll_init(struct window *); -void window_scroll_free(struct window *); -void window_scroll_resize(struct window *, u_int, u_int); -void window_scroll_key(struct window *, struct client *, int); +struct screen *window_scroll_init(struct window_pane *); +void window_scroll_free(struct window_pane *); +void window_scroll_resize(struct window_pane *, u_int, u_int); +void window_scroll_key(struct window_pane *, struct client *, int); -void window_scroll_redraw_screen(struct window *); +void window_scroll_redraw_screen(struct window_pane *); void window_scroll_write_line( - struct window *, struct screen_write_ctx *, u_int); + struct window_pane *, struct screen_write_ctx *, u_int); void window_scroll_write_column( - struct window *, struct screen_write_ctx *, u_int); + struct window_pane *, struct screen_write_ctx *, u_int); -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 *); +void window_scroll_scroll_up(struct window_pane *); +void window_scroll_scroll_down(struct window_pane *); +void window_scroll_scroll_left(struct window_pane *); +void window_scroll_scroll_right(struct window_pane *); const struct window_mode window_scroll_mode = { window_scroll_init, @@ -54,90 +54,90 @@ struct window_scroll_mode_data { }; struct screen * -window_scroll_init(struct window *w) +window_scroll_init(struct window_pane *wp) { struct window_scroll_mode_data *data; struct screen *s; struct screen_write_ctx ctx; u_int i; - w->modedata = data = xmalloc(sizeof *data); + wp->modedata = data = xmalloc(sizeof *data); data->ox = 0; data->oy = 0; s = &data->screen; - screen_init(s, screen_size_x(&w->base), screen_size_y(&w->base), 0); + screen_init(s, screen_size_x(&wp->base), screen_size_y(&wp->base), 0); s->mode &= ~MODE_CURSOR; - screen_write_start(&ctx, s, NULL, NULL); + screen_write_start(&ctx, NULL, s); for (i = 0; i < screen_size_y(s); i++) - window_scroll_write_line(w, &ctx, i); + window_scroll_write_line(wp, &ctx, i); screen_write_stop(&ctx); return (s); } void -window_scroll_free(struct window *w) +window_scroll_free(struct window_pane *wp) { - struct window_scroll_mode_data *data = w->modedata; + struct window_scroll_mode_data *data = wp->modedata; screen_free(&data->screen); xfree(data); } void -window_scroll_resize(struct window *w, u_int sx, u_int sy) +window_scroll_resize(struct window_pane *wp, u_int sx, u_int sy) { - struct window_scroll_mode_data *data = w->modedata; + struct window_scroll_mode_data *data = wp->modedata; struct screen *s = &data->screen; struct screen_write_ctx ctx; u_int i; screen_resize(s, sx, sy); - screen_write_start(&ctx, s, NULL, NULL); + screen_write_start(&ctx, NULL, s); for (i = 0; i < screen_size_y(s); i++) - window_scroll_write_line(w, &ctx, i); + window_scroll_write_line(wp, &ctx, i); screen_write_stop(&ctx); } void -window_scroll_key(struct window *w, unused struct client *c, int key) +window_scroll_key(struct window_pane *wp, unused struct client *c, int key) { - struct window_scroll_mode_data *data = w->modedata; + struct window_scroll_mode_data *data = wp->modedata; struct screen *s = &data->screen; int table; - table = options_get_number(&w->options, "mode-keys"); + table = options_get_number(&wp->window->options, "mode-keys"); switch (mode_key_lookup(table, key)) { case MODEKEY_QUIT: - window_reset_mode(w); + window_pane_reset_mode(wp); break; case MODEKEY_LEFT: - window_scroll_scroll_left(w); + window_scroll_scroll_left(wp); break; case MODEKEY_RIGHT: - window_scroll_scroll_right(w); + window_scroll_scroll_right(wp); break; case MODEKEY_UP: - window_scroll_scroll_up(w); + window_scroll_scroll_up(wp); break; case MODEKEY_DOWN: - window_scroll_scroll_down(w); + window_scroll_scroll_down(wp); break; case MODEKEY_PPAGE: - if (data->oy + screen_size_y(s) > screen_hsize(&w->base)) - data->oy = screen_hsize(&w->base); + if (data->oy + screen_size_y(s) > screen_hsize(&wp->base)) + data->oy = screen_hsize(&wp->base); else data->oy += screen_size_y(s); - window_scroll_redraw_screen(w); + window_scroll_redraw_screen(wp); break; case MODEKEY_NPAGE: if (data->oy < screen_size_y(s)) data->oy = 0; else data->oy -= screen_size_y(s); - window_scroll_redraw_screen(w); + window_scroll_redraw_screen(wp); break; default: break; @@ -146,9 +146,9 @@ window_scroll_key(struct window *w, unused struct client *c, int key) void window_scroll_write_line( - struct window *w, struct screen_write_ctx *ctx, u_int py) + struct window_pane *wp, struct screen_write_ctx *ctx, u_int py) { - struct window_scroll_mode_data *data = w->modedata; + struct window_scroll_mode_data *data = wp->modedata; struct screen *s = &data->screen; struct grid_cell gc; char hdr[32]; @@ -157,9 +157,9 @@ window_scroll_write_line( if (py == 0) { memcpy(&gc, &grid_default_cell, sizeof gc); size = xsnprintf(hdr, sizeof hdr, - "[%u,%u/%u]", data->ox, data->oy, screen_hsize(&w->base)); - gc.fg = options_get_number(&w->options, "mode-fg"); - gc.bg = options_get_number(&w->options, "mode-bg"); + "[%u,%u/%u]", data->ox, data->oy, screen_hsize(&wp->base)); + gc.fg = options_get_number(&wp->window->options, "mode-fg"); + gc.bg = options_get_number(&wp->window->options, "mode-bg"); screen_write_cursormove(ctx, screen_size_x(s) - size, 0); screen_write_puts(ctx, &gc, "%s", hdr); memcpy(&gc, &grid_default_cell, sizeof gc); @@ -167,58 +167,58 @@ window_scroll_write_line( size = 0; screen_write_cursormove(ctx, 0, py); - screen_write_copy(ctx, &w->base, data->ox, (screen_hsize(&w->base) - + screen_write_copy(ctx, &wp->base, data->ox, (screen_hsize(&wp->base) - data->oy) + py, screen_size_x(s) - size, 1); } void window_scroll_write_column( - struct window *w, struct screen_write_ctx *ctx, u_int px) + struct window_pane *wp, struct screen_write_ctx *ctx, u_int px) { - struct window_scroll_mode_data *data = w->modedata; + struct window_scroll_mode_data *data = wp->modedata; struct screen *s = &data->screen; screen_write_cursormove(ctx, px, 0); - screen_write_copy(ctx, &w->base, data->ox + px, - screen_hsize(&w->base) - data->oy, 1, screen_size_y(s)); + screen_write_copy(ctx, &wp->base, data->ox + px, + screen_hsize(&wp->base) - data->oy, 1, screen_size_y(s)); } void -window_scroll_redraw_screen(struct window *w) +window_scroll_redraw_screen(struct window_pane *wp) { - struct window_scroll_mode_data *data = w->modedata; + struct window_scroll_mode_data *data = wp->modedata; struct screen *s = &data->screen; struct screen_write_ctx ctx; u_int i; - screen_write_start_window(&ctx, w); + screen_write_start(&ctx, wp, NULL); for (i = 0; i < screen_size_y(s); i++) - window_scroll_write_line(w, &ctx, i); + window_scroll_write_line(wp, &ctx, i); screen_write_stop(&ctx); } void -window_scroll_scroll_up(struct window *w) +window_scroll_scroll_up(struct window_pane *wp) { - struct window_scroll_mode_data *data = w->modedata; + struct window_scroll_mode_data *data = wp->modedata; struct screen_write_ctx ctx; - if (data->oy >= screen_hsize(&w->base)) + if (data->oy >= screen_hsize(&wp->base)) return; data->oy++; - screen_write_start_window(&ctx, w); + screen_write_start(&ctx, wp, NULL); screen_write_cursormove(&ctx, 0, 0); screen_write_insertline(&ctx, 1); - window_scroll_write_line(w, &ctx, 0); - window_scroll_write_line(w, &ctx, 1); + window_scroll_write_line(wp, &ctx, 0); + window_scroll_write_line(wp, &ctx, 1); screen_write_stop(&ctx); } void -window_scroll_scroll_down(struct window *w) +window_scroll_scroll_down(struct window_pane *wp) { - struct window_scroll_mode_data *data = w->modedata; + struct window_scroll_mode_data *data = wp->modedata; struct screen *s = &data->screen; struct screen_write_ctx ctx; @@ -226,18 +226,18 @@ window_scroll_scroll_down(struct window *w) return; data->oy--; - screen_write_start_window(&ctx, w); + screen_write_start(&ctx, wp, NULL); screen_write_cursormove(&ctx, 0, 0); screen_write_deleteline(&ctx, 1); - window_scroll_write_line(w, &ctx, screen_size_y(s) - 1); - window_scroll_write_line(w, &ctx, 0); + window_scroll_write_line(wp, &ctx, screen_size_y(s) - 1); + window_scroll_write_line(wp, &ctx, 0); screen_write_stop(&ctx); } void -window_scroll_scroll_right(struct window *w) +window_scroll_scroll_right(struct window_pane *wp) { - struct window_scroll_mode_data *data = w->modedata; + struct window_scroll_mode_data *data = wp->modedata; struct screen *s = &data->screen; struct screen_write_ctx ctx; u_int i; @@ -246,20 +246,20 @@ window_scroll_scroll_right(struct window *w) return; data->ox++; - screen_write_start_window(&ctx, w); + screen_write_start(&ctx, wp, NULL); for (i = 1; i < screen_size_y(s); i++) { screen_write_cursormove(&ctx, 0, i); screen_write_deletecharacter(&ctx, 1); } - window_scroll_write_column(w, &ctx, screen_size_x(s) - 1); - window_scroll_write_line(w, &ctx, 0); + window_scroll_write_column(wp, &ctx, screen_size_x(s) - 1); + window_scroll_write_line(wp, &ctx, 0); screen_write_stop(&ctx); } void -window_scroll_scroll_left(struct window *w) +window_scroll_scroll_left(struct window_pane *wp) { - struct window_scroll_mode_data *data = w->modedata; + struct window_scroll_mode_data *data = wp->modedata; struct screen *s = &data->screen; struct screen_write_ctx ctx; u_int i; @@ -268,12 +268,12 @@ window_scroll_scroll_left(struct window *w) return; data->ox--; - screen_write_start_window(&ctx, w); + screen_write_start(&ctx, wp, NULL); for (i = 1; i < screen_size_y(s); i++) { screen_write_cursormove(&ctx, 0, i); screen_write_insertcharacter(&ctx, 1); } - window_scroll_write_column(w, &ctx, 0); - window_scroll_write_line(w, &ctx, 0); + window_scroll_write_column(wp, &ctx, 0); + window_scroll_write_line(wp, &ctx, 0); screen_write_stop(&ctx); } diff --git a/window.c b/window.c index 8d4bd496..9f7cdf43 100644 --- a/window.c +++ b/window.c @@ -1,4 +1,4 @@ -/* $Id: window.c,v 1.54 2009-01-10 19:37:35 nicm Exp $ */ +/* $Id: window.c,v 1.55 2009-01-11 23:31:46 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -46,16 +46,17 @@ #include "tmux.h" /* - * Each window is attached to a pty. This file contains code to handle them. + * Each window is attached to one or two panes, each of which is a pty. This + * file contains code to handle them. * - * A window has two buffers attached, these are filled and emptied by the main + * A pane has two buffers attached, these are filled and emptied by the main * server poll loop. Output data is received from pty's in screen format, * translated and returned as a series of escape sequences and strings via * input_parse (in input.c). Input data is received as key codes and written * directly via input_key. * - * Each window also has a "virtual" screen (screen.c) which contains the - * current state and is redisplayed when the window is reattached to a client. + * Each pane also has a "virtual" screen (screen.c) which contains the current + * state and is redisplayed when the window is reattached to a client. * * Windows are stored directly on a global array and wrapped in any number of * winlink structs to be linked onto local session RB trees. A reference count @@ -211,20 +212,15 @@ window_create(const char *name, const char *cmd, char *ptr, *copy; w = xmalloc(sizeof *w); - w->cmd = NULL; - w->cwd = NULL; - - w->fd = -1; - w->in = buffer_create(BUFSIZ); - w->out = buffer_create(BUFSIZ); - - w->mode = NULL; w->flags = 0; + w->panes[0] = window_pane_create(w, sx, sy, hlimit); + w->panes[1] = NULL; - screen_init(&w->base, sx, sy, hlimit); - w->screen = &w->base; + w->sx = sx; + w->sy = sy; + + w->active = w->panes[0]; - input_init(w); options_init(&w->options, &global_window_options); if (name == NULL) { @@ -253,60 +249,13 @@ window_create(const char *name, const char *cmd, ARRAY_ADD(&windows, w); w->references = 0; - if (window_spawn(w, cmd, cwd, envp) != 0) { + if (window_pane_spawn(w->active, cmd, cwd, envp) != 0) { window_destroy(w); return (NULL); } return (w); } -int -window_spawn( - struct window *w, const char *cmd, const char *cwd, const char **envp) -{ - struct winsize ws; - int mode; - const char **envq; - - if (w->fd != -1) - close(w->fd); - if (w->cmd != NULL) - xfree(w->cmd); - w->cmd = xstrdup(cmd); - w->cwd = xstrdup(cwd); - - memset(&ws, 0, sizeof ws); - ws.ws_col = screen_size_x(&w->base); - ws.ws_row = screen_size_y(&w->base); - - switch (forkpty(&w->fd, NULL, NULL, &ws)) { - case -1: - return (1); - case 0: - if (chdir(cwd) != 0) - chdir("/"); - for (envq = envp; *envq != NULL; envq++) { - if (putenv(*envq) != 0) - fatal("putenv failed"); - } - sigreset(); - log_debug("new child: cmd=%s pid=%ld", w->cmd, (long) getpid()); - log_close(); - - execl(_PATH_BSHELL, "sh", "-c", w->cmd, (char *) NULL); - fatal("execl failed"); - } - - if ((mode = fcntl(w->fd, F_GETFL)) == -1) - fatal("fcntl failed"); - if (fcntl(w->fd, F_SETFL, mode|O_NONBLOCK) == -1) - fatal("fcntl failed"); - if (fcntl(w->fd, F_SETFD, FD_CLOEXEC) == -1) - fatal("fcntl failed"); - - return (0); -} - void window_destroy(struct window *w) { @@ -318,87 +267,207 @@ window_destroy(struct window *w) } ARRAY_REMOVE(&windows, i); - if (w->fd != -1) - close(w->fd); - - input_free(w); - - window_reset_mode(w); options_free(&w->options); - screen_free(&w->base); - buffer_destroy(w->in); - buffer_destroy(w->out); - - if (w->cwd != NULL) - xfree(w->cwd); - if (w->cmd != NULL) - xfree(w->cmd); + window_pane_destroy(w->panes[0]); + if (w->panes[1] != NULL) + window_pane_destroy(w->panes[1]); + xfree(w->name); xfree(w); } int window_resize(struct window *w, u_int sx, u_int sy) +{ + if (w->panes[1] != NULL) { + window_pane_resize(w->panes[0], sx, sy / 2 - 1); + window_pane_resize(w->panes[1], sx, sy - (sy / 2)); + } else + window_pane_resize(w->panes[0], sx, sy); + + w->sx = sx; + w->sy = sy; + + return (0); +} + +int +window_remove_pane(struct window *w, int pane) +{ + if (w->panes[1] != NULL) { + window_pane_destroy(w->panes[pane]); + w->panes[pane] = NULL; + if (pane == 0) { + w->panes[0] = w->panes[1]; + w->panes[1] = NULL; + } + window_resize(w, w->sx, w->sy); + w->active = w->panes[0]; + return (0); + } + return (1); +} + +struct window_pane * +window_pane_create(struct window *w, u_int sx, u_int sy, u_int hlimit) +{ + struct window_pane *wp; + + wp = xmalloc(sizeof *wp); + wp->window = w; + + wp->cmd = NULL; + wp->cwd = NULL; + + wp->fd = -1; + wp->in = buffer_create(BUFSIZ); + wp->out = buffer_create(BUFSIZ); + + wp->mode = NULL; + + screen_init(&wp->base, sx, sy, hlimit); + wp->screen = &wp->base; + + input_init(wp); + + return (wp); +} + +void +window_pane_destroy(struct window_pane *wp) +{ + if (wp->fd != -1) + close(wp->fd); + + input_free(wp); + + window_pane_reset_mode(wp); + screen_free(&wp->base); + + buffer_destroy(wp->in); + buffer_destroy(wp->out); + + if (wp->cwd != NULL) + xfree(wp->cwd); + if (wp->cmd != NULL) + xfree(wp->cmd); + xfree(wp); +} + +int +window_pane_spawn(struct window_pane *wp, + const char *cmd, const char *cwd, const char **envp) +{ + struct winsize ws; + int mode; + const char **envq; + + if (wp->fd != -1) + close(wp->fd); + if (cmd != NULL) { + if (wp->cmd != NULL) + xfree(wp->cmd); + wp->cmd = xstrdup(cmd); + } + if (cwd != NULL) { + if (wp->cwd != NULL) + xfree(wp->cwd); + wp->cwd = xstrdup(cwd); + } + + memset(&ws, 0, sizeof ws); + ws.ws_col = screen_size_x(&wp->base); + ws.ws_row = screen_size_y(&wp->base); + + switch (forkpty(&wp->fd, NULL, NULL, &ws)) { + case -1: + return (1); + case 0: + if (chdir(wp->cwd) != 0) + chdir("/"); + for (envq = envp; *envq != NULL; envq++) { + if (putenv(*envq) != 0) + fatal("putenv failed"); + } + sigreset(); + log_close(); + + execl(_PATH_BSHELL, "sh", "-c", wp->cmd, (char *) NULL); + fatal("execl failed"); + } + + if ((mode = fcntl(wp->fd, F_GETFL)) == -1) + fatal("fcntl failed"); + if (fcntl(wp->fd, F_SETFL, mode|O_NONBLOCK) == -1) + fatal("fcntl failed"); + if (fcntl(wp->fd, F_SETFD, FD_CLOEXEC) == -1) + fatal("fcntl failed"); + + return (0); +} + +int +window_pane_resize(struct window_pane *wp, u_int sx, u_int sy) { struct winsize ws; - if (sx == screen_size_x(&w->base) && sy == screen_size_y(&w->base)) + if (sx == screen_size_x(&wp->base) && sy == screen_size_y(&wp->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(&wp->base, sx, sy); + if (wp->mode != NULL) + wp->mode->resize(wp, sx, sy); - if (w->fd != -1 && ioctl(w->fd, TIOCSWINSZ, &ws) == -1) + if (wp->fd != -1 && ioctl(wp->fd, TIOCSWINSZ, &ws) == -1) fatal("ioctl failed"); return (0); } int -window_set_mode(struct window *w, const struct window_mode *mode) +window_pane_set_mode(struct window_pane *wp, const struct window_mode *mode) { struct screen *s; - if (w->mode != NULL || w->mode == mode) + if (wp->mode != NULL || wp->mode == mode) return (1); - w->mode = mode; + wp->mode = mode; - if ((s = w->mode->init(w)) != NULL) - w->screen = s; - server_redraw_window(w); + if ((s = wp->mode->init(wp)) != NULL) + wp->screen = s; + server_redraw_window(wp->window); return (0); } void -window_reset_mode(struct window *w) +window_pane_reset_mode(struct window_pane *wp) { - if (w->mode == NULL) + if (wp->mode == NULL) return; - w->mode->free(w); - w->mode = NULL; + wp->mode->free(wp); + wp->mode = NULL; - w->screen = &w->base; - server_redraw_window(w); + wp->screen = &wp->base; + server_redraw_window(wp->window); } void -window_parse(struct window *w) +window_pane_parse(struct window_pane *wp) { - input_parse(w); + input_parse(wp); } void -window_key(struct window *w, struct client *c, int key) +window_pane_key(struct window_pane *wp, struct client *c, int key) { - if (w->mode != NULL) - w->mode->key(w, c, key); + if (wp->mode != NULL) + wp->mode->key(wp, c, key); else - input_key(w, key); + input_key(wp, key); }