diff options
-rw-r--r-- | CHANGES | 9 | ||||
-rw-r--r-- | TODO | 3 | ||||
-rw-r--r-- | cmd-kill-window.c | 10 | ||||
-rw-r--r-- | cmd-list-sessions.c | 11 | ||||
-rw-r--r-- | cmd-list-windows.c | 19 | ||||
-rw-r--r-- | cmd-new-session.c | 6 | ||||
-rw-r--r-- | cmd-new-window.c | 29 | ||||
-rw-r--r-- | cmd-rename-window.c | 12 | ||||
-rw-r--r-- | cmd-select-window.c | 12 | ||||
-rw-r--r-- | cmd-send-prefix.c | 4 | ||||
-rw-r--r-- | key-bindings.c | 4 | ||||
-rw-r--r-- | server-fn.c | 21 | ||||
-rw-r--r-- | server-msg.c | 4 | ||||
-rw-r--r-- | server.c | 34 | ||||
-rw-r--r-- | session.c | 173 | ||||
-rw-r--r-- | status.c | 22 | ||||
-rw-r--r-- | tmux.h | 60 | ||||
-rw-r--r-- | window.c | 263 |
18 files changed, 347 insertions, 349 deletions
@@ -1,3 +1,10 @@ +26 October 2007 + +* (nicm) Redo window data structures. The global array remains, but each per- + session list is now a RB tree of winlink structures. This disassociates the + window index from the array size (allowing arbitrary indexes) which still + allowing windows to have multiple indexes. + 25 October 2007 * (nicm) has-session command: checks if session exists. @@ -163,5 +170,5 @@ (including mutt, emacs). No status bar yet and no key remapping or other customisation. -$Id: CHANGES,v 1.51 2007-10-25 17:44:24 nicm Exp $ +$Id: CHANGES,v 1.52 2007-10-26 12:29:07 nicm Exp $ @@ -1,4 +1,3 @@ -- decide if TIOCPKT is necessary and either handle it or remove the code - it would be nice if there wasn't so much copying buffers about, audit uses - useful env vars like WINDOW - sort out who controls the buffers in local.c a bit @@ -20,8 +19,6 @@ - profile/optimise, particularly (i suspect) input.c - tidy up input.c a bit - decide about customised status line -- rethink data structures. window->index is O(n), could have a w->idx member - or use queues/trees and avoid NULLs? - client could pass term/tty fd up to server and then do nothing. what problems would this cause? -- need access to all terminfo data at once... signals? - cleanup/redesign IPC diff --git a/cmd-kill-window.c b/cmd-kill-window.c index 07d16a97..dce7f768 100644 --- a/cmd-kill-window.c +++ b/cmd-kill-window.c @@ -1,4 +1,4 @@ -/* $Id: cmd-kill-window.c,v 1.1 2007-10-19 11:10:35 nicm Exp $ */ +/* $Id: cmd-kill-window.c,v 1.2 2007-10-26 12:29:07 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> @@ -92,7 +92,7 @@ cmd_kill_window_exec(void *ptr, struct cmd_ctx *ctx) struct cmd_kill_window_data *data = ptr, std = { -1 }; struct client *c = ctx->client; struct session *s = ctx->session; - struct window *w; + struct winlink *wl; u_int i; int destroyed; @@ -100,13 +100,13 @@ cmd_kill_window_exec(void *ptr, struct cmd_ctx *ctx) data = &std; if (data->idx == -1) - w = s->window; - else if ((w = window_at(&s->windows, data->idx)) == NULL) { + wl = s->curw; + else if ((wl = winlink_find_by_index(&s->windows, data->idx)) == NULL) { ctx->error(ctx, "no window %u", data->idx); return; } - destroyed = session_detach(s, w); + destroyed = session_detach(s, wl); for (i = 0; i < ARRAY_LENGTH(&clients); i++) { c = ARRAY_ITEM(&clients, i); if (c == NULL || c->session != s) diff --git a/cmd-list-sessions.c b/cmd-list-sessions.c index 81aa1bb3..6bacdde2 100644 --- a/cmd-list-sessions.c +++ b/cmd-list-sessions.c @@ -1,4 +1,4 @@ -/* $Id: cmd-list-sessions.c,v 1.6 2007-10-23 09:36:07 nicm Exp $ */ +/* $Id: cmd-list-sessions.c,v 1.7 2007-10-26 12:29:07 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> @@ -45,8 +45,9 @@ cmd_list_sessions_exec(unused void *ptr, struct cmd_ctx *ctx) { struct client *c = ctx->client; struct session *s = ctx->session; + struct winlink *wl; char *tim; - u_int i, j, n; + u_int i, n; for (i = 0; i < ARRAY_LENGTH(&sessions); i++) { s = ARRAY_ITEM(&sessions, i); @@ -54,10 +55,8 @@ cmd_list_sessions_exec(unused void *ptr, struct cmd_ctx *ctx) continue; n = 0; - for (j = 0; j < ARRAY_LENGTH(&s->windows); j++) { - if (ARRAY_ITEM(&s->windows, j) != NULL) - n++; - } + RB_FOREACH(wl, winlinks, &s->windows) + n++; tim = ctime(&s->tim); *strchr(tim, '\n') = '\0'; diff --git a/cmd-list-windows.c b/cmd-list-windows.c index 6807845f..a2bce816 100644 --- a/cmd-list-windows.c +++ b/cmd-list-windows.c @@ -1,4 +1,4 @@ -/* $Id: cmd-list-windows.c,v 1.3 2007-10-23 09:36:07 nicm Exp $ */ +/* $Id: cmd-list-windows.c,v 1.4 2007-10-26 12:29:07 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> @@ -44,17 +44,14 @@ cmd_list_windows_exec(unused void *ptr, struct cmd_ctx *ctx) { struct client *c = ctx->client; struct session *s = ctx->session; + struct winlink *wl; struct window *w; - u_int i; - - for (i = 0; i < ARRAY_LENGTH(&s->windows); i++) { - w = ARRAY_ITEM(&s->windows, i); - if (w == NULL) - continue; - - ctx->print(ctx, - "%u: %s \"%s\" (%s) [%ux%u]", i, w->name, w->screen.title, - ttyname(w->fd), w->screen.sx, w->screen.sy); + + RB_FOREACH(wl, winlinks, &s->windows) { + w = wl->window; + ctx->print(ctx, "%u: %s \"%s\" (%s) [%ux%u]", wl->idx, + w->name, w->screen.title, ttyname(w->fd), + w->screen.sx, w->screen.sy); } if (!(ctx->flags & CMD_KEY)) diff --git a/cmd-new-session.c b/cmd-new-session.c index 80f77490..aeff70bf 100644 --- a/cmd-new-session.c +++ b/cmd-new-session.c @@ -1,4 +1,4 @@ -/* $Id: cmd-new-session.c,v 1.13 2007-10-19 17:15:29 nicm Exp $ */ +/* $Id: cmd-new-session.c,v 1.14 2007-10-26 12:29:07 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> @@ -133,8 +133,8 @@ cmd_new_session_exec(void *ptr, struct cmd_ctx *ctx) if (c->session == NULL) fatalx("session_create failed"); if (data->winname != NULL) { - xfree(c->session->window->name); - c->session->window->name = xstrdup(data->winname); + xfree(c->session->curw->window->name); + c->session->curw->window->name = xstrdup(data->winname); } if (data->flag_detached) diff --git a/cmd-new-window.c b/cmd-new-window.c index ca87cb53..ea81734d 100644 --- a/cmd-new-window.c +++ b/cmd-new-window.c @@ -1,4 +1,4 @@ -/* $Id: cmd-new-window.c,v 1.9 2007-10-19 09:21:25 nicm Exp $ */ +/* $Id: cmd-new-window.c,v 1.10 2007-10-26 12:29:07 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> @@ -19,6 +19,7 @@ #include <sys/types.h> #include <getopt.h> +#include <stdlib.h> #include "tmux.h" @@ -35,11 +36,12 @@ void cmd_new_window_free(void *); struct cmd_new_window_data { char *name; char *cmd; + int idx; int flag_detached; }; const struct cmd_entry cmd_new_window_entry = { - "new-window", "neww", "[-d] [-n name] [command]", + "new-window", "neww", "[-d] [-i index] [-n name] [command]", 0, cmd_new_window_parse, cmd_new_window_exec, @@ -52,15 +54,24 @@ int cmd_new_window_parse(void **ptr, int argc, char **argv, char **cause) { struct cmd_new_window_data *data; + const char *errstr; int opt; *ptr = data = xmalloc(sizeof *data); + data->idx = -1; data->flag_detached = 0; data->name = NULL; data->cmd = NULL; - while ((opt = getopt(argc, argv, "dn:")) != EOF) { + while ((opt = getopt(argc, argv, "di:n:")) != EOF) { switch (opt) { + case 'i': + data->idx = strtonum(optarg, 0, UINT_MAX, &errstr); + if (errstr != NULL) { + xasprintf(cause, "index %s", errstr); + goto error; + } + break; case 'n': data->name = xstrdup(optarg); break; @@ -85,6 +96,7 @@ usage: usage(cause, "%s %s", cmd_new_window_entry.name, cmd_new_window_entry.usage); +error: cmd_new_window_free(data); return (-1); } @@ -92,11 +104,12 @@ usage: void cmd_new_window_exec(void *ptr, struct cmd_ctx *ctx) { - struct cmd_new_window_data *data = ptr, std = { NULL, NULL, 0 }; + struct cmd_new_window_data *data = ptr; + struct cmd_new_window_data std = { NULL, NULL, -1, 0 }; struct client *c = ctx->client; struct session *s = ctx->session; + struct winlink *wl; char *cmd; - u_int i; if (data == NULL) data = &std; @@ -105,12 +118,14 @@ cmd_new_window_exec(void *ptr, struct cmd_ctx *ctx) if (cmd == NULL) cmd = default_command; - if (session_new(s, data->name, cmd, &i) != 0) { + if (data->idx < 0) + data->idx = -1; + if ((wl = session_new(s, data->name, cmd, data->idx)) == NULL) { ctx->error(ctx, "command failed: %s", cmd); return; } if (!data->flag_detached) { - session_select(s, i); + session_select(s, wl->idx); server_redraw_session(s); } else server_status_session(s); diff --git a/cmd-rename-window.c b/cmd-rename-window.c index fab15f32..1816d082 100644 --- a/cmd-rename-window.c +++ b/cmd-rename-window.c @@ -1,4 +1,4 @@ -/* $Id: cmd-rename-window.c,v 1.7 2007-10-19 17:15:29 nicm Exp $ */ +/* $Id: cmd-rename-window.c,v 1.8 2007-10-26 12:29:07 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> @@ -96,19 +96,19 @@ cmd_rename_window_exec(void *ptr, struct cmd_ctx *ctx) struct cmd_rename_window_data *data = ptr; struct client *c = ctx->client; struct session *s = ctx->session; - struct window *w; + struct winlink *wl; if (data == NULL) return; if (data->idx == -1) - w = s->window; - else if ((w = window_at(&s->windows, data->idx)) == NULL) { + wl = s->curw; + else if ((wl = winlink_find_by_index(&s->windows, data->idx)) == NULL) { ctx->error(ctx, "no window %u", data->idx); return; } - xfree(w->name); - w->name = xstrdup(data->newname); + xfree(wl->window->name); + wl->window->name = xstrdup(data->newname); server_status_session(s); diff --git a/cmd-select-window.c b/cmd-select-window.c index c0633567..9b906ea4 100644 --- a/cmd-select-window.c +++ b/cmd-select-window.c @@ -1,4 +1,4 @@ -/* $Id: cmd-select-window.c,v 1.4 2007-10-19 09:21:26 nicm Exp $ */ +/* $Id: cmd-select-window.c,v 1.5 2007-10-26 12:29:07 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> @@ -108,10 +108,16 @@ cmd_select_window_exec(void *ptr, struct cmd_ctx *ctx) if (data == NULL) return; - if (session_select(s, data->idx) == 0) + switch (session_select(s, data->idx)) { + case 0: server_redraw_session(s); - else + break; + case 1: + break; + default: ctx->error(ctx, "no window %u", data->idx); + break; + } if (!(ctx->flags & CMD_KEY)) server_write_client(c, MSG_EXIT, NULL, 0); diff --git a/cmd-send-prefix.c b/cmd-send-prefix.c index 304afbcc..62e3b4bc 100644 --- a/cmd-send-prefix.c +++ b/cmd-send-prefix.c @@ -1,4 +1,4 @@ -/* $Id: cmd-send-prefix.c,v 1.2 2007-10-19 23:33:20 nicm Exp $ */ +/* $Id: cmd-send-prefix.c,v 1.3 2007-10-26 12:29:07 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> @@ -49,5 +49,5 @@ cmd_send_prefix_exec(unused void *ptr, struct cmd_ctx *ctx) return; } - window_key(c->session->window, prefix_key); + input_translate_key(c->session->curw->window->out, prefix_key); } diff --git a/key-bindings.c b/key-bindings.c index ec1014d4..72b89c9a 100644 --- a/key-bindings.c +++ b/key-bindings.c @@ -1,4 +1,4 @@ -/* $Id: key-bindings.c,v 1.11 2007-10-23 10:25:57 nicm Exp $ */ +/* $Id: key-bindings.c,v 1.12 2007-10-26 12:29:07 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> @@ -177,7 +177,7 @@ key_bindings_print(struct cmd_ctx *ctx, const char *fmt, ...) if (!(c->flags & CLIENT_HOLD)) { input_store_zero(c->out, CODE_CURSOROFF); - for (i = 0; i < c->session->window->screen.sy; i++) { + for (i = 0; i < c->session->curw->window->screen.sy; i++) { input_store_two(c->out, CODE_CURSORMOVE, i + 1, 1); input_store_zero(c->out, CODE_CLEARLINE); } diff --git a/server-fn.c b/server-fn.c index 74f07a0e..536ad781 100644 --- a/server-fn.c +++ b/server-fn.c @@ -1,4 +1,4 @@ -/* $Id: server-fn.c,v 1.22 2007-10-23 10:48:23 nicm Exp $ */ +/* $Id: server-fn.c,v 1.23 2007-10-26 12:29:07 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> @@ -114,7 +114,7 @@ server_write_window_cur( for (i = 0; i < ARRAY_LENGTH(&clients); i++) { c = ARRAY_ITEM(&clients, i); if (c != NULL && - c->session != NULL && c->session->window == w) { + c->session != NULL && c->session->curw->window == w) { if (c->flags & CLIENT_HOLD) /* XXX OUTPUT only */ continue; server_write_client(c, type, buf, len); @@ -165,7 +165,7 @@ server_status_client(struct client *c) void server_clear_client(struct client *c) { - struct screen *s = &c->session->window->screen; + struct screen *s = &c->session->curw->window->screen; struct hdr hdr; size_t size; u_int i; @@ -192,7 +192,7 @@ server_clear_client(struct client *c) void server_redraw_client(struct client *c) { - struct screen *s = &c->session->window->screen; + struct screen *s = &c->session->curw->window->screen; struct hdr hdr; size_t size; @@ -248,7 +248,8 @@ server_clear_window_cur(struct window *w) for (i = 0; i < ARRAY_LENGTH(&clients); i++) { c = ARRAY_ITEM(&clients, i); - if (c != NULL && c->session != NULL && c->session->window == w) + if (c != NULL && + c->session != NULL && c->session->curw->window == w) server_clear_client(c); } } @@ -276,7 +277,8 @@ server_redraw_window_cur(struct window *w) for (i = 0; i < ARRAY_LENGTH(&clients); i++) { c = ARRAY_ITEM(&clients, i); - if (c != NULL && c->session != NULL && c->session->window == w) + if (c != NULL && + c->session != NULL && c->session->curw->window == w) server_redraw_client(c); } } @@ -304,7 +306,8 @@ server_status_window_cur(struct window *w) for (i = 0; i < ARRAY_LENGTH(&clients); i++) { c = ARRAY_ITEM(&clients, i); - if (c != NULL && c->session != NULL && c->session->window == w) + if (c != NULL && + c->session != NULL && c->session->curw->window == w) server_status_client(c); } } @@ -327,6 +330,7 @@ server_status_window_all(struct window *w) void server_write_message(struct client *c, const char *fmt, ...) { + struct screen *s = &c->session->curw->window->screen; struct hdr hdr; va_list ap; char *msg; @@ -364,8 +368,7 @@ server_write_message(struct client *c, const char *fmt, ...) size = BUFFER_USED(c->out); if (status_lines == 0) { - screen_draw( - &c->session->window->screen, c->out, c->sy - 1, c->sy - 1); + screen_draw(s, c->out, c->sy - 1, c->sy - 1); } else status_write(c); diff --git a/server-msg.c b/server-msg.c index 15be6f88..ae25a84c 100644 --- a/server-msg.c +++ b/server-msg.c @@ -1,4 +1,4 @@ -/* $Id: server-msg.c,v 1.29 2007-10-23 10:48:23 nicm Exp $ */ +/* $Id: server-msg.c,v 1.30 2007-10-26 12:29:07 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> @@ -223,7 +223,7 @@ server_msg_fn_keys(struct hdr *hdr, struct client *c) if (key == prefix_key) c->flags |= CLIENT_PREFIX; else - window_key(c->session->window, key); + input_translate_key(c->session->curw->window->out, key); } return (0); @@ -1,4 +1,4 @@ -/* $Id: server.c,v 1.34 2007-10-24 11:30:02 nicm Exp $ */ +/* $Id: server.c,v 1.35 2007-10-26 12:29:07 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> @@ -228,7 +228,7 @@ server_handle_windows(struct pollfd **pfd) for (i = 0; i < ARRAY_LENGTH(&windows); i++) { if ((w = ARRAY_ITEM(&windows, i)) != NULL) { - if (window_poll(w, *pfd) != 0) + if (buffer_poll(*pfd, w->in, w->out) != 0) server_lost_window(w); else server_handle_window(w); @@ -259,14 +259,14 @@ server_fill_clients(struct pollfd **pfd) /* Handle client pollfds. */ void -server_handle_clients(struct pollfd *(*pfd)) +server_handle_clients(struct pollfd **pfd) { struct client *c; u_int i; for (i = 0; i < ARRAY_LENGTH(&clients); i++) { if ((c = ARRAY_ITEM(&clients, i)) != NULL) { - if (buffer_poll((*pfd), c->in, c->out) != 0) + if (buffer_poll(*pfd, c->in, c->out) != 0) server_lost_client(c); else server_msg_dispatch(c); @@ -345,7 +345,7 @@ server_handle_window(struct window *w) u_int i; b = buffer_create(BUFSIZ); - window_data(w, b); + input_parse(w, b); if (BUFFER_USED(b) != 0) { server_write_window_cur( w, MSG_DATA, BUFFER_OUT(b), BUFFER_USED(b)); @@ -368,7 +368,7 @@ server_handle_window(struct window *w) case BELL_CURRENT: for (i = 0; i < ARRAY_LENGTH(&sessions); i++) { s = ARRAY_ITEM(&sessions, i); - if (s != NULL && s->window == w) + if (s != NULL && s->curw->window == w) server_write_session(s, MSG_DATA, "\007", 1); } break; @@ -384,6 +384,7 @@ server_lost_window(struct window *w) { struct client *c; struct session *s; + struct winlink *wl; u_int i, j; int destroyed; @@ -397,16 +398,23 @@ server_lost_window(struct window *w) continue; /* Detach window and either redraw or kill clients. */ - destroyed = session_detach(s, w); - for (j = 0; j < ARRAY_LENGTH(&clients); j++) { - c = ARRAY_ITEM(&clients, j); - if (c == NULL || c->session != s) + restart: + RB_FOREACH(wl, winlinks, &s->windows) { + if (wl->window != w) continue; - if (destroyed) { + destroyed = session_detach(s, wl); + for (j = 0; j < ARRAY_LENGTH(&clients); j++) { + c = ARRAY_ITEM(&clients, j); + if (c == NULL || c->session != s) + continue; + if (!destroyed) { + server_redraw_client(c); + continue; + } c->session = NULL; server_write_client(c, MSG_EXIT, NULL, 0); - } else - server_redraw_client(c); + } + goto restart; } } @@ -1,4 +1,4 @@ -/* $Id: session.c,v 1.24 2007-10-24 11:05:59 nicm Exp $ */ +/* $Id: session.c,v 1.25 2007-10-26 12:29:07 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> @@ -29,33 +29,41 @@ struct sessions sessions; void -session_cancelbell(struct session *s, struct window *w) +session_cancelbell(struct session *s, struct winlink *wl) { u_int i; - if (window_index(&s->bells, w, &i) == 0) - window_remove(&s->bells, w); + for (i = 0; i < ARRAY_LENGTH(&s->bells); i++) { + if (ARRAY_ITEM(&s->bells, i) == wl) { + ARRAY_REMOVE(&s->bells, i); + break; + } + } } void session_addbell(struct session *s, struct window *w) { - u_int i; - - /* Never bell in the current window. */ - if (w == s->window || !session_has(s, w)) - return; + struct winlink *wl; - if (window_index(&s->bells, w, &i) != 0) - window_add(&s->bells, w); + RB_FOREACH(wl, winlinks, &s->windows) { + if (wl == s->curw) + continue; + if (wl->window == w && !session_hasbell(s, wl)) + ARRAY_ADD(&s->bells, wl); + } } int -session_hasbell(struct session *s, struct window *w) +session_hasbell(struct session *s, struct winlink *wl) { u_int i; - return (window_index(&s->bells, w, &i) == 0); + for (i = 0; i < ARRAY_LENGTH(&s->bells); i++) { + if (ARRAY_ITEM(&s->bells, i) == wl) + return (1); + } + return (0); } /* Find session by name. */ @@ -83,8 +91,8 @@ session_create(const char *name, const char *cmd, u_int sx, u_int sy) s = xmalloc(sizeof *s); s->tim = time(NULL); - s->window = s->last = NULL; - ARRAY_INIT(&s->windows); + s->curw = s->lastw = NULL; + RB_INIT(&s->windows); ARRAY_INIT(&s->bells); s->sx = sx; @@ -103,7 +111,7 @@ session_create(const char *name, const char *cmd, u_int sx, u_int sy) s->name = xstrdup(name); else xasprintf(&s->name, "%u", i); - if (session_new(s, NULL, cmd, &i) != 0) { + if (session_new(s, NULL, cmd, -1) == NULL) { session_destroy(s); return (NULL); } @@ -116,7 +124,8 @@ session_create(const char *name, const char *cmd, u_int sx, u_int sy) void session_destroy(struct session *s) { - u_int i; + struct winlink *wl; + u_int i; if (session_index(s, &i) != 0) fatalx("session not found"); @@ -124,11 +133,11 @@ session_destroy(struct session *s) while (!ARRAY_EMPTY(&sessions) && ARRAY_LAST(&sessions) == NULL) ARRAY_TRUNC(&sessions, 1); - for (i = 0; i < ARRAY_LENGTH(&s->windows); i++) { - if (ARRAY_ITEM(&s->windows, i) != NULL) - window_remove(&s->windows, ARRAY_ITEM(&s->windows, i)); + while (!RB_EMPTY(&s->windows)) { + wl = RB_ROOT(&s->windows); + RB_REMOVE(winlinks, &s->windows, wl); + winlink_remove(&s->windows, wl); } - ARRAY_FREE(&s->windows); xfree(s->name); xfree(s); @@ -146,44 +155,43 @@ session_index(struct session *s, u_int *i) } /* Create a new window on a session. */ -int -session_new(struct session *s, const char *name, const char *cmd, u_int *i) +struct winlink * +session_new(struct session *s, const char *name, const char *cmd, int idx) { struct window *w; const char *environ[] = { NULL, "TERM=screen", NULL }; char buf[256]; + u_int i; - if (session_index(s, i) != 0) + if (session_index(s, &i) != 0) fatalx("session not found"); - xsnprintf(buf, sizeof buf, "TMUX=%ld,%u", (long) getpid(), *i); + xsnprintf(buf, sizeof buf, "TMUX=%ld,%u", (long) getpid(), i); environ[0] = buf; if ((w = window_create(name, cmd, environ, s->sx, s->sy)) == NULL) - return (-1); - session_attach(s, w); - - window_index(&s->windows, w, i); - return (0); + return (NULL); + return (session_attach(s, w, idx)); } /* Attach a window to a session. */ -void -session_attach(struct session *s, struct window *w) +struct winlink * +session_attach(struct session *s, struct window *w, int idx) { - window_add(&s->windows, w); + return (winlink_add(&s->windows, w, idx)); } /* Detach a window from a session. */ int -session_detach(struct session *s, struct window *w) +session_detach(struct session *s, struct winlink *wl) { - if (s->window == w && session_last(s) != 0 && session_previous(s) != 0) + if (s->curw == wl && session_last(s) != 0 && session_previous(s) != 0) session_next(s); - if (s->last == w) - s->last = NULL; + if (s->lastw == wl) + s->lastw = NULL; - window_remove(&s->windows, w); - if (ARRAY_EMPTY(&s->windows)) { + session_cancelbell(s, wl); + winlink_remove(&s->windows, wl); + if (RB_EMPTY(&s->windows)) { session_destroy(s); return (1); } @@ -194,34 +202,32 @@ session_detach(struct session *s, struct window *w) int session_has(struct session *s, struct window *w) { - u_int i; + struct winlink *wl; - return (window_index(&s->windows, w, &i) == 0); + RB_FOREACH(wl, winlinks, &s->windows) { + if (wl->window == w) + return (1); + } + return (0); } /* Move session to next window. */ int session_next(struct session *s) { - struct window *w; - u_int n; + struct winlink *wl; - if (s->window == NULL) + if (s->curw == NULL) return (-1); - w = window_next(&s->windows, s->window); - if (w == NULL) { - n = 0; - while ((w = ARRAY_ITEM(&s->windows, n)) == NULL) - n++; - if (w == s->window) - return (1); - } - if (w == s->window) - return (0); - s->last = s->window; - s->window = w; - session_cancelbell(s, w); + wl = winlink_next(&s->windows, s->curw); + if (wl == NULL) + wl = RB_MIN(winlinks, &s->windows); + if (wl == s->curw) + return (1); + s->lastw = s->curw; + s->curw = wl; + session_cancelbell(s, wl); return (0); } @@ -229,22 +235,19 @@ session_next(struct session *s) int session_previous(struct session *s) { - struct window *w; + struct winlink *wl; - if (s->window == NULL) + if (s->curw == NULL) return (-1); - w = window_previous(&s->windows, s->window); - if (w == NULL) { - w = ARRAY_LAST(&s->windows); - if (w == s->window) - return (1); - } - if (w == s->window) - return (0); - s->last = s->window; - s->window = w; - session_cancelbell(s, w); + wl = winlink_previous(&s->windows, s->curw); + if (wl == NULL) + wl = RB_MAX(winlinks, &s->windows); + if (wl == s->curw) + return (1); + s->lastw = s->curw; + s->curw = wl; + session_cancelbell(s, wl); return (0); } @@ -252,16 +255,16 @@ session_previous(struct session *s) int session_select(struct session *s, u_int i) { - struct window *w; + struct winlink *wl; - w = window_at(&s->windows, i); - if (w == NULL) + wl = winlink_find_by_index(&s->windows, i); + if (wl == NULL) return (-1); - if (w == s->window) - return (0); - s->last = s->window; - s->window = w; - session_cancelbell(s, w); + if (wl == s->curw) + return (1); + s->lastw = s->curw; + s->curw = wl; + session_cancelbell(s, wl); return (0); } @@ -269,16 +272,16 @@ session_select(struct session *s, u_int i) int session_last(struct session *s) { - struct window *w; + struct winlink *wl; - w = s->last; - if (w == NULL) + wl = s->lastw; + if (wl == NULL) return (-1); - if (w == s->window) + if (wl == s->curw) return (1); - s->last = s->window; - s->window = w; - session_cancelbell(s, w); + s->lastw = s->curw; + s->curw = wl; + session_cancelbell(s, wl); return (0); } @@ -1,4 +1,4 @@ -/* $Id: status.c,v 1.6 2007-10-12 12:37:48 nicm Exp $ */ +/* $Id: status.c,v 1.7 2007-10-26 12:29:07 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> @@ -27,11 +27,10 @@ void status_print(struct buffer *, size_t *, const char *, ...); void status_write(struct client *c) { - struct screen *s = &c->session->window->screen; + struct screen *s = &c->session->curw->window->screen; struct buffer *b = c->out; - struct window *w; + struct winlink *wl; size_t size; - u_int i; char flag; input_store_zero(b, CODE_CURSOROFF); @@ -39,19 +38,16 @@ status_write(struct client *c) input_store_two(b, CODE_ATTRIBUTES, 0, status_colour); size = c->sx; - for (i = 0; i < ARRAY_LENGTH(&c->session->windows); i++) { - w = ARRAY_ITEM(&c->session->windows, i); - if (w == NULL) - continue; - + RB_FOREACH(wl, winlinks, &c->session->windows) { flag = ' '; - if (w == c->session->last) + if (wl == c->session->lastw) flag = '-'; - if (w == c->session->window) + if (wl == c->session->curw) flag = '*'; - if (session_hasbell(c->session, w)) + if (session_hasbell(c->session, wl)) flag = '!'; - status_print(b, &size, "%u:%s%c ", i, w->name, flag); + status_print( + b, &size, "%u:%s%c ", wl->idx, wl->window->name, flag); if (size == 0) break; @@ -1,4 +1,4 @@ -/* $Id: tmux.h,v 1.70 2007-10-25 17:44:24 nicm Exp $ */ +/* $Id: tmux.h,v 1.71 2007-10-26 12:29:07 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> @@ -19,6 +19,9 @@ #ifndef TMUX_H #define TMUX_H +/* Shut up gcc warnings about empty if bodies. */ +#define RB_AUGMENT(x) do {} while (0) + #include <sys/param.h> #include <sys/tree.h> #include <sys/queue.h> @@ -385,9 +388,6 @@ struct input_ctx { ARRAY_DECL(, struct input_arg) args; }; -/* Input context macros. */ -#define INPUT_FLAGS(ictx) ((ictx)->flags) - /* Window structure. */ struct window { char *name; @@ -396,17 +396,26 @@ struct window { struct buffer *in; struct buffer *out; - u_int references; - struct input_ctx ictx; int flags; #define WINDOW_BELL 0x1 struct screen screen; + + u_int references; }; ARRAY_DECL(windows, struct window *); +/* Entry on local window list. */ +struct winlink { + int idx; + struct window *window; + + RB_ENTRY(winlink) entry; +}; +RB_HEAD(winlinks, winlink); + /* Client session. */ struct session { char *name; @@ -415,11 +424,11 @@ struct session { u_int sx; u_int sy; - struct window *window; - struct window *last; - struct windows windows; + struct winlink *curw; + struct winlink *lastw; + struct winlinks windows; - struct windows bells; /* windows with bells */ + ARRAY_DECL(, struct winlink *) bells; /* windows with bells */ #define SESSION_UNATTACHED 0x1 /* not attached to any clients */ int flags; @@ -665,33 +674,34 @@ void local_output(struct buffer *, size_t); /* window.c */ extern struct windows windows; +int window_cmp(struct window *, struct window *); +int winlink_cmp(struct winlink *, struct winlink *); +RB_PROTOTYPE(windows, window, entry, window_cmp); +RB_PROTOTYPE(winlinks, winli |