Merge branch 'obsd-master'

Conflicts:
	client.c
	tmux.1
	tmux.c
This commit is contained in:
Thomas Adam 2015-06-07 23:42:25 +01:00
commit 7acc4addb5
20 changed files with 624 additions and 266 deletions

2
cfg.c
View File

@ -107,7 +107,7 @@ cfg_default_done(unused struct cmd_q *cmdq)
*/ */
if (!TAILQ_EMPTY(&cfg_client->cmdq->queue)) if (!TAILQ_EMPTY(&cfg_client->cmdq->queue))
cmdq_continue(cfg_client->cmdq); cmdq_continue(cfg_client->cmdq);
cfg_client->references--; server_client_unref(cfg_client);
cfg_client = NULL; cfg_client = NULL;
} }
} }

View File

@ -222,7 +222,7 @@ client_main(int argc, char **argv, int flags)
cmdflags = CMD_STARTSERVER; cmdflags = CMD_STARTSERVER;
} else if (argc == 0) { } else if (argc == 0) {
msg = MSG_COMMAND; msg = MSG_COMMAND;
cmdflags = CMD_STARTSERVER|CMD_CANTNEST; cmdflags = CMD_STARTSERVER;
} else { } else {
msg = MSG_COMMAND; msg = MSG_COMMAND;
@ -240,24 +240,10 @@ client_main(int argc, char **argv, int flags)
TAILQ_FOREACH(cmd, &cmdlist->list, qentry) { TAILQ_FOREACH(cmd, &cmdlist->list, qentry) {
if (cmd->entry->flags & CMD_STARTSERVER) if (cmd->entry->flags & CMD_STARTSERVER)
cmdflags |= CMD_STARTSERVER; cmdflags |= CMD_STARTSERVER;
if (cmd->entry->flags & CMD_CANTNEST)
cmdflags |= CMD_CANTNEST;
} }
cmd_list_free(cmdlist); cmd_list_free(cmdlist);
} }
/*
* Check if this could be a nested session, if the command can't nest:
* if the socket path matches $TMUX, this is probably the same server.
*/
if (shell_cmd == NULL && environ_path != NULL &&
(cmdflags & CMD_CANTNEST) &&
strcmp(socket_path, environ_path) == 0) {
fprintf(stderr, "sessions should be nested with care, "
"unset $TMUX to force\n");
return (1);
}
/* Establish signal handlers. */ /* Establish signal handlers. */
set_signals(client_signal); set_signals(client_signal);

View File

@ -34,18 +34,18 @@ enum cmd_retval cmd_attach_session_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_attach_session_entry = { const struct cmd_entry cmd_attach_session_entry = {
"attach-session", "attach", "attach-session", "attach",
"c:drt:", 0, 0, "c:dErt:", 0, 0,
"[-dr] [-c working-directory] " CMD_TARGET_SESSION_USAGE, "[-dEr] [-c working-directory] " CMD_TARGET_SESSION_USAGE,
CMD_CANTNEST|CMD_STARTSERVER, CMD_STARTSERVER,
cmd_attach_session_exec cmd_attach_session_exec
}; };
enum cmd_retval enum cmd_retval
cmd_attach_session(struct cmd_q *cmdq, const char *tflag, int dflag, int rflag, cmd_attach_session(struct cmd_q *cmdq, const char *tflag, int dflag, int rflag,
const char *cflag) const char *cflag, int Eflag)
{ {
struct session *s; struct session *s;
struct client *c; struct client *c = cmdq->client, *c_loop;
struct winlink *wl = NULL; struct winlink *wl = NULL;
struct window *w = NULL; struct window *w = NULL;
struct window_pane *wp = NULL; struct window_pane *wp = NULL;
@ -79,8 +79,13 @@ cmd_attach_session(struct cmd_q *cmdq, const char *tflag, int dflag, int rflag,
wl = winlink_find_by_window(&s->windows, w); wl = winlink_find_by_window(&s->windows, w);
} }
if (cmdq->client == NULL) if (c == NULL)
return (CMD_RETURN_NORMAL); return (CMD_RETURN_NORMAL);
if (server_client_check_nested(c)) {
cmdq_error(cmdq, "sessions should be nested with care, "
"unset $TMUX to force");
return (CMD_RETURN_ERROR);
}
if (wl != NULL) { if (wl != NULL) {
if (wp != NULL) if (wp != NULL)
@ -88,18 +93,18 @@ cmd_attach_session(struct cmd_q *cmdq, const char *tflag, int dflag, int rflag,
session_set_current(s, wl); session_set_current(s, wl);
} }
if (cmdq->client->session != NULL) { if (c->session != NULL) {
if (dflag) { if (dflag) {
/* /*
* Can't use server_write_session in case attaching to * Can't use server_write_session in case attaching to
* the same session as currently attached to. * the same session as currently attached to.
*/ */
TAILQ_FOREACH(c, &clients, entry) { TAILQ_FOREACH(c_loop, &clients, entry) {
if (c->session != s || c == cmdq->client) if (c_loop->session != s || c == c)
continue; continue;
server_write_client(c, MSG_DETACH, server_write_client(c, MSG_DETACH,
c->session->name, c_loop->session->name,
strlen(c->session->name) + 1); strlen(c_loop->session->name) + 1);
} }
} }
@ -121,13 +126,13 @@ cmd_attach_session(struct cmd_q *cmdq, const char *tflag, int dflag, int rflag,
s->cwd = fd; s->cwd = fd;
} }
cmdq->client->session = s; c->session = s;
notify_attached_session_changed(cmdq->client); notify_attached_session_changed(c);
session_update_activity(s); session_update_activity(s);
server_redraw_client(cmdq->client); server_redraw_client(c);
s->curw->flags &= ~WINLINK_ALERTFLAGS; s->curw->flags &= ~WINLINK_ALERTFLAGS;
} else { } else {
if (server_client_open(cmdq->client, &cause) != 0) { if (server_client_open(c, &cause) != 0) {
cmdq_error(cmdq, "open terminal failed: %s", cause); cmdq_error(cmdq, "open terminal failed: %s", cause);
free(cause); free(cause);
return (CMD_RETURN_ERROR); return (CMD_RETURN_ERROR);
@ -152,23 +157,26 @@ cmd_attach_session(struct cmd_q *cmdq, const char *tflag, int dflag, int rflag,
} }
if (rflag) if (rflag)
cmdq->client->flags |= CLIENT_READONLY; c->flags |= CLIENT_READONLY;
if (dflag) { if (dflag) {
server_write_session(s, MSG_DETACH, s->name, server_write_session(s, MSG_DETACH, s->name,
strlen(s->name) + 1); strlen(s->name) + 1);
} }
update = options_get_string(&s->options, "update-environment"); if (!Eflag) {
environ_update(update, &cmdq->client->environ, &s->environ); update = options_get_string(&s->options,
"update-environment");
environ_update(update, &c->environ, &s->environ);
}
cmdq->client->session = s; c->session = s;
notify_attached_session_changed(cmdq->client); notify_attached_session_changed(c);
session_update_activity(s); session_update_activity(s);
server_redraw_client(cmdq->client); server_redraw_client(c);
s->curw->flags &= ~WINLINK_ALERTFLAGS; s->curw->flags &= ~WINLINK_ALERTFLAGS;
server_write_ready(cmdq->client); server_write_ready(c);
cmdq->client_exit = 0; cmdq->client_exit = 0;
} }
recalculate_sizes(); recalculate_sizes();
@ -183,5 +191,6 @@ cmd_attach_session_exec(struct cmd *self, struct cmd_q *cmdq)
struct args *args = self->args; struct args *args = self->args;
return (cmd_attach_session(cmdq, args_get(args, 't'), return (cmd_attach_session(cmdq, args_get(args, 't'),
args_has(args, 'd'), args_has(args, 'r'), args_get(args, 'c'))); args_has(args, 'd'), args_has(args, 'r'), args_get(args, 'c'),
args_has(args, 'E')));
} }

View File

@ -117,7 +117,7 @@ cmd_confirm_before_free(void *data)
struct cmd_confirm_before_data *cdata = data; struct cmd_confirm_before_data *cdata = data;
struct client *c = cdata->client; struct client *c = cdata->client;
c->references--; server_client_unref(c);
free(cdata->cmd); free(cdata->cmd);
free(cdata); free(cdata);

View File

