From 162bacdcd91caf631db6979a21c27d208a66046b Mon Sep 17 00:00:00 2001 From: Nicholas Marriott Date: Sun, 11 Jan 2009 23:31:46 +0000 Subject: 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 | 215 ++++++++++++----------- screen-write.c | 181 ++++++++------------ server-msg.c | 3 +- server.c | 247 +++++++++++++------------- status.c | 158 +++++++++-------- tmux.h | 151 ++++++++-------- tty-write.c | 77 ++------- tty.c | 299 +++++++++++++++----------------- window-clock.c | 55 +++--- window-copy.c | 476 +++++++++++++++++++++++++-------------------------- window-more.c | 102 +++++------ window-scroll.c | 140 +++++++-------- window.c | 247 ++++++++++++++++---------- 32 files changed, 1587 insertions(+), 1284 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_start_window(struct screen_redraw_ctx *ctx, struct window *w) -{ - struct screen *t = w->screen; +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); - screen_redraw_start(ctx, t, tty_write_window, w); -} - -/* Initialise redrawing with a client. */ +/* Redraw entire screen.. */ void -screen_redraw_start_client(struct screen_redraw_ctx *ctx, struct client *c) +screen_redraw_screen(struct client *c, struct screen *s) { - struct screen *t = c->session->curw->window->screen; + struct winlink *wl = c->session->curw; + u_int i, cx, cy, sy; + int status; - screen_redraw_start(ctx, t, tty_write_client, c); -} + status = options_get_number(&c->session->options, "status"); -/* 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; + /* 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; + } - /* - * 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; + } -/* Finish redrawing. */ -void -screen_redraw_stop(struct screen_redraw_ctx *ctx) -{ - struct screen *s = ctx->s; + /* 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); + } - s->cx = ctx->saved_cx; - s->cy = ctx->saved_cy; + /* 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); - 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); + /* Draw the status line. */ + screen_redraw_status(c); } -/* Write character. */ +/* Draw the status line. */ void -screen_redraw_putc( - struct screen_redraw_ctx *ctx, struct grid_cell *gc, u_char ch) +screen_redraw_status(struct client *c) { - gc->data = ch; - ctx->write(ctx->data, TTY_CELL, gc); - ctx->s->cx++; -} - -/* 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); + screen_redraw_line(c, &c->status, c->sy - 1, 0); } -/* Redraw single cell. */ +/* Draw blank columns. */ void -screen_redraw_cell(struct screen_redraw_ctx *ctx, u_int px, u_int py) +screen_redraw_blankx(struct client *c, u_int ox, u_int nx) { - const struct grid_cell *gc; - struct grid_cell tc; + u_int i, j; - 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); + 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, ' '); } - 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++; + c->tty.cx = UINT_MAX; + c->tty.cy = UINT_MAX; + memcpy(&c->tty.cell, &grid_default_cell, sizeof c->tty.cell); } -/* Draw set of lines. */ +/* Draw blank lines. */ void -screen_redraw_lines(struct screen_redraw_ctx *ctx, u_int py, u_int ny) +screen_redraw_blanky(struct client *c, u_int oy, 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); + 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 set of columns. */ +/* Draw a line. */ void -screen_redraw_columns(struct screen_redraw_ctx *ctx, u_int px, u_int nx) +screen_redraw_line(struct client *c, struct screen *s, u_int oy, u_int py) { - 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); + const struct grid_cell *gc; + struct grid_cell tc; + u_int i; + + for (i = 0; i < screen_size_x(s); i++) { + s->cx = i; + s->cy = py; + + 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); } - c->tty.flags |= flags; + if (c->flags & CLIENT_REDRAW) { + if (server_locked) + server_redraw_locked(c); + else + screen_redraw_screen(c, NULL); + } - c->flags &= ~(CLIENT_REDRAW|CLIENT_STATUS); -} + if (c->flags & CLIENT_STATUS) + screen_redraw_status(c); -/* 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; + c->tty.flags |= flags; - 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); + c->flags &= ~(CLIENT_REDRAW|CLIENT_STATUS); } /* 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; - - log_debug("lost window %d", w->fd); + struct client *c; + struct session *s; + struct winlink *wl; + struct window_pane *wp; + u_int i, j; + int destroyed; + + 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