summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CHANGES9
-rw-r--r--TODO3
-rw-r--r--cmd-kill-window.c10
-rw-r--r--cmd-list-sessions.c11
-rw-r--r--cmd-list-windows.c19
-rw-r--r--cmd-new-session.c6
-rw-r--r--cmd-new-window.c29
-rw-r--r--cmd-rename-window.c12
-rw-r--r--cmd-select-window.c12
-rw-r--r--cmd-send-prefix.c4
-rw-r--r--key-bindings.c4
-rw-r--r--server-fn.c21
-rw-r--r--server-msg.c4
-rw-r--r--server.c34
-rw-r--r--session.c173
-rw-r--r--status.c22
-rw-r--r--tmux.h60
-rw-r--r--window.c263
18 files changed, 347 insertions, 349 deletions
diff --git a/CHANGES b/CHANGES
index a7e64ead..a7b1470d 100644
--- a/CHANGES
+++ b/CHANGES
@@ -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 $
diff --git a/TODO b/TODO
index d58f333e..f40aa2a2 100644
--- a/TODO
+++ b/TODO
@@ -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);
diff --git a/server.c b/server.c
index 877724fd..81c0cddd 100644
--- a/server.c
+++ b/server.c
@@ -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;
}
}
diff --git a/session.c b/session.c
index c55542e4..54067a5b 100644
--- a/session.c
+++ b/session.c
@@ -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);
}
diff --git a/status.c b/status.c
index 3d1758b9..0f1b5680 100644
--- a/status.c
+++ b/status.c
@@ -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;
diff --git a/tmux.h b/tmux.h
index fc02963c..be4ed5e1 100644
--- a/tmux.h
+++ b/tmux.h
@@ -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