@ -29,6 +29,8 @@
#define CMD_FIND_QUIET 0x2 #define CMD_FIND_QUIET 0x2
#define CMD_FIND_WINDOW_INDEX 0x4 #define CMD_FIND_WINDOW_INDEX 0x4
#define CMD_FIND_DEFAULT_MARKED 0x8 #define CMD_FIND_DEFAULT_MARKED 0x8
#define CMD_FIND_EXACT_SESSION 0x10
#define CMD_FIND_EXACT_WINDOW 0x20
enum cmd_find_type { enum cmd_find_type {
CMD_FIND_PANE, CMD_FIND_PANE,
@ -380,6 +382,10 @@ cmd_find_get_session(struct cmd_find_state *fs, const char *session)
if (fs->s != NULL) if (fs->s != NULL)
return (0); return (0);
/* Stop now if exact only. */
if (fs->flags & CMD_FIND_EXACT_SESSION)
return (-1);
/* Otherwise look for prefix. */ /* Otherwise look for prefix. */
s = NULL; s = NULL;
RB_FOREACH(s_loop, sessions, &sessions) { RB_FOREACH(s_loop, sessions, &sessions) {
@ -454,10 +460,11 @@ cmd_find_get_window_with_session(struct cmd_find_state *fs, const char *window)
{ {
struct winlink *wl; struct winlink *wl;
const char *errstr; const char *errstr;
int idx, n; int idx, n, exact;
struct session *s; struct session *s;
log_debug("%s: %s", __func__, window); log_debug("%s: %s", __func__, window);
exact = (fs->flags & CMD_FIND_EXACT_WINDOW);
/* Check for window ids starting with @. */ /* Check for window ids starting with @. */
if (*window == '@') { if (*window == '@') {
@ -468,7 +475,7 @@ cmd_find_get_window_with_session(struct cmd_find_state *fs, const char *window)
} }
/* Try as an offset. */ /* Try as an offset. */
if (window[0] == '+' || window[0] == '-') { if (!exact && (window[0] == '+' || window[0] == '-')) {
if (window[1] != '\0') if (window[1] != '\0')
n = strtonum(window + 1, 1, INT_MAX, NULL); n = strtonum(window + 1, 1, INT_MAX, NULL);
else else
@ -498,40 +505,44 @@ cmd_find_get_window_with_session(struct cmd_find_state *fs, const char *window)
} }
/* Try special characters. */ /* Try special characters. */
if (strcmp(window, "!") == 0) { if (!exact) {
fs->wl = TAILQ_FIRST(&fs->s->lastw); if (strcmp(window, "!") == 0) {
if (fs->wl == NULL) fs->wl = TAILQ_FIRST(&fs->s->lastw);
return (-1); if (fs->wl == NULL)
fs->idx = fs->wl->idx; return (-1);
fs->w = fs->wl->window; fs->idx = fs->wl->idx;
return (0); fs->w = fs->wl->window;
} else if (strcmp(window, "^") == 0) { return (0);
fs->wl = RB_MIN(winlinks, &fs->s->windows); } else if (strcmp(window, "^") == 0) {
if (fs->wl == NULL) fs->wl = RB_MIN(winlinks, &fs->s->windows);
return (-1); if (fs->wl == NULL)
fs->idx = fs->wl->idx; return (-1);
fs->w = fs->wl->window; fs->idx = fs->wl->idx;
return (0); fs->w = fs->wl->window;
} else if (strcmp(window, "$") == 0) { return (0);
fs->wl = RB_MAX(winlinks, &fs->s->windows); } else if (strcmp(window, "$") == 0) {
if (fs->wl == NULL) fs->wl = RB_MAX(winlinks, &fs->s->windows);
return (-1); if (fs->wl == NULL)
fs->idx = fs->wl->idx; return (-1);
fs->w = fs->wl->window; fs->idx = fs->wl->idx;
return (0); fs->w = fs->wl->window;
return (0);
}
} }
/* First see if this is a valid window index in this session. */ /* First see if this is a valid window index in this session. */
idx = strtonum(window, 0, INT_MAX, &errstr); if (window[0] != '+' && window[0] != '-') {
if (errstr == NULL) { idx = strtonum(window, 0, INT_MAX, &errstr);
if (fs->flags & CMD_FIND_WINDOW_INDEX) { if (errstr == NULL) {
fs->idx = idx; if (fs->flags & CMD_FIND_WINDOW_INDEX) {
return (0); fs->idx = idx;
} return (0);
fs->wl = winlink_find_by_index(&fs->s->windows, idx); }
if (fs->wl != NULL) { fs->wl = winlink_find_by_index(&fs->s->windows, idx);
fs->w = fs->wl->window; if (fs->wl != NULL) {
return (0); fs->w = fs->wl->window;
return (0);
}
} }
} }
@ -550,6 +561,11 @@ cmd_find_get_window_with_session(struct cmd_find_state *fs, const char *window)
return (0); return (0);
} }
/* Stop now if exact only. */
if (exact)
return (-1);
/* Try as the start of a window name, error if multiple. */ /* Try as the start of a window name, error if multiple. */
fs->wl = NULL; fs->wl = NULL;
RB_FOREACH(wl, winlinks, &fs->s->windows) { RB_FOREACH(wl, winlinks, &fs->s->windows) {
@ -867,6 +883,16 @@ cmd_find_target(struct cmd_q *cmdq, const char *target, enum cmd_find_type type,
} }
} }
/* Set exact match flags. */
if (session != NULL && *session == '=') {
session++;
fs.flags |= CMD_FIND_EXACT_SESSION;
}
if (window != NULL && *window == '=') {
window++;
fs.flags |= CMD_FIND_EXACT_WINDOW;
}
/* Empty is the same as NULL. */ /* Empty is the same as NULL. */
if (session != NULL && *session == '\0') if (session != NULL && *session == '\0')
session = NULL; session = NULL;

View File

@ -132,7 +132,7 @@ cmd_load_buffer_callback(struct client *c, int closed, void *data)
return; return;
c->stdin_callback = NULL; c->stdin_callback = NULL;
c->references--; server_client_unref(c);
if (c->flags & CLIENT_DEAD) if (c->flags & CLIENT_DEAD)
return; return;

View File

@ -37,11 +37,11 @@ enum cmd_retval cmd_new_session_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_new_session_entry = { const struct cmd_entry cmd_new_session_entry = {
"new-session", "new", "new-session", "new",
"Ac:dDF:n:Ps:t:x:y:", 0, -1, "Ac:dDEF:n:Ps:t:x:y:", 0, -1,
"[-AdDP] [-c start-directory] [-F format] [-n window-name] " "[-AdDEP] [-c start-directory] [-F format] [-n window-name] "
"[-s session-name] " CMD_TARGET_SESSION_USAGE " [-x width] " "[-s session-name] " CMD_TARGET_SESSION_USAGE " [-x width] "
"[-y height] [command]", "[-y height] [command]",
CMD_STARTSERVER|CMD_CANTNEST, CMD_STARTSERVER,
cmd_new_session_exec cmd_new_session_exec
}; };
@ -91,7 +91,8 @@ cmd_new_session_exec(struct cmd *self, struct cmd_q *cmdq)
if (session_find(newname) != NULL) { if (session_find(newname) != NULL) {
if (args_has(args, 'A')) { if (args_has(args, 'A')) {
return (cmd_attach_session(cmdq, newname, return (cmd_attach_session(cmdq, newname,
args_has(args, 'D'), 0, NULL)); args_has(args, 'D'), 0, NULL,
args_has(args, 'E')));
} }
cmdq_error(cmdq, "duplicate session: %s", newname); cmdq_error(cmdq, "duplicate session: %s", newname);
return (CMD_RETURN_ERROR); return (CMD_RETURN_ERROR);
@ -145,15 +146,20 @@ cmd_new_session_exec(struct cmd *self, struct cmd_q *cmdq)
} }
/* /*
* Save the termios settings, part of which is used for new windows in * If this is a new client, check for nesting and save the termios
* this session. * settings (part of which is used for new windows in this session).
* *
* This is read again with tcgetattr() rather than using tty.tio as if * tcgetattr() is used rather than using tty.tio since if the client is
* detached, tty_open won't be called. Because of this, it must be done * detached, tty_open won't be called. It must be done before opening
* before opening the terminal as that calls tcsetattr() to prepare for * the terminal as that calls tcsetattr() to prepare for tmux taking
* tmux taking over. * over.
*/ */
if (!detached && !already_attached && c->tty.fd != -1) { if (!detached && !already_attached && c->tty.fd != -1) {
if (server_client_check_nested(cmdq->client)) {
cmdq_error(cmdq, "sessions should be nested with care, "
"unset $TMUX to force");
return (CMD_RETURN_ERROR);
}
if (tcgetattr(c->tty.fd, &tio) != 0) if (tcgetattr(c->tty.fd, &tio) != 0)
fatal("tcgetattr failed"); fatal("tcgetattr failed");
tiop = &tio; tiop = &tio;
@ -225,9 +231,11 @@ cmd_new_session_exec(struct cmd *self, struct cmd_q *cmdq)
/* Construct the environment. */ /* Construct the environment. */
environ_init(&env); environ_init(&env);
update = options_get_string(&global_s_options, "update-environment"); if (c != NULL && !args_has(args, 'E')) {
if (c != NULL) update = options_get_string(&global_s_options,
"update-environment");
environ_update(update, &c->environ, &env); environ_update(update, &c->environ, &env);
}
/* Create the new session. */ /* Create the new session. */
idx = -1 - options_get_number(&global_s_options, "base-index"); idx = -1 - options_get_number(&global_s_options, "base-index");

View File

@ -31,8 +31,8 @@ enum cmd_retval cmd_switch_client_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_switch_client_entry = { const struct cmd_entry cmd_switch_client_entry = {
"switch-client", "switchc", "switch-client", "switchc",
"lc:npt:rT:", 0, 0, "lc:Enpt:rT:", 0, 0,
"[-lnpr] [-c target-client] [-t target-session] [-T key-table]", "[-Elnpr] [-c target-client] [-t target-session] [-T key-table]",
CMD_READONLY, CMD_READONLY,
cmd_switch_client_exec cmd_switch_client_exec
}; };
@ -119,7 +119,7 @@ cmd_switch_client_exec(struct cmd *self, struct cmd_q *cmdq)
} }
} }
if (c != NULL && s != c->session) { if (c != NULL && s != c->session && !args_has(args, 'E')) {
update = options_get_string(&s->options, "update-environment"); update = options_get_string(&s->options, "update-environment");
environ_update(update, &c->environ, &s->environ); environ_update(update, &c->environ, &s->environ);
} }

392
colour.c
View File

@ -29,91 +29,305 @@
* of the 256 colour palette. * of the 256 colour palette.
*/ */
/* An RGB colour. */
struct colour_rgb { struct colour_rgb {
u_char i;
u_char r; u_char r;
u_char g; u_char g;
u_char b; u_char b;
}; };
/* 256 colour RGB table, generated on first use. */ const struct colour_rgb colour_from_256[] = {
struct colour_rgb *colour_rgb_256; { 0, 0x00, 0x00, 0x00 }, { 1, 0x00, 0x00, 0x5f },
{ 2, 0x00, 0x00, 0x87 }, { 3, 0x00, 0x00, 0xaf },
{ 4, 0x00, 0x00, 0xd7 }, { 5, 0x00, 0x00, 0xff },
{ 6, 0x00, 0x5f, 0x00 }, { 7, 0x00, 0x5f, 0x5f },
{ 8, 0x00, 0x5f, 0x87 }, { 9, 0x00, 0x5f, 0xaf },
{ 10, 0x00, 0x5f, 0xd7 }, { 11, 0x00, 0x5f, 0xff },
{ 12, 0x00, 0x87, 0x00 }, { 13, 0x00, 0x87, 0x5f },
{ 14, 0x00, 0x87, 0x87 }, { 15, 0x00, 0x87, 0xaf },
{ 16, 0x00, 0x87, 0xd7 }, { 17, 0x00, 0x87, 0xff },
{ 18, 0x00, 0xaf, 0x00 }, { 19, 0x00, 0xaf, 0x5f },
{ 20, 0x00, 0xaf, 0x87 }, { 21, 0x00, 0xaf, 0xaf },
{ 22, 0x00, 0xaf, 0xd7 }, { 23, 0x00, 0xaf, 0xff },
{ 24, 0x00, 0xd7, 0x00 }, { 25, 0x00, 0xd7, 0x5f },
{ 26, 0x00, 0xd7, 0x87 }, { 27, 0x00, 0xd7, 0xaf },
{ 28, 0x00, 0xd7, 0xd7 }, { 29, 0x00, 0xd7, 0xff },
{ 30, 0x00, 0xff, 0x00 }, { 31, 0x00, 0xff, 0x5f },
{ 32, 0x00, 0xff, 0x87 }, { 33, 0x00, 0xff, 0xaf },
{ 34, 0x00, 0xff, 0xd7 }, { 35, 0x00, 0xff, 0xff },
{ 36, 0x5f, 0x00, 0x00 }, { 37, 0x5f, 0x00, 0x5f },
{ 38, 0x5f, 0x00, 0x87 }, { 39, 0x5f, 0x00, 0xaf },
{ 40, 0x5f, 0x00, 0xd7 }, { 41, 0x5f, 0x00, 0xff },
{ 42, 0x5f, 0x5f, 0x00 }, { 43, 0x5f, 0x5f, 0x5f },
{ 44, 0x5f, 0x5f, 0x87 }, { 45, 0x5f, 0x5f, 0xaf },
{ 46, 0x5f, 0x5f, 0xd7 }, { 47, 0x5f, 0x5f, 0xff },
{ 48, 0x5f, 0x87, 0x00 }, { 49, 0x5f, 0x87, 0x5f },
{ 50, 0x5f, 0x87, 0x87 }, { 51, 0x5f, 0x87, 0xaf },
{ 52, 0x5f, 0x87, 0xd7 }, { 53, 0x5f, 0x87, 0xff },
{ 54, 0x5f, 0xaf, 0x00 }, { 55, 0x5f, 0xaf, 0x5f },
{ 56, 0x5f, 0xaf, 0x87 }, { 57, 0x5f, 0xaf, 0xaf },
{ 58, 0x5f, 0xaf, 0xd7 }, { 59, 0x5f, 0xaf, 0xff },
{ 60, 0x5f, 0xd7, 0x00 }, { 61, 0x5f, 0xd7, 0x5f },
{ 62, 0x5f, 0xd7, 0x87 }, { 63, 0x5f, 0xd7, 0xaf },
{ 64, 0x5f, 0xd7, 0xd7 }, { 65, 0x5f, 0xd7, 0xff },
{ 66, 0x5f, 0xff, 0x00 }, { 67, 0x5f, 0xff, 0x5f },
{ 68, 0x5f, 0xff, 0x87 }, { 69, 0x5f, 0xff, 0xaf },
{ 70, 0x5f, 0xff, 0xd7 }, { 71, 0x5f, 0xff, 0xff },
{ 72, 0x87, 0x00, 0x00 }, { 73, 0x87, 0x00, 0x5f },
{ 74, 0x87, 0x00, 0x87 }, { 75, 0x87, 0x00, 0xaf },
{ 76, 0x87, 0x00, 0xd7 }, { 77, 0x87, 0x00, 0xff },
{ 78, 0x87, 0x5f, 0x00 }, { 79, 0x87, 0x5f, 0x5f },
{ 80, 0x87, 0x5f, 0x87 }, { 81, 0x87, 0x5f, 0xaf },
{ 82, 0x87, 0x5f, 0xd7 }, { 83, 0x87, 0x5f, 0xff },
{ 84, 0x87, 0x87, 0x00 }, { 85, 0x87, 0x87, 0x5f },
{ 86, 0x87, 0x87, 0x87 }, { 87, 0x87, 0x87, 0xaf },
{ 88, 0x87, 0x87, 0xd7 }, { 89, 0x87, 0x87, 0xff },
{ 90, 0x87, 0xaf, 0x00 }, { 91, 0x87, 0xaf, 0x5f },
{ 92, 0x87, 0xaf, 0x87 }, { 93, 0x87, 0xaf, 0xaf },
{ 94, 0x87, 0xaf, 0xd7 }, { 95, 0x87, 0xaf, 0xff },
{ 96, 0x87, 0xd7, 0x00 }, { 97, 0x87, 0xd7, 0x5f },
{ 98, 0x87, 0xd7, 0x87 }, { 99, 0x87, 0xd7, 0xaf },
{ 100, 0x87, 0xd7, 0xd7 }, { 101, 0x87, 0xd7, 0xff },
{ 102, 0x87, 0xff, 0x00 }, { 103, 0x87, 0xff, 0x5f },
{ 104, 0x87, 0xff, 0x87 }, { 105, 0x87, 0xff, 0xaf },
{ 106, 0x87, 0xff, 0xd7 }, { 107, 0x87, 0xff, 0xff },
{ 108, 0xaf, 0x00, 0x00 }, { 109, 0xaf, 0x00, 0x5f },
{ 110, 0xaf, 0x00, 0x87 }, { 111, 0xaf, 0x00, 0xaf },
{ 112, 0xaf, 0x00, 0xd7 }, { 113, 0xaf, 0x00, 0xff },
{ 114, 0xaf, 0x5f, 0x00 }, { 115, 0xaf, 0x5f, 0x5f },
{ 116, 0xaf, 0x5f, 0x87 }, { 117, 0xaf, 0x5f, 0xaf },
{ 118, 0xaf, 0x5f, 0xd7 }, { 119, 0xaf, 0x5f, 0xff },
{ 120, 0xaf, 0x87, 0x00 }, { 121, 0xaf, 0x87, 0x5f },
{ 122, 0xaf, 0x87, 0x87 }, { 123, 0xaf, 0x87, 0xaf },
{ 124, 0xaf, 0x87, 0xd7 }, { 125, 0xaf, 0x87, 0xff },
{ 126, 0xaf, 0xaf, 0x00 }, { 127, 0xaf, 0xaf, 0x5f },
{ 128, 0xaf, 0xaf, 0x87 }, { 129, 0xaf, 0xaf, 0xaf },
{ 130, 0xaf, 0xaf, 0xd7 }, { 131, 0xaf, 0xaf, 0xff },
{ 132, 0xaf, 0xd7, 0x00 }, { 133, 0xaf, 0xd7, 0x5f },
{ 134, 0xaf, 0xd7, 0x87 }, { 135, 0xaf, 0xd7, 0xaf },
{ 136, 0xaf, 0xd7, 0xd7 }, { 137, 0xaf, 0xd7, 0xff },
{ 138, 0xaf, 0xff, 0x00 }, { 139, 0xaf, 0xff, 0x5f },
{ 140, 0xaf, 0xff, 0x87 }, { 141, 0xaf, 0xff, 0xaf },
{ 142, 0xaf, 0xff, 0xd7 }, { 143, 0xaf, 0xff, 0xff },
{ 144, 0xd7, 0x00, 0x00 }, { 145, 0xd7, 0x00, 0x5f },
{ 146, 0xd7, 0x00, 0x87 }, { 147, 0xd7, 0x00, 0xaf },
{ 148, 0xd7, 0x00, 0xd7 }, { 149, 0xd7, 0x00, 0xff },
{ 150, 0xd7, 0x5f, 0x00 }, { 151, 0xd7, 0x5f, 0x5f },
{ 152, 0xd7, 0x5f, 0x87 }, { 153, 0xd7, 0x5f, 0xaf },
{ 154, 0xd7, 0x5f, 0xd7 }, { 155, 0xd7, 0x5f, 0xff },
{ 156, 0xd7, 0x87, 0x00 }, { 157, 0xd7, 0x87, 0x5f },
{ 158, 0xd7, 0x87, 0x87 }, { 159, 0xd7, 0x87, 0xaf },
{ 160, 0xd7, 0x87, 0xd7 }, { 161, 0xd7, 0x87, 0xff },
{ 162, 0xd7, 0xaf, 0x00 }, { 163, 0xd7, 0xaf, 0x5f },
{ 164, 0xd7, 0xaf, 0x87 }, { 165, 0xd7, 0xaf, 0xaf },
{ 166, 0xd7, 0xaf, 0xd7 }, { 167, 0xd7, 0xaf, 0xff },
{ 168, 0xd7, 0xd7, 0x00 }, { 169, 0xd7, 0xd7, 0x5f },
{ 170, 0xd7, 0xd7, 0x87 }, { 171, 0xd7, 0xd7, 0xaf },
{ 172, 0xd7, 0xd7, 0xd7 }, { 173, 0xd7, 0xd7, 0xff },
{ 174, 0xd7, 0xff, 0x00 }, { 175, 0xd7, 0xff, 0x5f },
{ 176, 0xd7, 0xff, 0x87 }, { 177, 0xd7, 0xff, 0xaf },
{ 178, 0xd7, 0xff, 0xd7 }, { 179, 0xd7, 0xff, 0xff },
{ 180, 0xff, 0x00, 0x00 }, { 181, 0xff, 0x00, 0x5f },
{ 182, 0xff, 0x00, 0x87 }, { 183, 0xff, 0x00, 0xaf },
{ 184, 0xff, 0x00, 0xd7 }, { 185, 0xff, 0x00, 0xff },
{ 186, 0xff, 0x5f, 0x00 }, { 187, 0xff, 0x5f, 0x5f },
{ 188, 0xff, 0x5f, 0x87 }, { 189, 0xff, 0x5f, 0xaf },
{ 190, 0xff, 0x5f, 0xd7 }, { 191, 0xff, 0x5f, 0xff },
{ 192, 0xff, 0x87, 0x00 }, { 193, 0xff, 0x87, 0x5f },
{ 194, 0xff, 0x87, 0x87 }, { 195, 0xff, 0x87, 0xaf },
{ 196, 0xff, 0x87, 0xd7 }, { 197, 0xff, 0x87, 0xff },
{ 198, 0xff, 0xaf, 0x00 }, { 199, 0xff, 0xaf, 0x5f },
{ 200, 0xff, 0xaf, 0x87 }, { 201, 0xff, 0xaf, 0xaf },
{ 202, 0xff, 0xaf, 0xd7 }, { 203, 0xff, 0xaf, 0xff },
{ 204, 0xff, 0xd7, 0x00 }, { 205, 0xff, 0xd7, 0x5f },
{ 206, 0xff, 0xd7, 0x87 }, { 207, 0xff, 0xd7, 0xaf },
{ 208, 0xff, 0xd7, 0xd7 }, { 209, 0xff, 0xd7, 0xff },
{ 210, 0xff, 0xff, 0x00 }, { 211, 0xff, 0xff, 0x5f },
{ 212, 0xff, 0xff, 0x87 }, { 213, 0xff, 0xff, 0xaf },
{ 214, 0xff, 0xff, 0xd7 }, { 215, 0xff, 0xff, 0xff },
{ 216, 0x08, 0x08, 0x08 }, { 217, 0x12, 0x12, 0x12 },
{ 218, 0x1c, 0x1c, 0x1c }, { 219, 0x26, 0x26, 0x26 },
{ 220, 0x30, 0x30, 0x30 }, { 221, 0x3a, 0x3a, 0x3a },
{ 222, 0x44, 0x44, 0x44 }, { 223, 0x4e, 0x4e, 0x4e },
{ 224, 0x58, 0x58, 0x58 }, { 225, 0x62, 0x62, 0x62 },
{ 226, 0x6c, 0x6c, 0x6c }, { 227, 0x76, 0x76, 0x76 },
{ 228, 0x80, 0x80, 0x80 }, { 229, 0x8a, 0x8a, 0x8a },
{ 230, 0x94, 0x94, 0x94 }, { 231, 0x9e, 0x9e, 0x9e },
{ 232, 0xa8, 0xa8, 0xa8 }, { 233, 0xb2, 0xb2, 0xb2 },
{ 234, 0xbc, 0xbc, 0xbc }, { 235, 0xc6, 0xc6, 0xc6 },
{ 236, 0xd0, 0xd0, 0xd0 }, { 237, 0xda, 0xda, 0xda },
{ 238, 0xe4, 0xe4, 0xe4 }, { 239, 0xee, 0xee, 0xee },
};
const struct colour_rgb colour_to_256[] = {
{ 0, 0x00, 0x00, 0x00 }, { 1, 0x00, 0x00, 0x5f },
{ 2, 0x00, 0x00, 0x87 }, { 3, 0x00, 0x00, 0xaf },
{ 4, 0x00, 0x00, 0xd7 }, { 5, 0x00, 0x00, 0xff },
{ 6, 0x00, 0x5f, 0x00 }, { 7, 0x00, 0x5f, 0x5f },
{ 8, 0x00, 0x5f, 0x87 }, { 9, 0x00, 0x5f, 0xaf },
{ 10, 0x00, 0x5f, 0xd7 }, { 11, 0x00, 0x5f, 0xff },
{ 12, 0x00, 0x87, 0x00 }, { 13, 0x00, 0x87, 0x5f },
{ 14, 0x00, 0x87, 0x87 }, { 15, 0x00, 0x87, 0xaf },
{ 16, 0x00, 0x87, 0xd7 }, { 17, 0x00, 0x87, 0xff },
{ 18, 0x00, 0xaf, 0x00 }, { 19, 0x00, 0xaf, 0x5f },
{ 20, 0x00, 0xaf, 0x87 }, { 21, 0x00, 0xaf, 0xaf },
{ 22, 0x00, 0xaf, 0xd7 }, { 23, 0x00, 0xaf, 0xff },
{ 24, 0x00, 0xd7, 0x00 }, { 25, 0x00, 0xd7, 0x5f },
{ 26, 0x00, 0xd7, 0x87 }, { 27, 0x00, 0xd7, 0xaf },
{ 28, 0x00, 0xd7, 0xd7 }, { 29, 0x00, 0xd7, 0xff },
{ 30, 0x00, 0xff, 0x00 }, { 31, 0x00, 0xff, 0x5f },
{ 32, 0x00, 0xff, 0x87 }, { 33, 0x00, 0xff, 0xaf },
{ 34, 0x00, 0xff, 0xd7 }, { 35, 0x00, 0xff, 0xff },
{ 216, 0x08, 0x08, 0x08 }, { 217, 0x12, 0x12, 0x12 },
{ 218, 0x1c, 0x1c, 0x1c }, { 219, 0x26, 0x26, 0x26 },
{ 220, 0x30, 0x30, 0x30 }, { 221, 0x3a, 0x3a, 0x3a },
{ 222, 0x44, 0x44, 0x44 }, { 223, 0x4e, 0x4e, 0x4e },
{ 224, 0x58, 0x58, 0x58 }, { 36, 0x5f, 0x00, 0x00 },
{ 37, 0x5f, 0x00, 0x5f }, { 38, 0x5f, 0x00, 0x87 },
{ 39, 0x5f, 0x00, 0xaf }, { 40, 0x5f, 0x00, 0xd7 },
{ 41, 0x5f, 0x00, 0xff }, { 42, 0x5f, 0x5f, 0x00 },
{ 43, 0x5f, 0x5f, 0x5f }, { 44, 0x5f, 0x5f, 0x87 },
{ 45, 0x5f, 0x5f, 0xaf }, { 46, 0x5f, 0x5f, 0xd7 },
{ 47, 0x5f, 0x5f, 0xff }, { 48, 0x5f, 0x87, 0x00 },
{ 49, 0x5f, 0x87, 0x5f }, { 50, 0x5f, 0x87, 0x87 },
{ 51, 0x5f, 0x87, 0xaf }, { 52, 0x5f, 0x87, 0xd7 },
{ 53, 0x5f, 0x87, 0xff }, { 54, 0x5f, 0xaf, 0x00 },
{ 55, 0x5f, 0xaf, 0x5f }, { 56, 0x5f, 0xaf, 0x87 },
{ 57, 0x5f, 0xaf, 0xaf }, { 58, 0x5f, 0xaf, 0xd7 },
{ 59, 0x5f, 0xaf, 0xff }, { 60, 0x5f, 0xd7, 0x00 },
{ 61, 0x5f, 0xd7, 0x5f }, { 62, 0x5f, 0xd7, 0x87 },
{ 63, 0x5f, 0xd7, 0xaf }, { 64, 0x5f, 0xd7, 0xd7 },
{ 65, 0x5f, 0xd7, 0xff }, { 66, 0x5f, 0xff, 0x00 },
{ 67, 0x5f, 0xff, 0x5f }, { 68, 0x5f, 0xff, 0x87 },
{ 69, 0x5f, 0xff, 0xaf }, { 70, 0x5f, 0xff, 0xd7 },
{ 71, 0x5f, 0xff, 0xff }, { 225, 0x62, 0x62, 0x62 },
{ 226, 0x6c, 0x6c, 0x6c }, { 227, 0x76, 0x76, 0x76 },
{ 228, 0x80, 0x80, 0x80 }, { 72, 0x87, 0x00, 0x00 },
{ 73, 0x87, 0x00, 0x5f }, { 74, 0x87, 0x00, 0x87 },
{ 75, 0x87, 0x00, 0xaf }, { 76, 0x87, 0x00, 0xd7 },
{ 77, 0x87, 0x00, 0xff }, { 78, 0x87, 0x5f, 0x00 },
{ 79, 0x87, 0x5f, 0x5f }, { 80, 0x87, 0x5f, 0x87 },
{ 81, 0x87, 0x5f, 0xaf }, { 82, 0x87, 0x5f, 0xd7 },
{ 83, 0x87, 0x5f, 0xff }, { 84, 0x87, 0x87, 0x00 },
{ 85, 0x87, 0x87, 0x5f }, { 86, 0x87, 0x87, 0x87 },
{ 87, 0x87, 0x87, 0xaf }, { 88, 0x87, 0x87, 0xd7 },
{ 89, 0x87, 0x87, 0xff }, { 90, 0x87, 0xaf, 0x00 },
{ 91, 0x87, 0xaf, 0x5f }, { 92, 0x87, 0xaf, 0x87 },
{ 93, 0x87, 0xaf, 0xaf }, { 94, 0x87, 0xaf, 0xd7 },
{ 95, 0x87, 0xaf, 0xff }, { 96, 0x87, 0xd7, 0x00 },
{ 97, 0x87, 0xd7, 0x5f }, { 98, 0x87, 0xd7, 0x87 },
{ 99, 0x87, 0xd7, 0xaf }, { 100, 0x87, 0xd7, 0xd7 },
{ 101, 0x87, 0xd7, 0xff }, { 102, 0x87, 0xff, 0x00 },
{ 103, 0x87, 0xff, 0x5f }, { 104, 0x87, 0xff, 0x87 },
{ 105, 0x87, 0xff, 0xaf }, { 106, 0x87, 0xff, 0xd7 },
{ 107, 0x87, 0xff, 0xff }, { 229, 0x8a, 0x8a, 0x8a },
{ 230, 0x94, 0x94, 0x94 }, { 231, 0x9e, 0x9e, 0x9e },
{ 232, 0xa8, 0xa8, 0xa8 }, { 108, 0xaf, 0x00, 0x00 },
{ 109, 0xaf, 0x00, 0x5f }, { 110, 0xaf, 0x00, 0x87 },
{ 111, 0xaf, 0x00, 0xaf }, { 112, 0xaf, 0x00, 0xd7 },
{ 113, 0xaf, 0x00, 0xff }, { 114, 0xaf, 0x5f, 0x00 },
{ 115, 0xaf, 0x5f, 0x5f }, { 116, 0xaf, 0x5f, 0x87 },
{ 117, 0xaf, 0x5f, 0xaf }, { 118, 0xaf, 0x5f, 0xd7 },
{ 119, 0xaf, 0x5f, 0xff }, { 120, 0xaf, 0x87, 0x00 },
{ 121, 0xaf, 0x87, 0x5f }, { 122, 0xaf, 0x87, 0x87 },
{ 123, 0xaf, 0x87, 0xaf }, { 124, 0xaf, 0x87, 0xd7 },
{ 125, 0xaf, 0x87, 0xff }, { 126, 0xaf, 0xaf, 0x00 },
{ 127, 0xaf, 0xaf, 0x5f }, { 128, 0xaf, 0xaf, 0x87 },
{ 129, 0xaf, 0xaf, 0xaf }, { 130, 0xaf, 0xaf, 0xd7 },
{ 131, 0xaf, 0xaf, 0xff }, { 132, 0xaf, 0xd7, 0x00 },
{ 133, 0xaf, 0xd7, 0x5f }, { 134, 0xaf, 0xd7, 0x87 },
{ 135, 0xaf, 0xd7, 0xaf }, { 136, 0xaf, 0xd7, 0xd7 },
{ 137, 0xaf, 0xd7, 0xff }, { 138, 0xaf, 0xff, 0x00 },
{ 139, 0xaf, 0xff, 0x5f }, { 140, 0xaf, 0xff, 0x87 },
{ 141, 0xaf, 0xff, 0xaf }, { 142, 0xaf, 0xff, 0xd7 },
{ 143, 0xaf, 0xff, 0xff }, { 233, 0xb2, 0xb2, 0xb2 },
{ 234, 0xbc, 0xbc, 0xbc }, { 235, 0xc6, 0xc6, 0xc6 },
{ 236, 0xd0, 0xd0, 0xd0 }, { 144, 0xd7, 0x00, 0x00 },
{ 145, 0xd7, 0x00, 0x5f }, { 146, 0xd7, 0x00, 0x87 },
{ 147, 0xd7, 0x00, 0xaf }, { 148, 0xd7, 0x00, 0xd7 },
{ 149, 0xd7, 0x00, 0xff }, { 150, 0xd7, 0x5f, 0x00 },
{ 151, 0xd7, 0x5f, 0x5f }, { 152, 0xd7, 0x5f, 0x87 },
{ 153, 0xd7, 0x5f, 0xaf }, { 154, 0xd7, 0x5f, 0xd7 },
{ 155, 0xd7, 0x5f, 0xff }, { 156, 0xd7, 0x87, 0x00 },
{ 157, 0xd7, 0x87, 0x5f }, { 158, 0xd7, 0x87, 0x87 },
{ 159, 0xd7, 0x87, 0xaf }, { 160, 0xd7, 0x87, 0xd7 },
{ 161, 0xd7, 0x87, 0xff }, { 162, 0xd7, 0xaf, 0x00 },
{ 163, 0xd7, 0xaf, 0x5f }, { 164, 0xd7, 0xaf, 0x87 },
{ 165, 0xd7, 0xaf, 0xaf }, { 166, 0xd7, 0xaf, 0xd7 },
{ 167, 0xd7, 0xaf, 0xff }, { 168, 0xd7, 0xd7, 0x00 },
{ 169, 0xd7, 0xd7, 0x5f }, { 170, 0xd7, 0xd7, 0x87 },
{ 171, 0xd7, 0xd7, 0xaf }, { 172, 0xd7, 0xd7, 0xd7 },
{ 173, 0xd7, 0xd7, 0xff }, { 174, 0xd7, 0xff, 0x00 },
{ 175, 0xd7, 0xff, 0x5f }, { 176, 0xd7, 0xff, 0x87 },
{ 177, 0xd7, 0xff, 0xaf }, { 178, 0xd7, 0xff, 0xd7 },
{ 179, 0xd7, 0xff, 0xff }, { 237, 0xda, 0xda, 0xda },
{ 238, 0xe4, 0xe4, 0xe4 }, { 239, 0xee, 0xee, 0xee },
{ 180, 0xff, 0x00, 0x00 }, { 181, 0xff, 0x00, 0x5f },
{ 182, 0xff, 0x00, 0x87 }, { 183, 0xff, 0x00, 0xaf },
{ 184, 0xff, 0x00, 0xd7 }, { 185, 0xff, 0x00, 0xff },
{ 186, 0xff, 0x5f, 0x00 }, { 187, 0xff, 0x5f, 0x5f },
{ 188, 0xff, 0x5f, 0x87 }, { 189, 0xff, 0x5f, 0xaf },
{ 190, 0xff, 0x5f, 0xd7 }, { 191, 0xff, 0x5f, 0xff },
{ 192, 0xff, 0x87, 0x00 }, { 193, 0xff, 0x87, 0x5f },
{ 194, 0xff, 0x87, 0x87 }, { 195, 0xff, 0x87, 0xaf },
{ 196, 0xff, 0x87, 0xd7 }, { 197, 0xff, 0x87, 0xff },
{ 198, 0xff, 0xaf, 0x00 }, { 199, 0xff, 0xaf, 0x5f },
{ 200, 0xff, 0xaf, 0x87 }, { 201, 0xff, 0xaf, 0xaf },
{ 202, 0xff, 0xaf, 0xd7 }, { 203, 0xff, 0xaf, 0xff },
{ 204, 0xff, 0xd7, 0x00 }, { 205, 0xff, 0xd7, 0x5f },
{ 206, 0xff, 0xd7, 0x87 }, { 207, 0xff, 0xd7, 0xaf },
{ 208, 0xff, 0xd7, 0xd7 }, { 209, 0xff, 0xd7, 0xff },
{ 210, 0xff, 0xff, 0x00 }, { 211, 0xff, 0xff, 0x5f },
{ 212, 0xff, 0xff, 0x87 }, { 213, 0xff, 0xff, 0xaf },
{ 214, 0xff, 0xff, 0xd7 }, { 215, 0xff, 0xff, 0xff },
};
void colour_rgb_generate256(void); int colour_cmp_rgb(const void *, const void *);
u_int colour_rgb_distance(struct colour_rgb *, struct colour_rgb *);
int colour_rgb_find(struct colour_rgb *);
/* Generate 256 colour RGB table. */ /* Compare function for bsearch(). */
void int
colour_rgb_generate256(void) colour_cmp_rgb(const void *lhs0, const void *rhs0)
{ {
struct colour_rgb *rgb; const struct colour_rgb *lhs = lhs0, *rhs = rhs0;
u_int i, r, g, b;
/* if (lhs->r < rhs->r)
* Allocate the table. The first 16 colours are often changed by users return (-1);
* and terminals so don't include them. if (lhs->r > rhs->r)
*/ return (1);
colour_rgb_256 = xcalloc(240, sizeof *colour_rgb_256);
/* Add the colours first. */ if (lhs->g < rhs->g)
r = g = b = 0; return (-1);
for (i = 240; i > 24; i--) { if (lhs->g > rhs->g)
rgb = &colour_rgb_256[240 - i]; return (1);
if (r != 0) if (lhs->b < rhs->b)
rgb->r = (r * 40) + 55; return (-1);
if (g != 0) if (lhs->b > rhs->b)
rgb->g = (g * 40) + 55; return (1);
if (b != 0)
rgb->b = (b * 40) + 55;
b++; return (0);
if (b > 5) {
b = 0;
g++;
}
if (g > 5) {
g = 0;
r++;
}
}
/* Then add the greys. */
for (i = 24; i > 0; i--) {
rgb = &colour_rgb_256[240 - i];
rgb->r = 8 + (24 - i) * 10;
rgb->g = 8 + (24 - i) * 10;
rgb->b = 8 + (24 - i) * 10;
}
}
/* Get colour RGB distance. */
u_int
colour_rgb_distance(struct colour_rgb *rgb1, struct colour_rgb *rgb2)
{
int r, g, b;
r = rgb1->r - rgb2->r;
g = rgb1->g - rgb2->g;
b = rgb1->b - rgb2->b;
return (r * r + g * g + b * b);
} }
/* Work out the nearest colour from the 256 colour set. */ /* Work out the nearest colour from the 256 colour set. */
int int
colour_rgb_find(struct colour_rgb *rgb) colour_find_rgb(u_char r, u_char g, u_char b)
{ {
u_int distance, lowest, colour, i; struct colour_rgb rgb = { .r = r, .g = g, .b = b }, *found;
u_int distance, lowest, colour, i;
int dr, dg, db;
if (colour_rgb_256 == NULL) found = bsearch(&rgb, colour_to_256, nitems(colour_to_256),
colour_rgb_generate256(); sizeof colour_to_256[0], colour_cmp_rgb);
if (found != NULL)
return (16 + found->i);
colour = 16; colour = 16;
lowest = UINT_MAX; lowest = UINT_MAX;
for (i = 0; i < 240; i++) { for (i = 0; i < 240; i++) {
distance = colour_rgb_distance(&colour_rgb_256[i], rgb); dr = (int)colour_from_256[i].r - r;
dg = (int)colour_from_256[i].g - g;
db = (int)colour_from_256[i].b - b;
distance = dr * dr + dg * dg + db * db;
if (distance < lowest) { if (distance < lowest) {
lowest = distance; lowest = distance;
colour = 16 + i; colour = 16 + i;
@ -194,20 +408,20 @@ colour_tostring(int c)
int int
colour_fromstring(const char *s) colour_fromstring(const char *s)
{ {
const char *errstr; const char *errstr;
const char *cp; const char *cp;
struct colour_rgb rgb; int n;
int n; u_char r, g, b;
if (*s == '#' && strlen(s) == 7) { if (*s == '#' && strlen(s) == 7) {
for (cp = s + 1; isxdigit((u_char) *cp); cp++) for (cp = s + 1; isxdigit((u_char) *cp); cp++)
; ;
if (*cp != '\0') if (*cp != '\0')
return (-1); return (-1);
n = sscanf(s + 1, "%2hhx%2hhx%2hhx", &rgb.r, &rgb.g, &rgb.b); n = sscanf(s + 1, "%2hhx%2hhx%2hhx", &r, &g, &b);
if (n != 3) if (n != 3)
return (-1); return (-1);
return (colour_rgb_find(&rgb) | 0x100); return (colour_find_rgb(r, g, b) | 0x100);
} }
if (strncasecmp(s, "colour", (sizeof "colour") - 1) == 0) { if (strncasecmp(s, "colour", (sizeof "colour") - 1) == 0) {
@ -217,47 +431,39 @@ colour_fromstring(const char *s)
return (n | 0x100); return (n | 0x100);
} }
if (strcasecmp(s, "black") == 0 || (s[0] == '0' && s[1] == '\0')) if (strcasecmp(s, "black") == 0 || strcmp(s, "0") == 0)
return (0); return (0);
if (strcasecmp(s, "red") == 0 || (s[0] == '1' && s[1] == '\0')) if (strcasecmp(s, "red") == 0 || strcmp(s, "1") == 0)
return (1); return (1);
if (strcasecmp(s, "green") == 0 || (s[0] == '2' && s[1] == '\0')) if (strcasecmp(s, "green") == 0 || strcmp(s, "2") == 0)
return (2); return (2);
if (strcasecmp(s, "yellow") == 0 || (s[0] == '3' && s[1] == '\0')) if (strcasecmp(s, "yellow") == 0 || strcmp(s, "3") == 0)
return (3); return (3);
if (strcasecmp(s, "blue") == 0 || (s[0] == '4' && s[1] == '\0')) if (strcasecmp(s, "blue") == 0 || strcmp(s, "4") == 0)
return (4); return (4);
if (strcasecmp(s, "magenta") == 0 || (s[0] == '5' && s[1] == '\0')) if (strcasecmp(s, "magenta") == 0 || strcmp(s, "5") == 0)
return (5); return (5);
if (strcasecmp(s, "cyan") == 0 || (s[0] == '6' && s[1] == '\0')) if (strcasecmp(s, "cyan") == 0 || strcmp(s, "6") == 0)
return (6); return (6);
if (strcasecmp(s, "white") == 0 || (s[0] == '7' && s[1] == '\0')) if (strcasecmp(s, "white") == 0 || strcmp(s, "7") == 0)
return (7); return (7);
if (strcasecmp(s, "default") == 0 || (s[0] == '8' && s[1] == '\0')) if (strcasecmp(s, "default") == 0 || strcmp(s, "8") == 0)
return (8); return (8);
if (strcasecmp(s, "brightblack") == 0 || if (strcasecmp(s, "brightblack") == 0 || strcmp(s, "90") == 0)
(s[0] == '9' && s[1] == '0' && s[2] == '\0'))
return (90); return (90);
if (strcasecmp(s, "brightred") == 0 || if (strcasecmp(s, "brightred") == 0 || strcmp(s, "91") == 0)
(s[0] == '9' && s[1] == '1' && s[2] == '\0'))
return (91); return (91);
if (strcasecmp(s, "brightgreen") == 0 || if (strcasecmp(s, "brightgreen") == 0 || strcmp(s, "92") == 0)
(s[0] == '9' && s[1] == '2' && s[2] == '\0'))
return (92); return (92);
if (strcasecmp(s, "brightyellow") == 0 || if (strcasecmp(s, "brightyellow") == 0 || strcmp(s, "93") == 0)
(s[0] == '9' && s[1] == '3' && s[2] == '\0'))
return (93); return (93);
if (strcasecmp(s, "brightblue") == 0 || if (strcasecmp(s, "brightblue") == 0 || strcmp(s, "94") == 0)
(s[0] == '9' && s[1] == '4' && s[2] == '\0'))
return (94); return (94);
if (strcasecmp(s, "brightmagenta") == 0 || if (strcasecmp(s, "brightmagenta") == 0 || strcmp(s, "95") == 0)
(s[0] == '9' && s[1] == '5' && s[2] == '\0'))
return (95); return (95);
if (strcasecmp(s, "brightcyan") == 0 || if (strcasecmp(s, "brightcyan") == 0 || strcmp(s, "96") == 0)
(s[0] == '9' && s[1] == '6' && s[2] == '\0'))
return (96); return (96);
if (strcasecmp(s, "brightwhite") == 0 || if (strcasecmp(s, "brightwhite") == 0 || strcmp(s, "97") == 0)
(s[0] == '9' && s[1] == '7' && s[2] == '\0'))
return (97); return (97);
return (-1); return (-1);
} }

91
input.c
View File

@ -126,6 +126,8 @@ void input_csi_dispatch_rm_private(struct input_ctx *);
void input_csi_dispatch_sm(struct input_ctx *); void input_csi_dispatch_sm(struct input_ctx *);
void input_csi_dispatch_sm_private(struct input_ctx *); void input_csi_dispatch_sm_private(struct input_ctx *);
void input_csi_dispatch_winops(struct input_ctx *); void input_csi_dispatch_winops(struct input_ctx *);
void input_csi_dispatch_sgr_256(struct input_ctx *, int, u_int *);
void input_csi_dispatch_sgr_rgb(struct input_ctx *, int, u_int *);
void input_csi_dispatch_sgr(struct input_ctx *); void input_csi_dispatch_sgr(struct input_ctx *);
int input_dcs_dispatch(struct input_ctx *); int input_dcs_dispatch(struct input_ctx *);
int input_utf8_open(struct input_ctx *); int input_utf8_open(struct input_ctx *);
@ -1609,13 +1611,71 @@ input_csi_dispatch_winops(struct input_ctx *ictx)
} }
} }
/* Handle CSI SGR for 256 colours. */
void
input_csi_dispatch_sgr_256(struct input_ctx *ictx, int fgbg, u_int *i)
{
struct grid_cell *gc = &ictx->cell.cell;
int c;
(*i)++;
c = input_get(ictx, *i, 0, -1);
if (c == -1) {
if (fgbg == 38) {
gc->flags &= ~GRID_FLAG_FG256;
gc->fg = 8;
} else if (fgbg == 48) {
gc->flags &= ~GRID_FLAG_BG256;
gc->bg = 8;
}
} else {
if (fgbg == 38) {
gc->flags |= GRID_FLAG_FG256;
gc->fg = c;
} else if (fgbg == 48) {
gc->flags |= GRID_FLAG_BG256;
gc->bg = c;
}
}
}
/* Handle CSI SGR for RGB colours. */
void
input_csi_dispatch_sgr_rgb(struct input_ctx *ictx, int fgbg, u_int *i)
{
struct grid_cell *gc = &ictx->cell.cell;
int c, r, g, b;
(*i)++;
r = input_get(ictx, *i, 0, -1);
if (r == -1 || r > 255)
return;
(*i)++;
g = input_get(ictx, *i, 0, -1);
if (g == -1 || g > 255)
return;
(*i)++;
b = input_get(ictx, *i, 0, -1);
if (b == -1 || b > 255)
return;
c = colour_find_rgb(r, g, b);
if (fgbg == 38) {
gc->flags |= GRID_FLAG_FG256;
gc->fg = c;
} else if (fgbg == 48) {
gc->flags |= GRID_FLAG_BG256;
gc->bg = c;
}
}
/* Handle CSI SGR. */ /* Handle CSI SGR. */
void void
input_csi_dispatch_sgr(struct input_ctx *ictx) input_csi_dispatch_sgr(struct input_ctx *ictx)
{ {
struct grid_cell *gc = &ictx->cell.cell; struct grid_cell *gc = &ictx->cell.cell;
u_int i; u_int i;
int n, m; int n;
if (ictx->param_list_len == 0) { if (ictx->param_list_len == 0) {
memcpy(gc, &grid_default_cell, sizeof *gc); memcpy(gc, &grid_default_cell, sizeof *gc);
@ -1627,28 +1687,13 @@ input_csi_dispatch_sgr(struct input_ctx *ictx)
if (n == 38 || n == 48) { if (n == 38 || n == 48) {
i++; i++;
if (input_get(ictx, i, 0, -1) != 5) switch (input_get(ictx, i, 0, -1)) {
continue; case 2:
input_csi_dispatch_sgr_rgb(ictx, n, &i);
i++; break;
m = input_get(ictx, i, 0, -1); case 5:
if (m == -1) { input_csi_dispatch_sgr_256(ictx, n, &i);
if (n == 38) { break;
gc->flags &= ~GRID_FLAG_FG256;
gc->fg = 8;
} else if (n == 48) {
gc->flags &= ~GRID_FLAG_BG256;
gc->bg = 8;
}
} else {
if (n == 38) {
gc->flags |= GRID_FLAG_FG256;
gc->fg = m;
} else if (n == 48) {
gc->flags |= GRID_FLAG_BG256;
gc->bg = m;
}
} }
continue; continue;
} }

View File

@ -161,16 +161,16 @@ key_bindings_init(void)
"bind , command-prompt -I'#W' \"rename-window '%%'\"", "bind , command-prompt -I'#W' \"rename-window '%%'\"",
"bind - delete-buffer", "bind - delete-buffer",
"bind . command-prompt \"move-window -t '%%'\"", "bind . command-prompt \"move-window -t '%%'\"",
"bind 0 select-window -t:0", "bind 0 select-window -t:=0",
"bind 1 select-window -t:1", "bind 1 select-window -t:=1",
"bind 2 select-window -t:2", "bind 2 select-window -t:=2",
"bind 3 select-window -t:3", "bind 3 select-window -t:=3",
"bind 4 select-window -t:4", "bind 4 select-window -t:=4",
"bind 5 select-window -t:5", "bind 5 select-window -t:=5",
"bind 6 select-window -t:6", "bind 6 select-window -t:=6",
"bind 7 select-window -t:7", "bind 7 select-window -t:=7",
"bind 8 select-window -t:8", "bind 8 select-window -t:=8",
"bind 9 select-window -t:9", "bind 9 select-window -t:=9",
"bind : command-prompt", "bind : command-prompt",
"bind \\; last-pane", "bind \\; last-pane",
"bind = choose-buffer", "bind = choose-buffer",

View File

@ -120,9 +120,9 @@ notify_drain(void)
} }
if (ne->client != NULL) if (ne->client != NULL)
ne->client->references--; server_client_unref(ne->client);
if (ne->session != NULL) if (ne->session != NULL)
ne->session->references--; session_unref(ne->session);
if (ne->window != NULL) if (ne->window != NULL)
window_remove_ref(ne->window); window_remove_ref(ne->window);

View File

@ -30,6 +30,7 @@
#include "tmux.h" #include "tmux.h"
void server_client_key_table(struct client *, const char *); void server_client_key_table(struct client *, const char *);
void server_client_free(int, short, void *);
void server_client_check_focus(struct window_pane *); void server_client_check_focus(struct window_pane *);
void server_client_check_resize(struct window_pane *); void server_client_check_resize(struct window_pane *);
int server_client_check_mouse(struct client *); int server_client_check_mouse(struct client *);
@ -45,6 +46,27 @@ void server_client_msg_command(struct client *, struct imsg *);
void server_client_msg_identify(struct client *, struct imsg *); void server_client_msg_identify(struct client *, struct imsg *);
void server_client_msg_shell(struct client *); void server_client_msg_shell(struct client *);
/* Check if this client is inside this server. */
int
server_client_check_nested(struct client *c)
{
struct environ_entry *envent;
struct window_pane *wp;
if (c->tty.path == NULL)
return (0);
envent = environ_find(&c->environ, "TMUX");
if (envent == NULL || *envent->value == '\0')
return (0);
RB_FOREACH(wp, window_pane_tree, &all_window_panes) {
if (strcmp(wp->tty, c->tty.path) == 0)
return (1);
}
return (0);
}
/* Set client key table. */ /* Set client key table. */
void void
server_client_key_table(struct client *c, const char *name) server_client_key_table(struct client *c, const char *name)
@ -63,7 +85,7 @@ server_client_create(int fd)
setblocking(fd, 0); setblocking(fd, 0);
c = xcalloc(1, sizeof *c); c = xcalloc(1, sizeof *c);
c->references = 0; c->references = 1;
imsg_init(&c->ibuf, fd); imsg_init(&c->ibuf, fd);
server_update_event(c); server_update_event(c);
@ -139,6 +161,14 @@ server_client_lost(struct client *c)
{ {
struct message_entry *msg, *msg1; struct message_entry *msg, *msg1;
c->flags |= CLIENT_DEAD;
status_prompt_clear(c);
status_message_clear(c);
if (c->stdin_callback != NULL)
c->stdin_callback(c, 1, c->stdin_callback_data);
TAILQ_REMOVE(&clients, c, entry); TAILQ_REMOVE(&clients, c, entry);
log_debug("lost client %d", c->ibuf.fd); log_debug("lost client %d", c->ibuf.fd);
@ -191,8 +221,7 @@ server_client_lost(struct client *c)
if (event_initialized(&c->event)) if (event_initialized(&c->event))
event_del(&c->event); event_del(&c->event);
TAILQ_INSERT_TAIL(&dead_clients, c, entry); server_client_unref(c);
c->flags |= CLIENT_DEAD;
server_add_accept(0); /* may be more file descriptors now */ server_add_accept(0); /* may be more file descriptors now */
@ -201,6 +230,29 @@ server_client_lost(struct client *c)
server_update_socket(); server_update_socket();
} }
/* Remove reference from a client. */
void
server_client_unref(struct client *c)
{
log_debug("unref client %d (%d references)", c->ibuf.fd, c->references);
c->references--;
if (c->references == 0)
event_once(-1, EV_TIMEOUT, server_client_free, c, NULL);
}
/* Free dead client. */
void
server_client_free(unused int fd, unused short events, void *arg)
{
struct client *c = arg;
log_debug("free client %d (%d references)", c->ibuf.fd, c->references);
if (c->references == 0)
free(c);
}
/* Process a single client event. */ /* Process a single client event. */
void void
server_client_callback(int fd, short events, void *data) server_client_callback(int fd, short events, void *data)

View File

@ -40,9 +40,7 @@
* Main server functions. * Main server functions.
*/ */
/* Client list. */
struct clients clients; struct clients clients;
struct clients dead_clients;
int server_fd; int server_fd;
int server_shutdown; int server_shutdown;
@ -59,7 +57,6 @@ int server_create_socket(void);
void server_loop(void); void server_loop(void);
int server_should_shutdown(void); int server_should_shutdown(void);
void server_send_shutdown(void); void server_send_shutdown(void);
void server_clean_dead(void);
void server_accept_callback(int, short, void *); void server_accept_callback(int, short, void *);
void server_signal_callback(int, short, void *); void server_signal_callback(int, short, void *);
void server_child_signal(void); void server_child_signal(void);
@ -204,9 +201,7 @@ server_start(int lockfd, char *lockfile)
RB_INIT(&windows); RB_INIT(&windows);
RB_INIT(&all_window_panes); RB_INIT(&all_window_panes);
TAILQ_INIT(&clients); TAILQ_INIT(&clients);
TAILQ_INIT(&dead_clients);
RB_INIT(&sessions); RB_INIT(&sessions);
RB_INIT(&dead_sessions);
TAILQ_INIT(&session_groups); TAILQ_INIT(&session_groups);
mode_key_init_trees(); mode_key_init_trees();
key_bindings_init(); key_bindings_init();
@ -268,8 +263,6 @@ server_loop(void)
server_window_loop(); server_window_loop();
server_client_loop(); server_client_loop();
server_clean_dead();
} }
} }
@ -321,29 +314,6 @@ server_send_shutdown(void)
session_destroy(s); session_destroy(s);
} }
/* Free dead, unreferenced clients and sessions. */
void
server_clean_dead(void)
{
struct session *s, *s1;
struct client *c, *c1;
RB_FOREACH_SAFE(s, sessions, &dead_sessions, s1) {
if (s->references != 0)
continue;
RB_REMOVE(sessions, &dead_sessions, s);
free(s->name);
free(s);
}
TAILQ_FOREACH_SAFE(c, &dead_clients, entry, c1) {
if (c->references != 0)
continue;
TAILQ_REMOVE(&dead_clients, c, entry);
free(c);
}
}
/* Update socket execute permissions based on whether sessions are attached. */ /* Update socket execute permissions based on whether sessions are attached. */
void void
server_update_socket(void) server_update_socket(void)

