aboutsummaryrefslogtreecommitdiff
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, winlink, entry, winlink_cmp);
+struct winlink *winlink_find_by_index(struct winlinks *, int);
+struct winlink *winlink_find_by_window(struct winlinks *, struct window *);
+int winlink_next_index(struct winlinks *);
+struct winlink *winlink_add(struct winlinks *, struct window *, int);
+void winlink_remove(struct winlinks *, struct winlink *);
+struct winlink *winlink_next(struct winlinks *, struct winlink *);
+struct winlink *winlink_previous(struct winlinks *, struct winlink *);
struct window *window_create(
const char *, const char *, const char **, u_int, u_int);
-int window_index(struct windows *, struct window *, u_int *);
-void window_add(struct windows *, struct window *);
-void window_remove(struct windows *, struct window *);
void window_destroy(struct window *);
-struct window *window_next(struct windows *, struct window *);
-struct window *window_previous(struct windows *, struct window *);
-struct window *window_at(struct windows *, u_int);
int window_resize(struct window *, u_int, u_int);
-int window_poll(struct window *, struct pollfd *);
-void window_key(struct window *, int);
-void window_data(struct window *, struct buffer *);
/* session.c */
extern struct sessions sessions;
-void session_cancelbell(struct session *, struct window *);
+void session_cancelbell(struct session *, struct winlink *);
void session_addbell(struct session *, struct window *);
-int session_hasbell(struct session *, struct window *);
+int session_hasbell(struct session *, struct winlink *);
struct session *session_find(const char *);
struct session *session_create(const char *, const char *, u_int, u_int);
void session_destroy(struct session *);
int session_index(struct session *, u_int *);
-int session_new(
- struct session *, const char *, const char *, u_int *);
-void session_attach(struct session *, struct window *);
-int session_detach(struct session *, struct window *);
+struct winlink *session_new(struct session *, const char *, const char *, int);
+struct winlink *session_attach(struct session *, struct window *, int);
+int session_detach(struct session *, struct winlink *);
int session_has(struct session *, struct window *);
int session_next(struct session *);
int session_previous(struct session *);
diff --git a/window.c b/window.c
index 9420dab1..5965b5ed 100644
--- a/window.c
+++ b/window.c
@@ -1,4 +1,4 @@
-/* $Id: window.c,v 1.23 2007-10-24 15:29:29 nicm Exp $ */
+/* $Id: window.c,v 1.24 2007-10-26 12:29:07 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -22,6 +22,7 @@
#include <fcntl.h>
#include <paths.h>
#include <signal.h>
+#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <termios.h>
@@ -47,15 +48,109 @@
* Each window also has a "virtual" screen (screen.c) which contains the
* current state and is redisplayed when the window is reattached to a client.
*
- * A global list of windows is maintained, and a window may also be a member
- * of any number of sessions. A reference count is maintained and a window
- * removed from the global list and destroyed when it reaches zero.
+ * Windows are stored directly on a global array and wrapped in any number of
+ * winlink structs to be linked onto local session RB trees A reference count
+ * is maintained and a window removed from the global list and destroyed when
+ * it reaches zero
*/
/* Global window list. */
-struct windows windows;
+struct windows windows;
+
+RB_GENERATE(winlinks, winlink, entry, winlink_cmp);
+
+int
+winlink_cmp(struct winlink *wl1, struct winlink *wl2)
+{
+ return (wl1->idx - wl2->idx);
+}
+
+struct winlink *
+winlink_find_by_index(struct winlinks *wwl, int idx)
+{
+ struct winlink wl;
+
+ if (idx < 0)
+ fatalx("bad index");
+
+ wl.idx = idx;
+ return (RB_FIND(winlinks, wwl, &wl));
+}
+
+int
+winlink_next_index(struct winlinks *wwl)
+{
+ u_int i;
+
+ for (i = 0; i < INT_MAX; i++) {
+ if (winlink_find_by_index(wwl, i) == NULL)
+ return (i);
+ }
+
+ fatalx("no free indexes");
+}
+
+struct winlink *
+winlink_add(struct winlinks *wwl, struct window *w, int idx)
+{
+ struct winlink *wl;
+
+ if (idx == -1)
+ idx = winlink_next_index(wwl);
+ else if (winlink_find_by_index(wwl, idx) != NULL)
+ return (NULL);
+
+ if (idx < 0)
+ fatalx("bad index");
+
+ wl = xcalloc(1, sizeof *wl);
+ wl->idx = idx;
+ wl->window = w;
+ RB_INSERT(winlinks, wwl, wl);
+
+ w->references++;
+
+ return (wl);
+}
+
+void
+winlink_remove(struct winlinks *wwl, struct winlink *wl)
+{
+ struct window *w = wl->window;
+
+ RB_REMOVE(winlinks, wwl, wl);
+ xfree(wl);
+
+ if (w->references == 0)
+ fatal("bad reference count");
+ w->references--;
+ if (w->references == 0)
+ window_destroy(w);
+}
+
+struct winlink *
+winlink_next(unused struct winlinks *wwl, struct winlink *wl)
+{
+ return (RB_NEXT(winlinks, wwl, wl));
+}
+
+struct winlink *
+winlink_previous(struct winlinks *wwl, struct winlink *wl)
+{
+ struct winlink *wk;
+ int idx = wl->idx;
+
+ wk = NULL;
+ wl = RB_MIN(winlinks, wwl);
+ while (wl != NULL && wl->idx < idx) {
+ wk = wl;
+ wl = RB_NEXT(winlinks, wwl, wl);
+ }
+ if (wl == NULL)
+ return (NULL);
+ return (wk);
+}
-/* Create a new window. */
struct window *
window_create(
const char *name, const char *cmd, const char **environ, u_int sx, u_int sy)
@@ -92,10 +187,6 @@ window_create(
if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1)
fatal("fcntl failed");
- mode = 1;
- if (ioctl(fd, TIOCPKT, &mode) == -1)
- fatal("ioctl failed");
-
w = xmalloc(sizeof *w);
w->fd = fd;
w->in = buffer_create(BUFSIZ);
@@ -126,60 +217,23 @@ window_create(
} else
w->name = xstrdup(name);
- window_add(&windows, w);
- w->references = 1;
+ ARRAY_ADD(&windows, w);
+ w->references = 0;
return (w);
}
-/* Find window index in list. */
-int
-window_index(struct windows *ww, struct window *w, u_int *i)
-{
- for (*i = 0; *i < ARRAY_LENGTH(ww); (*i)++) {
- if (w == ARRAY_ITEM(ww, *i))
- return (0);
- }
- return (-1);
-}
-
-/* Add a window to a list. */
-void
-window_add(struct windows *ww, struct window *w)
-{
- u_int i;
-
- if (window_index(ww, NULL, &i) != 0)
- ARRAY_ADD(ww, w);
- else
- ARRAY_SET(ww, i, w);
-
- w->references++;
-}
-
-/* Remove a window from a list. */
void
-window_remove(struct windows *ww, struct window *w)
+window_destroy(struct window *w)
{
u_int i;
- if (window_index(ww, w, &i) != 0)
- fatalx("window not found");
- ARRAY_SET(ww, i, NULL);
- while (!ARRAY_EMPTY(ww) && ARRAY_LAST(ww) == NULL)
- ARRAY_TRUNC(ww, 1);
-
- w->references--;
- if (w->references == 0)
- window_destroy(w);
- if (w->references == 1)
- window_remove(&windows, w);
-}
-
-/* Destroy a window. */
-void
-window_destroy(struct window *w)
-{
+ for (i = 0; i < ARRAY_LENGTH(&windows); i++) {
+ if (ARRAY_ITEM(&windows, i) == w)
+ break;
+ }
+ ARRAY_REMOVE(&windows, i);
+
close(w->fd);
input_free(w);
@@ -193,55 +247,6 @@ window_destroy(struct window *w)
xfree(w);
}
-/* Locate next window in list. */
-struct window *
-window_next(struct windows *ww, struct window *w)
-{
- u_int i;
-
- if (window_index(ww, w, &i) != 0)
- fatalx("window not found");
-
- if (i == ARRAY_LENGTH(ww) - 1)
- return (NULL);
- do {
- i++;
- w = window_at(ww, i);
- if (w != NULL)
- return (w);
- } while (i != ARRAY_LENGTH(ww) - 1);
- return (NULL);
-}
-
-/* Locate previous window in list. */
-struct window *
-window_previous(struct windows *ww, struct window *w)
-{
- u_int i;
-
- if (window_index(ww, w, &i) != 0)
- fatalx("window not found");
- if (i == 0)
- return (NULL);
- do {
- i--;
- w = window_at(ww, i);
- if (w != NULL)
- return (w);
- } while (i != 0);
- return (NULL);
-}
-
-/* Locate window at specific position in list. */
-struct window *
-window_at(struct windows *ww, u_int i)
-{
- if (i >= ARRAY_LENGTH(ww))
- return (NULL);
- return (ARRAY_ITEM(ww, i));
-}
-
-/* Resize a window. */
int
window_resize(struct window *w, u_int sx, u_int sy)
{
@@ -261,51 +266,3 @@ window_resize(struct window *w, u_int sx, u_int sy)
return (0);
}
-/* Handle window poll results. This is special because of TIOCPKT. */
-int
-window_poll(struct window *w, struct pollfd *pfd)
-{
- struct termios tio;
- size_t size;
- u_char *ptr;
-
- size = BUFFER_USED(w->in);
- if (buffer_poll(pfd, w->in, w->out) != 0)
- return (-1);
-
- if (BUFFER_USED(w->in) == size)
- return (0);
- ptr = BUFFER_IN(w->in) - (BUFFER_USED(w->in) - size);
-
- log_debug("window packet: %hhu", *ptr);
- switch (*ptr) {
- case TIOCPKT_DATA:
- case TIOCPKT_FLUSHREAD:
- case TIOCPKT_FLUSHWRITE:
- case TIOCPKT_STOP:
- case TIOCPKT_START:
- case TIOCPKT_DOSTOP:
- case TIOCPKT_NOSTOP:
- buffer_delete_range(w->in, size, 1);
- break;
- case TIOCPKT_IOCTL:
- buffer_delete_range(w->in, size, 1 + sizeof tio);
- break;
- }
-
- return (0);
-}
-
-/* Process window key. */
-void
-window_key(struct window *w, int key)
-{
- input_translate_key(w->out, key);
-}
-
-/* Process output data from child process. */
-void
-window_data(struct window *w, struct buffer *b)
-{
- input_parse(w, b);
-}