From 9e6090a7a2a0d25499bce0dc68fd67289f3a5e39 Mon Sep 17 00:00:00 2001 From: Nicholas Marriott Date: Tue, 3 Jun 2008 21:42:37 +0000 Subject: [PATCH] Per-session configuration options. --- CHANGES | 5 +- Makefile | 4 +- TODO | 5 ++ cmd-new-session.c | 14 +++-- cmd-new-window.c | 10 ++-- cmd-send-prefix.c | 7 ++- cmd-set-option.c | 81 +++++++++++++++++++++------ options.c | 139 ++++++++++++++++++++++++++++++++++++++++++++++ resize.c | 11 ++-- screen.c | 6 +- server-fn.c | 7 ++- server.c | 29 +++++----- session.c | 12 ++-- status.c | 12 ++-- tmux.c | 28 +++++----- tmux.h | 46 ++++++++++++--- window-copy.c | 7 ++- window-more.c | 7 ++- window-scroll.c | 7 ++- window.c | 8 +-- 20 files changed, 343 insertions(+), 102 deletions(-) create mode 100644 options.c diff --git a/CHANGES b/CHANGES index be14b9c0..efcd7ece 100644 --- a/CHANGES +++ b/CHANGES @@ -1,5 +1,8 @@ 03 June 2008 +* Per session options. Setting options without specifying a session sets the + global options as normal (global options are inherited by all sessions); + passing -c or -s will set the option only for that session. * Because a client has a session attached, any command needing a session can take a client and use its session. So, anything that used to accept -s now accepts -c as well. @@ -379,4 +382,4 @@ (including mutt, emacs). No status bar yet and no key remapping or other customisation. -$Id: CHANGES,v 1.102 2008-06-03 16:55:09 nicm Exp $ +$Id: CHANGES,v 1.103 2008-06-03 21:42:36 nicm Exp $ diff --git a/Makefile b/Makefile index bdc5c056..d9cc31bb 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.56 2008-06-03 05:10:38 nicm Exp $ +# $Id: Makefile,v 1.57 2008-06-03 21:42:37 nicm Exp $ .SUFFIXES: .c .o .y .h .PHONY: clean update-index.html upload-index.html @@ -29,7 +29,7 @@ SRCS= tmux.c server.c server-msg.c server-fn.c buffer.c buffer-poll.c status.c \ cmd-switch-client.c cmd-has-session.c cmd-scroll-mode.c cmd-copy-mode.c \ cmd-paste-buffer.c cmd-new-session.c cmd-start-server.c \ cmd-kill-server.c \ - window-scroll.c window-more.c window-copy.c \ + window-scroll.c window-more.c window-copy.c options.c \ tty.c tty-keys.c tty-write.c screen-write.c screen-redraw.c CC?= cc diff --git a/TODO b/TODO index c09b5668..1b48b24f 100644 --- a/TODO +++ b/TODO @@ -65,6 +65,11 @@ - different screen model? layers perhaps? hmm - cfg file improvements - select-window can become windowonly (what about default?) +- monitor for activity in windows as well as bell +- status bar customisation variables, date/time, show-activity, show-last-window + string-left, string-right - pass through strptime and print... +- per-window options (per-session list of window ranges?) +- show-options --- [18:20] *priteau* i found something in tmux that could be tweaked to be better diff --git a/cmd-new-session.c b/cmd-new-session.c index 66bf6a9f..59dcf792 100644 --- a/cmd-new-session.c +++ b/cmd-new-session.c @@ -1,4 +1,4 @@ -/* $Id: cmd-new-session.c,v 1.23 2008-06-03 05:35:51 nicm Exp $ */ +/* $Id: cmd-new-session.c,v 1.24 2008-06-03 21:42:37 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -113,7 +113,7 @@ cmd_new_session_exec(void *ptr, struct cmd_ctx *ctx) struct client *c = ctx->cmdclient; struct session *s; char *cmd, *cause; - u_int sx, sy; + u_int sx, sy, slines; if (ctx->flags & CMD_KEY) return; @@ -136,7 +136,7 @@ cmd_new_session_exec(void *ptr, struct cmd_ctx *ctx) cmd = data->cmd; if (cmd == NULL) - cmd = default_command; + cmd = options_get_string(&global_options, "default-command"); sx = 80; sy = 25; @@ -144,9 +144,11 @@ cmd_new_session_exec(void *ptr, struct cmd_ctx *ctx) sx = c->sx; sy = c->sy; } - if (sy < status_lines) - sy = status_lines + 1; - sy -= status_lines; + + slines = options_get_number(&global_options, "status-lines"); + if (sy < slines) + sy = slines + 1; + sy -= slines; if (!data->flag_detached && tty_open(&c->tty, &cause) != 0) { ctx->error(ctx, "%s", cause); diff --git a/cmd-new-window.c b/cmd-new-window.c index 8f09da0a..030847b5 100644 --- a/cmd-new-window.c +++ b/cmd-new-window.c @@ -1,4 +1,4 @@ -/* $Id: cmd-new-window.c,v 1.19 2008-06-03 16:55:09 nicm Exp $ */ +/* $Id: cmd-new-window.c,v 1.20 2008-06-03 21:42:37 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -138,13 +138,13 @@ cmd_new_window_exec(void *ptr, struct cmd_ctx *ctx) struct winlink *wl; char *cmd; - cmd = data->cmd; - if (cmd == NULL) - cmd = default_command; - if ((s = cmd_find_session(ctx, data->cname, data->sname)) == NULL) return; + cmd = data->cmd; + if (cmd == NULL) + cmd = options_get_string(&s->options, "default-command"); + if (data->idx < 0) data->idx = -1; wl = session_new(s, data->name, cmd, data->idx); diff --git a/cmd-send-prefix.c b/cmd-send-prefix.c index 87a8ba69..117ec4c2 100644 --- a/cmd-send-prefix.c +++ b/cmd-send-prefix.c @@ -1,4 +1,4 @@ -/* $Id: cmd-send-prefix.c,v 1.11 2008-06-03 16:55:09 nicm Exp $ */ +/* $Id: cmd-send-prefix.c,v 1.12 2008-06-03 21:42:37 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -41,12 +41,13 @@ const struct cmd_entry cmd_send_prefix_entry = { void cmd_send_prefix_exec(void *ptr, struct cmd_ctx *ctx) { + struct session *s; struct winlink *wl; - if ((wl = cmd_windowonly_get(ptr, ctx, NULL)) == NULL) + if ((wl = cmd_windowonly_get(ptr, ctx, &s)) == NULL) return; - window_key(wl->window, prefix_key); + window_key(wl->window, options_get_number(&s->options, "prefix-key")); if (ctx->cmdclient != NULL) server_write_client(ctx->cmdclient, MSG_EXIT, NULL, 0); diff --git a/cmd-set-option.c b/cmd-set-option.c index 45b8d1bd..3a47583f 100644 --- a/cmd-set-option.c +++ b/cmd-set-option.c @@ -1,4 +1,4 @@ -/* $Id: cmd-set-option.c,v 1.18 2008-06-03 05:35:51 nicm Exp $ */ +/* $Id: cmd-set-option.c,v 1.19 2008-06-03 21:42:37 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -35,13 +35,16 @@ void cmd_set_option_recv(void **, struct buffer *); void cmd_set_option_free(void *); struct cmd_set_option_data { + char *cname; + char *sname; + int flag_global; char *option; char *value; }; const struct cmd_entry cmd_set_option_entry = { "set-option", "set", - "option value", + "[-c client-tty|-s session-name] option value", 0, cmd_set_option_parse, cmd_set_option_exec, @@ -59,11 +62,28 @@ cmd_set_option_parse( int opt; *ptr = data = xmalloc(sizeof *data); + data->cname = NULL; + data->sname = NULL; + data->flag_global = 1; data->option = NULL; data->value = NULL; - while ((opt = getopt(argc, argv, "")) != EOF) { + while ((opt = getopt(argc, argv, "c:s:")) != EOF) { switch (opt) { + case 'c': + if (data->sname != NULL) + goto usage; + if (data->cname == NULL) + data->cname = xstrdup(optarg); + data->flag_global = 0; + break; + case 's': + if (data->cname != NULL) + goto usage; + if (data->sname == NULL) + data->sname = xstrdup(optarg); + data->flag_global = 0; + break; default: goto usage; } @@ -91,13 +111,22 @@ cmd_set_option_exec(void *ptr, unused struct cmd_ctx *ctx) { struct cmd_set_option_data *data = ptr; struct client *c; + struct session *s; + struct options *oo; const char *errstr; u_int i; int number, bool, key; + u_char colour; if (data == NULL) return; + if (data->flag_global || + ((s = cmd_find_session(ctx, data->cname, data->sname))) == NULL) + oo = &global_options; + else + oo = &s->options; + if (*data->option == '\0') { ctx->error(ctx, "invalid option"); return; @@ -127,13 +156,13 @@ cmd_set_option_exec(void *ptr, unused struct cmd_ctx *ctx) ctx->error(ctx, "unknown key: %s", data->value); return; } - prefix_key = key; + options_set_number(oo, "prefix-key", key); } else if (strcmp(data->option, "status") == 0) { if (bool == -1) { ctx->error(ctx, "bad value: %s", data->value); return; } - status_lines = bool; + options_set_number(oo, "status-lines", bool); recalculate_sizes(); } else if (strcmp(data->option, "status-fg") == 0) { if (data->value == NULL) { @@ -145,9 +174,13 @@ cmd_set_option_exec(void *ptr, unused struct cmd_ctx *ctx) ctx->error(ctx, "bad colour: %s", data->value); return; } - status_colour &= 0x0f; - status_colour |= number << 4; - if (status_lines > 0) { + + colour = options_get_number(oo, "status-colour"); + colour &= 0x0f; + colour |= number << 4; + options_set_number(oo, "status-colour", colour); + + if (options_get_number(oo, "status-lines") > 0) { for (i = 0; i < ARRAY_LENGTH(&clients); i++) { c = ARRAY_ITEM(&clients, i); if (c != NULL && c->session != NULL) @@ -164,9 +197,13 @@ cmd_set_option_exec(void *ptr, unused struct cmd_ctx *ctx) ctx->error(ctx, "bad colour: %s", data->value); return; } - status_colour &= 0xf0; - status_colour |= number; - if (status_lines > 0) { + + colour = options_get_number(oo, "status-colour"); + colour &= 0xf0; + colour |= number; + options_set_number(oo, "status-colour", colour); + + if (options_get_number(oo, "status-lines") > 0) { for (i = 0; i < ARRAY_LENGTH(&clients); i++) { c = ARRAY_ITEM(&clients, i); if (c != NULL && c->session != NULL) @@ -179,22 +216,22 @@ cmd_set_option_exec(void *ptr, unused struct cmd_ctx *ctx) return; } if (strcmp(data->value, "any") == 0) - bell_action = BELL_ANY; + number = BELL_ANY; else if (strcmp(data->value, "none") == 0) - bell_action = BELL_NONE; + number = BELL_NONE; else if (strcmp(data->value, "current") == 0) - bell_action = BELL_CURRENT; + number = BELL_CURRENT; else { ctx->error(ctx, "unknown bell-action: %s", data->value); return; } + options_set_number(oo, "bell-action", number); } else if (strcmp(data->option, "default-command") == 0) { if (data->value == NULL) { ctx->error(ctx, "invalid value"); return; } - xfree(default_command); - default_command = xstrdup(data->value); + options_set_string(oo, "default-command", "%s", data->value); } else if (strcmp(data->option, "history-limit") == 0) { if (data->value == NULL) { ctx->error(ctx, "invalid value"); @@ -204,7 +241,7 @@ cmd_set_option_exec(void *ptr, unused struct cmd_ctx *ctx) ctx->error(ctx, "history-limit too big: %u", number); return; } - history_limit = number; + options_set_number(oo, "history-limit", number); } else { ctx->error(ctx, "unknown option: %s", data->option); return; @@ -219,6 +256,9 @@ cmd_set_option_send(void *ptr, struct buffer *b) { struct cmd_set_option_data *data = ptr; + buffer_write(b, data, sizeof *data); + cmd_send_string(b, data->cname); + cmd_send_string(b, data->sname); cmd_send_string(b, data->option); cmd_send_string(b, data->value); } @@ -229,6 +269,9 @@ cmd_set_option_recv(void **ptr, struct buffer *b) struct cmd_set_option_data *data; *ptr = data = xmalloc(sizeof *data); + buffer_read(b, data, sizeof *data); + data->cname = cmd_recv_string(b); + data->sname = cmd_recv_string(b); data->option = cmd_recv_string(b); data->value = cmd_recv_string(b); } @@ -238,6 +281,10 @@ cmd_set_option_free(void *ptr) { struct cmd_set_option_data *data = ptr; + if (data->cname != NULL) + xfree(data->cname); + if (data->sname != NULL) + xfree(data->sname); if (data->option != NULL) xfree(data->option); if (data->value != NULL) diff --git a/options.c b/options.c new file mode 100644 index 00000000..69ad750c --- /dev/null +++ b/options.c @@ -0,0 +1,139 @@ +/* $Id: options.c,v 1.1 2008-06-03 21:42:37 nicm Exp $ */ + +/* + * Copyright (c) 2008 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" + +/* + * Option handling; each option has a name, type and value and is stored in + * a splay tree. + */ + +SPLAY_GENERATE(options_tree, options_entry, entry, options_cmp); + +int +options_cmp(struct options_entry *o1, struct options_entry *o2) +{ + return (strcmp(o1->name, o2->name)); +} + +void +options_init(struct options *oo, struct options *parent) +{ + SPLAY_INIT(&oo->tree); + oo->parent = parent; +} + +void +options_free(struct options *oo) +{ + struct options_entry *o; + + while (!SPLAY_EMPTY(&oo->tree)) { + o = SPLAY_ROOT(&oo->tree); + SPLAY_REMOVE(options_tree, &oo->tree, o); + xfree(o->name); + if (o->type == OPTIONS_STRING) + xfree(o->value.string); + xfree(o); + } +} + +void printflike3 +options_set_string(struct options *oo, const char *name, const char *fmt, ...) +{ + struct options_entry *o, p; + va_list ap; + + p.name = name; + o = SPLAY_FIND(options_tree, &oo->tree, &p); + if (o == NULL) { + o = xmalloc(sizeof *o); + o->name = xstrdup(name); + SPLAY_INSERT(options_tree, &oo->tree, o); + } else if (o->type == OPTIONS_STRING) + xfree(o->value.string); + + va_start(ap, fmt); + o->type = OPTIONS_STRING; + xvasprintf(&o->value.string, fmt, ap); + va_end(ap); +} + +char * +options_get_string(struct options *oo, const char *name) +{ + struct options_entry *o, p; + + p.name = name; + o = SPLAY_FIND(options_tree, &oo->tree, &p); + while (o == NULL) { + oo = oo->parent; + o = SPLAY_FIND(options_tree, &oo->tree, &p); + if (o != NULL) + break; + } + if (o == NULL) + fatalx("missing option"); + if (o->type != OPTIONS_STRING) + fatalx("option not a string"); + return (o->value.string); +} + +void +options_set_number(struct options *oo, const char *name, long long value) +{ + struct options_entry *o, p; + + p.name = name; + o = SPLAY_FIND(options_tree, &oo->tree, &p); + if (o == NULL) { + o = xmalloc(sizeof *o); + o->name = xstrdup(name); + SPLAY_INSERT(options_tree, &oo->tree, o); + } else if (o->type == OPTIONS_STRING) + xfree(o->value.string); + + o->type = OPTIONS_NUMBER; + o->value.number = value; + +} + +int +options_get_number(struct options *oo, const char *name) +{ + struct options_entry *o, p; + + p.name = name; + o = SPLAY_FIND(options_tree, &oo->tree, &p); + while (o == NULL) { + oo = oo->parent; + o = SPLAY_FIND(options_tree, &oo->tree, &p); + if (o != NULL) + break; + } + if (o == NULL) + fatalx("missing option"); + if (o->type != OPTIONS_NUMBER) + fatalx("option not a number"); + return (o->value.number); +} diff --git a/resize.c b/resize.c index 4999c432..c3be5719 100644 --- a/resize.c +++ b/resize.c @@ -1,4 +1,4 @@ -/* $Id: resize.c,v 1.10 2008-06-01 20:32:41 nicm Exp $ */ +/* $Id: resize.c,v 1.11 2008-06-03 21:42:37 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -48,7 +48,7 @@ recalculate_sizes(void) struct session *s; struct client *c; struct window *w; - u_int i, j, ssx, ssy; + u_int i, j, ssx, ssy, slines; for (i = 0; i < ARRAY_LENGTH(&sessions); i++) { s = ARRAY_ITEM(&sessions, i); @@ -73,9 +73,10 @@ recalculate_sizes(void) } s->flags &= ~SESSION_UNATTACHED; - if (ssy < status_lines) - ssy = status_lines + 1; - ssy -= status_lines; + slines = options_get_number(&s->options, "status-lines"); + if (ssy < slines) + ssy = slines + 1; + ssy -= slines; if (s->sx == ssx && s->sy == ssy) continue; diff --git a/screen.c b/screen.c index 432103cf..45ece4b7 100644 --- a/screen.c +++ b/screen.c @@ -1,4 +1,4 @@ -/* $Id: screen.c,v 1.59 2008-01-03 21:32:11 nicm Exp $ */ +/* $Id: screen.c,v 1.60 2008-06-03 21:42:37 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -128,7 +128,7 @@ screen_stringcolour(const char *s) /* Create a new screen. */ void -screen_create(struct screen *s, u_int dx, u_int dy) +screen_create(struct screen *s, u_int dx, u_int dy, u_int hlimit) { s->dx = dx; s->dy = dy; @@ -139,7 +139,7 @@ screen_create(struct screen *s, u_int dx, u_int dy) s->rlower = s->dy - 1; s->hsize = 0; - s->hlimit = history_limit; + s->hlimit = hlimit; s->attr = SCREEN_DEFATTR; s->colr = SCREEN_DEFCOLR; diff --git a/server-fn.c b/server-fn.c index cf55e238..0de4cbe0 100644 --- a/server-fn.c +++ b/server-fn.c @@ -1,4 +1,4 @@ -/* $Id: server-fn.c,v 1.37 2008-06-02 18:08:17 nicm Exp $ */ +/* $Id: server-fn.c,v 1.38 2008-06-03 21:42:37 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -182,6 +182,9 @@ server_write_message(struct client *c, const char *fmt, ...) va_list ap; char *msg; size_t size; + u_int slines; + + slines = options_get_number(&c->session->options, "status-lines"); screen_redraw_start_client(&ctx, c); screen_redraw_move_cursor(&ctx, 0, c->sy - 1); @@ -203,7 +206,7 @@ server_write_message(struct client *c, const char *fmt, ...) buffer_flush(c->tty.fd, c->tty.in, c->tty.out); usleep(750000); - if (status_lines == 0) { + if (slines == 0) { screen_redraw_lines(&ctx, c->sy - 1, 1); screen_redraw_stop(&ctx); } else { diff --git a/server.c b/server.c index 8264b155..49f98fc1 100644 --- a/server.c +++ b/server.c @@ -1,4 +1,4 @@ -/* $Id: server.c,v 1.48 2008-06-02 21:16:21 nicm Exp $ */ +/* $Id: server.c,v 1.49 2008-06-03 21:42:37 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -364,14 +364,15 @@ void server_handle_client(struct client *c) { struct window *w = c->session->curw->window; - int key; + int key, prefix; + prefix = options_get_number(&c->session->options, "prefix-key"); while (tty_keys_next(&c->tty, &key) == 0) { if (c->flags & CLIENT_PREFIX) { key_bindings_dispatch(key, c); c->flags &= ~CLIENT_PREFIX; continue; - } else if (key == prefix_key) + } else if (key == prefix) c->flags |= CLIENT_PREFIX; else window_key(w, key); @@ -413,21 +414,19 @@ server_handle_window(struct window *w) for (i = 0; i < ARRAY_LENGTH(&sessions); i++) { s = ARRAY_ITEM(&sessions, i); - if (s != NULL) - session_addbell(s, w); - } + if (s == NULL || !session_has(s, w)) + continue; + session_addbell(s, w); - switch (bell_action) { - case BELL_ANY: - tty_write_window(w, TTY_CHARACTER, '\007'); - break; - case BELL_CURRENT: - for (i = 0; i < ARRAY_LENGTH(&sessions); i++) { - s = ARRAY_ITEM(&sessions, i); - if (s != NULL && s->curw->window == w) + switch (options_get_number(&s->options, "bell-action")) { + case BELL_ANY: + tty_write_session(s, TTY_CHARACTER, '\007'); + break; + case BELL_CURRENT: + if (s->curw->window == w) tty_write_session(s, TTY_CHARACTER, '\007'); + break; } - break; } server_status_window(w); diff --git a/session.c b/session.c index 4bc52b75..0748c117 100644 --- a/session.c +++ b/session.c @@ -1,4 +1,4 @@ -/* $Id: session.c,v 1.32 2008-06-03 18:13:54 nicm Exp $ */ +/* $Id: session.c,v 1.33 2008-06-03 21:42:37 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -95,7 +95,8 @@ session_create(const char *name, const char *cmd, u_int sx, u_int sy) s->curw = s->lastw = NULL; RB_INIT(&s->windows); ARRAY_INIT(&s->bells); - + options_init(&s->options, &global_options); + s->sx = sx; s->sy = sy; @@ -137,6 +138,8 @@ session_destroy(struct session *s) while (!ARRAY_EMPTY(&sessions) && ARRAY_LAST(&sessions) == NULL) ARRAY_TRUNC(&sessions, 1); + options_free(&s->options); + while (!RB_EMPTY(&s->windows)) winlink_remove(&s->windows, RB_ROOT(&s->windows)); @@ -162,14 +165,15 @@ session_new(struct session *s, const char *name, const char *cmd, int idx) struct window *w; const char *env[] = { NULL, "TERM=screen", NULL }; char buf[256]; - u_int i; + u_int i, hlimit; if (session_index(s, &i) != 0) fatalx("session not found"); xsnprintf(buf, sizeof buf, "TMUX=%ld,%u", (long) getpid(), i); env[0] = buf; - if ((w = window_create(name, cmd, env, s->sx, s->sy)) == NULL) + hlimit = options_get_number(&s->options, "history-limit"); + if ((w = window_create(name, cmd, env, s->sx, s->sy, hlimit)) == NULL) return (NULL); return (session_attach(s, w, idx)); } diff --git a/status.c b/status.c index 8e215ea5..ca177874 100644 --- a/status.c +++ b/status.c @@ -1,4 +1,4 @@ -/* $Id: status.c,v 1.18 2008-01-03 21:32:11 nicm Exp $ */ +/* $Id: status.c,v 1.19 2008-06-03 21:42:37 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -30,13 +30,17 @@ status_write_client(struct client *c) struct screen_redraw_ctx ctx; struct winlink *wl; char flag; + u_char scolour; + u_int slines; - if (status_lines == 0 || c->sy <= status_lines) + scolour = options_get_number(&c->session->options, "status-colour"); + slines = options_get_number(&c->session->options, "status-lines"); + if (slines == 0 || c->sy <= slines) return; screen_redraw_start_client(&ctx, c); - screen_redraw_move_cursor(&ctx, 0, c->sy - status_lines); - screen_redraw_set_attributes(&ctx, 0, status_colour); + screen_redraw_move_cursor(&ctx, 0, c->sy - slines); + screen_redraw_set_attributes(&ctx, 0, scolour); RB_FOREACH(wl, winlinks, &c->session->windows) { flag = ' '; diff --git a/tmux.c b/tmux.c index 2c61d01c..8a8ebcdf 100644 --- a/tmux.c +++ b/tmux.c @@ -1,4 +1,4 @@ -/* $Id: tmux.c,v 1.50 2008-06-03 18:13:54 nicm Exp $ */ +/* $Id: tmux.c,v 1.51 2008-06-03 21:42:37 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -42,15 +42,12 @@ const char *_malloc_options = "AJX"; volatile sig_atomic_t sigwinch; volatile sig_atomic_t sigterm; + char *cfg_file; -char *default_command; +struct options global_options; char *paste_buffer; -int bell_action; + int debug_level; -int prefix_key = META; -u_char status_colour; -u_int history_limit; -u_int status_lines; void sighandler(int); __dead void usage(void); @@ -201,12 +198,12 @@ main(int argc, char **argv) log_open(stderr, LOG_USER, debug_level); siginit(); - status_lines = 1; - status_colour = 0x02; - - bell_action = BELL_ANY; - - history_limit = 2000; + options_init(&global_options, NULL); + options_set_number(&global_options, "status-lines", 1); + options_set_number(&global_options, "status-colour", 0x02); + options_set_number(&global_options, "bell-action", BELL_ANY); + options_set_number(&global_options, "history-limit", 2000); + options_set_number(&global_options, "prefix-key", META); paste_buffer = NULL; @@ -260,7 +257,8 @@ main(int argc, char **argv) if (shell == NULL || *shell == '\0') shell = _PATH_BSHELL; } - xasprintf(&default_command, "exec %s", shell); + options_set_string( + &global_options, "default-command", "exec %s", shell); if (argc == 0) { cmd = xmalloc(sizeof *cmd); @@ -334,7 +332,7 @@ main(int argc, char **argv) } out: - xfree(default_command); + options_free(&global_options); close(cctx.srv_fd); buffer_destroy(cctx.srv_in); diff --git a/tmux.h b/tmux.h index 1e635289..6a212fc4 100644 --- a/tmux.h +++ b/tmux.h @@ -1,4 +1,4 @@ -/* $Id: tmux.h,v 1.124 2008-06-03 18:13:54 nicm Exp $ */ +/* $Id: tmux.h,v 1.125 2008-06-03 21:42:37 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -533,6 +533,27 @@ struct winlink { }; RB_HEAD(winlinks, winlink); +/* Option data structures. */ +struct options_entry { + char *name; + + enum { + OPTIONS_STRING, + OPTIONS_NUMBER + } type; + union { + char *string; + long long number; + } value; + + SPLAY_ENTRY(options_entry) entry; +}; + +struct options { + SPLAY_HEAD(options_tree, options_entry) tree; + struct options *parent; +}; + /* Client session. */ struct session { char *name; @@ -545,6 +566,8 @@ struct session { struct winlink *lastw; struct winlinks windows; + struct options options; + ARRAY_DECL(, struct winlink *) bells; /* windows with bells */ #define SESSION_UNATTACHED 0x1 /* not attached to any clients */ @@ -685,15 +708,13 @@ extern volatile sig_atomic_t sigterm; #define BELL_NONE 0 #define BELL_ANY 1 #define BELL_CURRENT 2 +extern struct options global_options; extern char *default_command; extern char *cfg_file; extern char *paste_buffer; extern int bell_action; extern int debug_level; -extern int prefix_key; -extern u_char status_colour; extern u_int history_limit; -extern u_int status_lines; void logfile(const char *); void siginit(void); void sigreset(void); @@ -701,6 +722,17 @@ void sigreset(void); /* cfg.c */ int load_cfg(const char *, char **x); +/* options.c */ +int options_cmp(struct options_entry *, struct options_entry *); +SPLAY_PROTOTYPE(options_tree, options_entry, entry, options_cmp); +void options_init(struct options *, struct options *); +void options_free(struct options *); +void printflike3 options_set_string( + struct options *, const char *, const char *, ...); +char *options_get_string(struct options *, const char *); +void options_set_number(struct options *, const char *, long long); +int options_get_number(struct options *, const char *); + /* tty.c */ void tty_init(struct tty *, char *, char *); int tty_open(struct tty *, char **); @@ -937,7 +969,7 @@ void screen_redraw_lines(struct screen_redraw_ctx *, u_int, u_int); /* screen.c */ const char *screen_colourstring(u_char); u_char screen_stringcolour(const char *); -void screen_create(struct screen *, u_int, u_int); +void screen_create(struct screen *, u_int, u_int, u_int); void screen_destroy(struct screen *); void screen_resize(struct screen *, u_int, u_int); void screen_expand_line(struct screen *, u_int, u_int); @@ -967,8 +999,8 @@ 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); +struct window *window_create(const char *, + const char *, const char **, u_int, u_int, u_int); void window_destroy(struct window *); int window_resize(struct window *, u_int, u_int); int window_set_mode(struct window *, const struct window_mode *); diff --git a/window-copy.c b/window-copy.c index e61796e3..2129f1c1 100644 --- a/window-copy.c +++ b/window-copy.c @@ -1,4 +1,4 @@ -/* $Id: window-copy.c,v 1.15 2007-12-07 09:49:18 nicm Exp $ */ +/* $Id: window-copy.c,v 1.16 2008-06-03 21:42:37 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -91,7 +91,7 @@ window_copy_init(struct window *w) data->cy = w->base.cy; s = &data->screen; - screen_create(s, screen_size_x(&w->base), screen_size_y(&w->base)); + screen_create(s, screen_size_x(&w->base), screen_size_y(&w->base), 0); s->cx = data->cx; s->cy = data->cy; @@ -202,7 +202,8 @@ window_copy_write_line( size_t size; if (py == 0) { - screen_write_set_attributes(ctx, 0, status_colour); + screen_write_set_attributes( + ctx, ATTR_BRIGHT|ATTR_REVERSE, 0x70); screen_write_move_cursor(ctx, 0, 0); size = screen_write_put_string_rjust( ctx, "[%u,%u/%u]", data->ox, data->oy, w->base.hsize); diff --git a/window-more.c b/window-more.c index 51660445..fbb5b999 100644 --- a/window-more.c +++ b/window-more.c @@ -1,4 +1,4 @@ -/* $Id: window-more.c,v 1.10 2008-01-03 21:32:11 nicm Exp $ */ +/* $Id: window-more.c,v 1.11 2008-06-03 21:42:37 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -92,7 +92,7 @@ window_more_init(struct window *w) data->top = 0; s = &data->screen; - screen_create(s, screen_size_x(&w->base), screen_size_y(&w->base)); + screen_create(s, screen_size_x(&w->base), screen_size_y(&w->base), 0); s->mode &= ~MODE_CURSOR; return (s); @@ -171,7 +171,8 @@ window_more_write_line(struct window *w, struct screen_write_ctx *ctx, u_int py) size_t size; if (py == 0) { - screen_write_set_attributes(ctx, 0, status_colour); + screen_write_set_attributes( + ctx, ATTR_BRIGHT|ATTR_REVERSE, 0x70); screen_write_move_cursor(ctx, 0, 0); size = screen_write_put_string_rjust( ctx, "[%u/%u]", data->top, ARRAY_LENGTH(&data->list)); diff --git a/window-scroll.c b/window-scroll.c index 1e86ba09..9602bb87 100644 --- a/window-scroll.c +++ b/window-scroll.c @@ -1,4 +1,4 @@ -/* $Id: window-scroll.c,v 1.17 2008-01-03 21:32:11 nicm Exp $ */ +/* $Id: window-scroll.c,v 1.18 2008-06-03 21:42:37 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -65,7 +65,7 @@ window_scroll_init(struct window *w) data->oy = 0; s = &data->screen; - screen_create(s, screen_size_x(&w->base), screen_size_y(&w->base)); + screen_create(s, screen_size_x(&w->base), screen_size_y(&w->base), 0); s->mode &= ~MODE_CURSOR; screen_write_start(&ctx, s, NULL, NULL); @@ -153,7 +153,8 @@ window_scroll_write_line( size_t size; if (py == 0) { - screen_write_set_attributes(ctx, 0, status_colour); + screen_write_set_attributes( + ctx, ATTR_BRIGHT|ATTR_REVERSE, 0x70); screen_write_move_cursor(ctx, 0, 0); size = screen_write_put_string_rjust( ctx, "[%u,%u/%u]", data->ox, data->oy, w->base.hsize); diff --git a/window.c b/window.c index 1e270590..5ca72320 100644 --- a/window.c +++ b/window.c @@ -1,4 +1,4 @@ -/* $Id: window.c,v 1.37 2008-06-03 18:38:51 nicm Exp $ */ +/* $Id: window.c,v 1.38 2008-06-03 21:42:37 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -145,8 +145,8 @@ winlink_previous(unused struct winlinks *wwl, struct winlink *wl) } struct window * -window_create( - const char *name, const char *cmd, const char **env, u_int sx, u_int sy) +window_create(const char *name, + const char *cmd, const char **env, u_int sx, u_int sy, u_int hlimit) { struct window *w; struct winsize ws; @@ -186,7 +186,7 @@ window_create( w->in = buffer_create(BUFSIZ); w->out = buffer_create(BUFSIZ); w->mode = NULL; - screen_create(&w->base, sx, sy); + screen_create(&w->base, sx, sy, hlimit); w->screen = &w->base; input_init(w);