View File

@ -26,12 +26,12 @@
#include "tmux.h" #include "tmux.h"
/* Global session list. */
struct sessions sessions; struct sessions sessions;
struct sessions dead_sessions;
u_int next_session_id; u_int next_session_id;
struct session_groups session_groups; struct session_groups session_groups;
void session_free(int, short, void *);
struct winlink *session_next_alert(struct winlink *); struct winlink *session_next_alert(struct winlink *);
struct winlink *session_previous_alert(struct winlink *); struct winlink *session_previous_alert(struct winlink *);
@ -108,7 +108,7 @@ session_create(const char *name, int argc, char **argv, const char *path,
struct winlink *wl; struct winlink *wl;
s = xmalloc(sizeof *s); s = xmalloc(sizeof *s);
s->references = 0; s->references = 1;
s->flags = 0; s->flags = 0;
if (gettimeofday(&s->creation_time, NULL) != 0) if (gettimeofday(&s->creation_time, NULL) != 0)
@ -163,6 +163,29 @@ session_create(const char *name, int argc, char **argv, const char *path,
return (s); return (s);
} }
/* Remove a reference from a session. */
void
session_unref(struct session *s)
{
log_debug("session %s has %d references", s->name, s->references);
s->references--;
if (s->references == 0)
event_once(-1, EV_TIMEOUT, session_free, s, NULL);
}
/* Free session. */
void
session_free(unused int fd, unused short events, void *arg)
{
struct session *s = arg;
log_debug("sesson %s freed (%d references)", s->name, s->references);
if (s->references == 0)
free(s);
}
/* Destroy a session. */ /* Destroy a session. */
void void
session_destroy(struct session *s) session_destroy(struct session *s)
@ -190,7 +213,7 @@ session_destroy(struct session *s)
close(s->cwd); close(s->cwd);
RB_INSERT(sessions, &dead_sessions, s); session_unref(s);
} }
/* Check a session name is valid: not empty and no colons or periods. */ /* Check a session name is valid: not empty and no colons or periods. */

38
tmux.1
View File

@ -23,7 +23,7 @@
.Sh SYNOPSIS .Sh SYNOPSIS
.Nm tmux .Nm tmux
.Bk -words .Bk -words
.Op Fl 2lCquvV .Op Fl 2CluvV
.Op Fl c Ar shell-command .Op Fl c Ar shell-command
.Op Fl f Ar file .Op Fl f Ar file
.Op Fl L Ar socket-name .Op Fl L Ar socket-name
@ -408,6 +408,14 @@ An
pattern which is matched against the session name. pattern which is matched against the session name.
.El .El
.Pp .Pp
If the session name is prefixed with a
.Ql = : ,
only an exact match is accepted (so
.Ql =mysess
will only match exactly
.Ql mysess ,
not
.Ql mysession ) .
If a single session is found, it is used as the target session; multiple matches If a single session is found, it is used as the target session; multiple matches
produce an error. produce an error.
If a session is omitted, the current session is used if available; if no If a session is omitted, the current session is used if available; if no
@ -444,6 +452,9 @@ As an
pattern matched against the window name. pattern matched against the window name.
.El .El
.Pp .Pp
Like sessions, a
.Ql =
prefix will do an exact match only.
An empty window name specifies the next unused index if appropriate (for An empty window name specifies the next unused index if appropriate (for
example the example the
.Ic new-window .Ic new-window
@ -663,7 +674,7 @@ section.
The following commands are available to manage clients and sessions: The following commands are available to manage clients and sessions:
.Bl -tag -width Ds .Bl -tag -width Ds
.It Xo Ic attach-session .It Xo Ic attach-session
.Op Fl dr .Op Fl dEr
.Op Fl c Ar working-directory .Op Fl c Ar working-directory
.Op Fl t Ar target-session .Op Fl t Ar target-session
.Xc .Xc
@ -702,6 +713,12 @@ session.
.Fl c .Fl c
will set the session working directory (used for new windows) to will set the session working directory (used for new windows) to
.Ar working-directory . .Ar working-directory .
.Pp
If
.Fl E
is used,
.Ic update-environment
option will not be applied.
.It Xo Ic detach-client .It Xo Ic detach-client
.Op Fl P .Op Fl P
.Op Fl a .Op Fl a
@ -776,7 +793,7 @@ command.
Lock all clients attached to Lock all clients attached to
.Ar target-session . .Ar target-session .
.It Xo Ic new-session .It Xo Ic new-session
.Op Fl AdDP .Op Fl AdDEP
.Op Fl c Ar start-directory .Op Fl c Ar start-directory
.Op Fl F Ar format .Op Fl F Ar format
.Op Fl n Ar window-name .Op Fl n Ar window-name
@ -851,6 +868,13 @@ By default, it uses the format
.Ql #{session_name}: .Ql #{session_name}:
but a different format may be specified with but a different format may be specified with
.Fl F . .Fl F .
.Pp
If
.Fl E
is used,
.Ic update-environment
option will not be applied.
.Ic update-environment .
.It Xo Ic refresh-client .It Xo Ic refresh-client
.Op Fl S .Op Fl S
.Op Fl t Ar target-client .Op Fl t Ar target-client
@ -905,7 +929,7 @@ Suspend a client by sending
.Dv SIGTSTP .Dv SIGTSTP
(tty stop). (tty stop).
.It Xo Ic switch-client .It Xo Ic switch-client
.Op Fl lnpr .Op Fl Elnpr
.Op Fl c Ar target-client .Op Fl c Ar target-client
.Op Fl t Ar target-session .Op Fl t Ar target-session
.Op Fl T Ar key-table .Op Fl T Ar key-table
@ -927,6 +951,12 @@ toggles whether a client is read-only (see the
.Ic attach-session .Ic attach-session
command). command).
.Pp .Pp
If
.Fl E
is used,
.Ic update-environment
option will not be applied.
.Pp
.Fl T .Fl T
sets the client's key table; the next key from the client will be interpreted from sets the client's key table; the next key from the client will be interpreted from
.Ar key-table . .Ar key-table .

2
tmux.c
View File

@ -61,7 +61,7 @@ __dead void
usage(void) usage(void)
{ {
fprintf(stderr, fprintf(stderr,
"usage: %s [-2lquvV] [-c shell-command] [-f file] [-L socket-name]\n" "usage: %s [-2CluvV] [-c shell-command] [-f file] [-L socket-name]\n"
" [-S socket-path] [command [flags]]\n", " [-S socket-path] [command [flags]]\n",
__progname); __progname);
exit(1); exit(1);

10
tmux.h
View File

@ -1378,8 +1378,7 @@ struct cmd_entry {
const char *usage; const char *usage;
#define CMD_STARTSERVER 0x1 #define CMD_STARTSERVER 0x1
#define CMD_CANTNEST 0x2 #define CMD_READONLY 0x2
#define CMD_READONLY 0x4
int flags; int flags;
enum cmd_retval (*exec)(struct cmd *, struct cmd_q *); enum cmd_retval (*exec)(struct cmd *, struct cmd_q *);
@ -1806,7 +1805,7 @@ extern const struct cmd_entry cmd_wait_for_entry;
/* cmd-attach-session.c */ /* cmd-attach-session.c */
enum cmd_retval cmd_attach_session(struct cmd_q *, const char *, int, int, enum cmd_retval cmd_attach_session(struct cmd_q *, const char *, int, int,
const char *); const char *, int);
/* cmd-list.c */ /* cmd-list.c */
struct cmd_list *cmd_list_parse(int, char **, const char *, u_int, char **); struct cmd_list *cmd_list_parse(int, char **, const char *, u_int, char **);
@ -1872,9 +1871,11 @@ void server_update_socket(void);
void server_add_accept(int); void server_add_accept(int);
/* server-client.c */ /* server-client.c */
int server_client_check_nested(struct client *);
void server_client_handle_key(struct client *, int); void server_client_handle_key(struct client *, int);
void server_client_create(int); void server_client_create(int);
int server_client_open(struct client *, char **); int server_client_open(struct client *, char **);
void server_client_unref(struct client *);
void server_client_lost(struct client *); void server_client_lost(struct client *);
void server_client_callback(int, short, void *); void server_client_callback(int, short, void *);
void server_client_status_timer(void); void server_client_status_timer(void);
@ -1956,6 +1957,7 @@ char *xterm_keys_lookup(int);
int xterm_keys_find(const char *, size_t, size_t *, int *); int xterm_keys_find(const char *, size_t, size_t *, int *);
/* colour.c */ /* colour.c */
int colour_find_rgb(u_char, u_char, u_char);
void colour_set_fg(struct grid_cell *, int); void colour_set_fg(struct grid_cell *, int);
void colour_set_bg(struct grid_cell *, int); void colour_set_bg(struct grid_cell *, int);
const char *colour_tostring(int); const char *colour_tostring(int);
@ -2262,7 +2264,6 @@ void control_notify_session_close(struct session *);
/* session.c */ /* session.c */
extern struct sessions sessions; extern struct sessions sessions;
extern struct sessions dead_sessions;
extern struct session_groups session_groups; extern struct session_groups session_groups;
int session_cmp(struct session *, struct session *); int session_cmp(struct session *, struct session *);
RB_PROTOTYPE(sessions, session, entry, session_cmp); RB_PROTOTYPE(sessions, session, entry, session_cmp);
@ -2274,6 +2275,7 @@ struct session *session_create(const char *, int, char **, const char *,
int, struct environ *, struct termios *, int, u_int, int, struct environ *, struct termios *, int, u_int,
u_int, char **); u_int, char **);
void session_destroy(struct session *); void session_destroy(struct session *);
void session_unref(struct session *);
int session_check_name(const char *); int session_check_name(const char *);
void session_update_activity(struct session *); void session_update_activity(struct session *);
struct session *session_next_session(struct session *); struct session *session_next_session(struct session *);

View File

@ -501,6 +501,7 @@ tty_keys_next(struct tty *tty)
case -1: /* no, or not valid */ case -1: /* no, or not valid */
break; break;
case -2: /* yes, but we don't care. */ case -2: /* yes, but we don't care. */
key = KEYC_MOUSE;
goto discard_key; goto discard_key;
case 1: /* partial */ case 1: /* partial */
goto partial_key; goto partial_key;

View File

@ -209,11 +209,11 @@ window_choose_data_create(int type, struct client *c, struct session *s)
void void
window_choose_data_free(struct window_choose_data *wcd) window_choose_data_free(struct window_choose_data *wcd)
{ {
wcd->start_client->references--; server_client_unref(wcd->start_client);
wcd->start_session->references--; session_unref(wcd->start_session);
if (wcd->tree_session != NULL) if (wcd->tree_session != NULL)
wcd->tree_session->references--; session_unref(wcd->tree_session);
free(wcd->ft_template); free(wcd->ft_template);
format_free(wcd->ft); format_free(wcd->ft);