Merge branch 'obsd-master'

Conflicts:
	Makefile
	cmd-server-info.c
	cmd-start-server.c
This commit is contained in:
Thomas Adam 2014-01-31 21:39:56 +00:00
commit d50e47fc4a
35 changed files with 1414 additions and 699 deletions

138
Makefile Normal file
View File

@ -0,0 +1,138 @@
# $OpenBSD$
PROG= tmux
SRCS= arguments.c \
attributes.c \
cfg.c \
client.c \
clock.c \
cmd-attach-session.c \
cmd-bind-key.c \
cmd-break-pane.c \
cmd-capture-pane.c \
cmd-choose-buffer.c \
cmd-choose-client.c \
cmd-choose-list.c \
cmd-choose-tree.c \
cmd-clear-history.c \
cmd-clock-mode.c \
cmd-command-prompt.c \
cmd-confirm-before.c \
cmd-copy-mode.c \
cmd-delete-buffer.c \
cmd-detach-client.c \
cmd-display-message.c \
cmd-display-panes.c \
cmd-find-window.c \
cmd-has-session.c \
cmd-if-shell.c \
cmd-join-pane.c \
cmd-kill-pane.c \
cmd-kill-server.c \
cmd-kill-session.c \
cmd-kill-window.c \
cmd-link-window.c \
cmd-list-buffers.c \
cmd-list-clients.c \
cmd-list-commands.c \
cmd-list-keys.c \
cmd-list-panes.c \
cmd-list-sessions.c \
cmd-list-windows.c \
cmd-list.c \
cmd-load-buffer.c \
cmd-lock-server.c \
cmd-move-window.c \
cmd-new-session.c \
cmd-new-window.c \
cmd-paste-buffer.c \
cmd-pipe-pane.c \
cmd-refresh-client.c \
cmd-rename-session.c \
cmd-rename-window.c \
cmd-resize-pane.c \
cmd-respawn-pane.c \
cmd-respawn-window.c \
cmd-rotate-window.c \
cmd-run-shell.c \
cmd-save-buffer.c \
cmd-select-layout.c \
cmd-select-pane.c \
cmd-select-window.c \
cmd-send-keys.c \
cmd-set-buffer.c \
cmd-set-environment.c \
cmd-set-option.c \
cmd-show-environment.c \
cmd-show-messages.c \
cmd-show-options.c \
cmd-source-file.c \
cmd-split-window.c \
cmd-string.c \
cmd-suspend-client.c \
cmd-swap-pane.c \
cmd-swap-window.c \
cmd-switch-client.c \
cmd-unbind-key.c \
cmd-unlink-window.c \
cmd-wait-for.c \
cmd.c \
cmd-queue.c \
colour.c \
control.c \
control-notify.c \
environ.c \
format.c \
grid-cell.c \
grid-view.c \
grid.c \
input-keys.c \
input.c \
job.c \
key-bindings.c \
key-string.c \
layout-custom.c \
layout-set.c \
layout.c \
log.c \
mode-key.c \
names.c \
notify.c \
options-table.c \
options.c \
paste.c \
procname.c \
resize.c \
screen-redraw.c \
screen-write.c \
screen.c \
server-client.c \
server-fn.c \
server-window.c \
server.c \
session.c \
signal.c \
status.c \
style.c \
tmux.c \
tty-acs.c \
tty-keys.c \
tty-term.c \
tty.c \
utf8.c \
window-choose.c \
window-clock.c \
window-copy.c \
window.c \
xmalloc.c \
xterm-keys.c
CDIAGFLAGS+= -Wno-long-long -Wall -W -Wnested-externs -Wformat=2
CDIAGFLAGS+= -Wmissing-prototypes -Wstrict-prototypes -Wmissing-declarations
CDIAGFLAGS+= -Wwrite-strings -Wshadow -Wpointer-arith -Wsign-compare
CDIAGFLAGS+= -Wundef -Wbad-function-cast -Winline -Wcast-align
LDADD= -lutil -lcurses -levent
DPADD= ${LIBUTIL} ${LIBCURSES} ${LIBEVENT}
.include <bsd.prog.mk>

View File

@ -20,6 +20,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <unistd.h>
#include "tmux.h" #include "tmux.h"
@ -77,7 +78,6 @@ struct args *
args_parse(const char *template, int argc, char **argv) args_parse(const char *template, int argc, char **argv)
{ {
struct args *args; struct args *args;
char *ptr;
int opt; int opt;
args = xcalloc(1, sizeof *args); args = xcalloc(1, sizeof *args);
@ -88,7 +88,7 @@ args_parse(const char *template, int argc, char **argv)
while ((opt = getopt(argc, argv, template)) != -1) { while ((opt = getopt(argc, argv, template)) != -1) {
if (opt < 0) if (opt < 0)
continue; continue;
if (opt == '?' || (ptr = strchr(template, opt)) == NULL) { if (opt == '?' || strchr(template, opt) == NULL) {
args_free(args); args_free(args);
return (NULL); return (NULL);
} }
@ -204,19 +204,15 @@ args_set(struct args *args, u_char ch, const char *value)
/* Replace existing argument. */ /* Replace existing argument. */
if ((entry = args_find(args, ch)) != NULL) { if ((entry = args_find(args, ch)) != NULL) {
free(entry->value); free(entry->value);
if (value != NULL) entry->value = NULL;
entry->value = xstrdup(value); } else {
else entry = xcalloc(1, sizeof *entry);
entry->value = NULL; entry->flag = ch;
return; RB_INSERT(args_tree, &args->tree, entry);
} }
entry = xcalloc(1, sizeof *entry);
entry->flag = ch;
if (value != NULL) if (value != NULL)
entry->value = xstrdup(value); entry->value = xstrdup(value);
RB_INSERT(args_tree, &args->tree, entry);
} }
/* Get argument value. Will be NULL if it isn't present. */ /* Get argument value. Will be NULL if it isn't present. */

View File

@ -118,10 +118,15 @@ retry:
close(fd); close(fd);
xasprintf(&lockfile, "%s.lock", path); xasprintf(&lockfile, "%s.lock", path);
if ((lockfd = client_get_lock(lockfile)) == -1) if ((lockfd = client_get_lock(lockfile)) == -1) {
free(lockfile);
goto retry; goto retry;
if (unlink(path) != 0 && errno != ENOENT) }
if (unlink(path) != 0 && errno != ENOENT) {
free(lockfile);
close(lockfd);
return (-1); return (-1);
}
fd = server_start(lockfd, lockfile); fd = server_start(lockfd, lockfile);
free(lockfile); free(lockfile);
close(lockfd); close(lockfd);
@ -232,7 +237,8 @@ client_main(int argc, char **argv, int flags)
/* Initialise the client socket and start the server. */ /* Initialise the client socket and start the server. */
fd = client_connect(socket_path, cmdflags & CMD_STARTSERVER); fd = client_connect(socket_path, cmdflags & CMD_STARTSERVER);
if (fd == -1) { if (fd == -1) {
fprintf(stderr, "failed to connect to server\n"); fprintf(stderr, "failed to connect to server: %s\n",
strerror(errno));
return (1); return (1);
} }

View File

@ -47,6 +47,9 @@ cmd_attach_session(struct cmd_q *cmdq, const char *tflag, int dflag, int rflag,
{ {
struct session *s; struct session *s;
struct client *c; struct client *c;
struct winlink *wl = NULL;
struct window *w = NULL;
struct window_pane *wp = NULL;
const char *update; const char *update;
char *cause; char *cause;
u_int i; u_int i;
@ -59,12 +62,31 @@ cmd_attach_session(struct cmd_q *cmdq, const char *tflag, int dflag, int rflag,
return (CMD_RETURN_ERROR); return (CMD_RETURN_ERROR);
} }
if ((s = cmd_find_session(cmdq, tflag, 1)) == NULL) if (tflag == NULL) {
return (CMD_RETURN_ERROR); if ((s = cmd_find_session(cmdq, tflag, 1)) == NULL)
return (CMD_RETURN_ERROR);
} else if (tflag[strcspn(tflag, ":.")] != '\0') {
if ((wl = cmd_find_pane(cmdq, tflag, &s, &wp)) == NULL)
return (CMD_RETURN_ERROR);
} else {
if ((s = cmd_find_session(cmdq, tflag, 1)) == NULL)
return (CMD_RETURN_ERROR);
w = cmd_lookup_windowid(tflag);
if (w == NULL && (wp = cmd_lookup_paneid(tflag)) != NULL)
w = wp->window;
if (w != NULL)
wl = winlink_find_by_window(&s->windows, w);
}
if (cmdq->client == NULL) if (cmdq->client == NULL)
return (CMD_RETURN_NORMAL); return (CMD_RETURN_NORMAL);
if (wl != NULL) {
if (wp != NULL)
window_set_active_pane(wp->window, wp);
session_set_current(s, wl);
}
if (cmdq->client->session != NULL) { if (cmdq->client->session != NULL) {
if (dflag) { if (dflag) {
/* /*

View File

@ -38,10 +38,20 @@ const struct cmd_entry cmd_kill_server_entry = {
cmd_kill_server_exec cmd_kill_server_exec
}; };
const struct cmd_entry cmd_start_server_entry = {
"start-server", "start",
"", 0, 0,
"",
CMD_STARTSERVER,
NULL,
cmd_kill_server_exec
};
enum cmd_retval enum cmd_retval
cmd_kill_server_exec(unused struct cmd *self, unused struct cmd_q *cmdq) cmd_kill_server_exec(struct cmd *self, unused struct cmd_q *cmdq)
{ {
kill(getpid(), SIGTERM); if (self->entry == &cmd_kill_server_entry)
kill(getpid(), SIGTERM);
return (CMD_RETURN_NORMAL); return (CMD_RETURN_NORMAL);
} }

View File

@ -107,13 +107,16 @@ cmd_new_session_exec(struct cmd *self, struct cmd_q *cmdq)
cp = format_expand(ft, args_get(args, 'c')); cp = format_expand(ft, args_get(args, 'c'));
format_free(ft); format_free(ft);
fd = open(cp, O_RDONLY|O_DIRECTORY); if (cp != NULL && *cp != '\0') {
free(cp); fd = open(cp, O_RDONLY|O_DIRECTORY);
if (fd == -1) { free(cp);
cmdq_error(cmdq, "bad working directory: %s", if (fd == -1) {
strerror(errno)); cmdq_error(cmdq, "bad working directory: %s",
return (CMD_RETURN_ERROR); strerror(errno));
} return (CMD_RETURN_ERROR);
}
} else if (cp != NULL)
free(cp);
cwd = fd; cwd = fd;
} else if (c != NULL && c->session == NULL) } else if (c != NULL && c->session == NULL)
cwd = c->cwd; cwd = c->cwd;

View File

@ -82,6 +82,37 @@ cmd_new_window_exec(struct cmd *self, struct cmd_q *cmdq)
} }
detached = args_has(args, 'd'); detached = args_has(args, 'd');
if (args->argc == 0)
cmd = options_get_string(&s->options, "default-command");
else
cmd = args->argv[0];
if (args_has(args, 'c')) {
ft = format_create();
if ((c = cmd_find_client(cmdq, NULL, 1)) != NULL)
format_client(ft, c);
format_session(ft, s);
format_winlink(ft, s, s->curw);
format_window_pane(ft, s->curw->window->active);
cp = format_expand(ft, args_get(args, 'c'));
format_free(ft);
if (cp != NULL && *cp != '\0') {
fd = open(cp, O_RDONLY|O_DIRECTORY);
free(cp);
if (fd == -1) {
cmdq_error(cmdq, "bad working directory: %s",
strerror(errno));
return (CMD_RETURN_ERROR);
}
} else if (cp != NULL)
free(cp);
cwd = fd;
} else if (cmdq->client != NULL && cmdq->client->session == NULL)
cwd = cmdq->client->cwd;
else
cwd = s->cwd;
wl = NULL; wl = NULL;
if (idx != -1) if (idx != -1)
wl = winlink_find_by_index(&s->windows, idx); wl = winlink_find_by_index(&s->windows, idx);
@ -102,34 +133,6 @@ cmd_new_window_exec(struct cmd *self, struct cmd_q *cmdq)
} }
} }
if (args->argc == 0)
cmd = options_get_string(&s->options, "default-command");
else
cmd = args->argv[0];
if (args_has(args, 'c')) {
ft = format_create();
if ((c = cmd_find_client(cmdq, NULL, 1)) != NULL)
format_client(ft, c);
format_session(ft, s);
format_winlink(ft, s, s->curw);
format_window_pane(ft, s->curw->window->active);
cp = format_expand(ft, args_get(args, 'c'));
format_free(ft);
fd = open(cp, O_RDONLY|O_DIRECTORY);
free(cp);
if (fd == -1) {
cmdq_error(cmdq, "bad working directory: %s",
strerror(errno));
return (CMD_RETURN_ERROR);
}
cwd = fd;
} else if (cmdq->client != NULL && cmdq->client->session == NULL)
cwd = cmdq->client->cwd;
else
cwd = s->cwd;
if (idx == -1) if (idx == -1)
idx = -1 - options_get_number(&s->options, "base-index"); idx = -1 - options_get_number(&s->options, "base-index");
wl = session_new(s, args_get(args, 'n'), cmd, cwd, idx, &cause); wl = session_new(s, args_get(args, 'n'), cmd, cwd, idx, &cause);

View File

@ -69,9 +69,7 @@ cmdq_print(struct cmd_q *cmdq, const char *fmt, ...)
if (c == NULL) if (c == NULL)
/* nothing */; /* nothing */;
else if (c->session == NULL || (c->flags & CLIENT_CONTROL)) { else if (c->session == NULL || (c->flags & CLIENT_CONTROL)) {
va_start(ap, fmt);
evbuffer_add_vprintf(c->stdout_data, fmt, ap); evbuffer_add_vprintf(c->stdout_data, fmt, ap);
va_end(ap);
evbuffer_add(c->stdout_data, "\n", 1); evbuffer_add(c->stdout_data, "\n", 1);
server_push_stdout(c); server_push_stdout(c);
@ -104,9 +102,7 @@ cmdq_info(struct cmd_q *cmdq, const char *fmt, ...)
if (c == NULL) if (c == NULL)
/* nothing */; /* nothing */;
else if (c->session == NULL || (c->flags & CLIENT_CONTROL)) { else if (c->session == NULL || (c->flags & CLIENT_CONTROL)) {
va_start(ap, fmt);
evbuffer_add_vprintf(c->stdout_data, fmt, ap); evbuffer_add_vprintf(c->stdout_data, fmt, ap);
va_end(ap);
evbuffer_add(c->stdout_data, "\n", 1); evbuffer_add(c->stdout_data, "\n", 1);
server_push_stdout(c); server_push_stdout(c);

View File

@ -60,6 +60,9 @@ struct options_entry *cmd_set_option_flag(struct cmd *, struct cmd_q *,
struct options_entry *cmd_set_option_choice(struct cmd *, struct cmd_q *, struct options_entry *cmd_set_option_choice(struct cmd *, struct cmd_q *,
const struct options_table_entry *, struct options *, const struct options_table_entry *, struct options *,
const char *); const char *);
struct options_entry *cmd_set_option_style(struct cmd *, struct cmd_q *,
const struct options_table_entry *, struct options *,
const char *);
const struct cmd_entry cmd_set_option_entry = { const struct cmd_entry cmd_set_option_entry = {
"set-option", "set", "set-option", "set",
@ -304,9 +307,11 @@ cmd_set_option_set(struct cmd *self, struct cmd_q *cmdq,
break; break;
case OPTIONS_TABLE_COLOUR: case OPTIONS_TABLE_COLOUR:
o = cmd_set_option_colour(self, cmdq, oe, oo, value); o = cmd_set_option_colour(self, cmdq, oe, oo, value);
style_update_new(oo, o->name, oe->style);
break; break;
case OPTIONS_TABLE_ATTRIBUTES: case OPTIONS_TABLE_ATTRIBUTES:
o = cmd_set_option_attributes(self, cmdq, oe, oo, value); o = cmd_set_option_attributes(self, cmdq, oe, oo, value);
style_update_new(oo, o->name, oe->style);
break; break;
case OPTIONS_TABLE_FLAG: case OPTIONS_TABLE_FLAG:
o = cmd_set_option_flag(self, cmdq, oe, oo, value); o = cmd_set_option_flag(self, cmdq, oe, oo, value);
@ -314,6 +319,9 @@ cmd_set_option_set(struct cmd *self, struct cmd_q *cmdq,
case OPTIONS_TABLE_CHOICE: case OPTIONS_TABLE_CHOICE:
o = cmd_set_option_choice(self, cmdq, oe, oo, value); o = cmd_set_option_choice(self, cmdq, oe, oo, value);
break; break;
case OPTIONS_TABLE_STYLE:
o = cmd_set_option_style(self, cmdq, oe, oo, value);
break;
} }
if (o == NULL) if (o == NULL)
return (-1); return (-1);
@ -462,3 +470,23 @@ cmd_set_option_choice(unused struct cmd *self, struct cmd_q *cmdq,
return (options_set_number(oo, oe->name, choice)); return (options_set_number(oo, oe->name, choice));
} }
/* Set a style option. */
struct options_entry *
cmd_set_option_style(struct cmd *self, struct cmd_q *cmdq,
const struct options_table_entry *oe, struct options *oo,
const char *value)
{
struct args *args = self->args;
struct options_entry *o;
int append;
append = args_has(args, 'a');
if ((o = options_set_style(oo, oe->name, value, append)) == NULL) {
cmdq_error(cmdq, "bad style: %s", value);
return (NULL);
}
style_update_old(oo, oe->name, &o->style);
return (o);
}

View File

@ -20,6 +20,8 @@
#include <string.h> #include <string.h>
#include <time.h> #include <time.h>
#include <unistd.h>
#include <vis.h>
#include "tmux.h" #include "tmux.h"
@ -31,13 +33,98 @@ enum cmd_retval cmd_show_messages_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_show_messages_entry = { const struct cmd_entry cmd_show_messages_entry = {
"show-messages", "showmsgs", "show-messages", "showmsgs",
"t:", 0, 0, "IJTt:", 0, 0,
CMD_TARGET_CLIENT_USAGE, "[-IJT] " CMD_TARGET_CLIENT_USAGE,
0, 0,
NULL, NULL,
cmd_show_messages_exec cmd_show_messages_exec
}; };
const struct cmd_entry cmd_server_info_entry = {
"server-info", "info",
"", 0, 0,
"",
0,
NULL,
cmd_show_messages_exec
};
void cmd_show_messages_server (struct cmd_q *);
void cmd_show_messages_terminals (struct cmd_q *);
void cmd_show_messages_jobs (struct cmd_q *);
void
cmd_show_messages_server (struct cmd_q *cmdq)
{
char *tim;
tim = ctime(&start_time);
*strchr(tim, '\n') = '\0';
cmdq_print(cmdq, "started %s", tim);
cmdq_print(cmdq, "socket path %s", socket_path);
cmdq_print(cmdq, "debug level %d", debug_level);
cmdq_print(cmdq, "protocol version %d", PROTOCOL_VERSION);
}
void
cmd_show_messages_terminals (struct cmd_q *cmdq)
{
struct tty_term *term;
const struct tty_term_code_entry *ent;
struct tty_code *code;
u_int i, n;
char out[80];
n = 0;
LIST_FOREACH(term, &tty_terms, entry) {
cmdq_print(cmdq,
"Terminal %u: %s [references=%u, flags=0x%x]:",
n, term->name, term->references, term->flags);
n++;
for (i = 0; i < NTTYCODE; i++) {
ent = &tty_term_codes[i];
code = &term->codes[ent->code];
switch (code->type) {
case TTYCODE_NONE:
cmdq_print(cmdq, "%4u: %s: [missing]",
ent->code, ent->name);
break;
case TTYCODE_STRING:
strnvis(out, code->value.string, sizeof out,
VIS_OCTAL|VIS_TAB|VIS_NL);
cmdq_print(cmdq, "%4u: %s: (string) %s",
ent->code, ent->name, out);
break;
case TTYCODE_NUMBER:
cmdq_print(cmdq, "%4u: %s: (number) %d",
ent->code, ent->name, code->value.number);
break;
case TTYCODE_FLAG:
cmdq_print(cmdq, "%4u: %s: (flag) %s",
ent->code, ent->name,
code->value.flag ? "true" : "false");
break;
}
}
}
}
void
cmd_show_messages_jobs (struct cmd_q *cmdq)
{
struct job *job;
u_int n;
n = 0;
LIST_FOREACH(job, &all_jobs, lentry) {
cmdq_print(cmdq,
"Job %u: %s [fd=%d, pid=%d, status=%d]",
n, job->cmd, job->fd, job->pid, job->status);
n++;
}
}
enum cmd_retval enum cmd_retval
cmd_show_messages_exec(struct cmd *self, struct cmd_q *cmdq) cmd_show_messages_exec(struct cmd *self, struct cmd_q *cmdq)
{ {
@ -46,6 +133,27 @@ cmd_show_messages_exec(struct cmd *self, struct cmd_q *cmdq)
struct message_entry *msg; struct message_entry *msg;
char *tim; char *tim;
u_int i; u_int i;
int done;
done = 0;
if (args_has (args, 'I') || self->entry == &cmd_server_info_entry) {
cmd_show_messages_server (cmdq);
done = 1;
}
if (args_has (args, 'T') || self->entry == &cmd_server_info_entry) {
if (done)
cmdq_print (cmdq, "%s", "");
cmd_show_messages_terminals (cmdq);
done = 1;
}
if (args_has (args, 'J') || self->entry == &cmd_server_info_entry) {
if (done)
cmdq_print (cmdq, "%s", "");
cmd_show_messages_jobs (cmdq);
done = 1;
}
if (done)
return (CMD_RETURN_NORMAL);
if ((c = cmd_find_client(cmdq, args_get(args, 't'), 0)) == NULL) if ((c = cmd_find_client(cmdq, args_get(args, 't'), 0)) == NULL)
return (CMD_RETURN_ERROR); return (CMD_RETURN_ERROR);

View File

@ -94,13 +94,16 @@ cmd_split_window_exec(struct cmd *self, struct cmd_q *cmdq)
cp = format_expand(ft, args_get(args, 'c')); cp = format_expand(ft, args_get(args, 'c'));
format_free(ft); format_free(ft);
fd = open(cp, O_RDONLY|O_DIRECTORY); if (cp != NULL && *cp != '\0') {
free(cp); fd = open(cp, O_RDONLY|O_DIRECTORY);
if (fd == -1) { free(cp);
cmdq_error(cmdq, "bad working directory: %s", if (fd == -1) {
strerror(errno)); cmdq_error(cmdq, "bad working directory: %s",
return (CMD_RETURN_ERROR); strerror(errno));
} return (CMD_RETURN_ERROR);
}
} else if (cp != NULL)
free(cp);
cwd = fd; cwd = fd;
} else if (cmdq->client != NULL && cmdq->client->session == NULL) } else if (cmdq->client != NULL && cmdq->client->session == NULL)
cwd = cmdq->client->cwd; cwd = cmdq->client->cwd;

View File

@ -1,42 +0,0 @@
/* $Id$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
*
* 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 <sys/types.h>
#include "tmux.h"
/*
* Start the server and do nothing else.
*/
enum cmd_retval cmd_start_server_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_start_server_entry = {
"start-server", "start",
"", 0, 0,
"",
CMD_STARTSERVER,
NULL,
cmd_start_server_exec
};
enum cmd_retval
cmd_start_server_exec(unused struct cmd *self, unused struct cmd_q *cmdq)
{
return (CMD_RETURN_NORMAL);
}

View File

@ -59,9 +59,13 @@ cmd_switch_client_key_binding(struct cmd *self, int key)
enum cmd_retval enum cmd_retval
cmd_switch_client_exec(struct cmd *self, struct cmd_q *cmdq) cmd_switch_client_exec(struct cmd *self, struct cmd_q *cmdq)
{ {
struct args *args = self->args; struct args *args = self->args;
struct client *c; struct client *c;
struct session *s; struct session *s;
struct winlink *wl = NULL;
struct window *w = NULL;
struct window_pane *wp = NULL;
const char *tflag;
if ((c = cmd_find_client(cmdq, args_get(args, 'c'), 0)) == NULL) if ((c = cmd_find_client(cmdq, args_get(args, 'c'), 0)) == NULL)
return (CMD_RETURN_ERROR); return (CMD_RETURN_ERROR);
@ -76,7 +80,7 @@ cmd_switch_client_exec(struct cmd *self, struct cmd_q *cmdq)
} }
} }
s = NULL; tflag = args_get(args, 't');
if (args_has(args, 'n')) { if (args_has(args, 'n')) {
if ((s = session_next_session(c->session)) == NULL) { if ((s = session_next_session(c->session)) == NULL) {
cmdq_error(cmdq, "can't find next session"); cmdq_error(cmdq, "can't find next session");
@ -94,10 +98,33 @@ cmd_switch_client_exec(struct cmd *self, struct cmd_q *cmdq)
cmdq_error(cmdq, "can't find last session"); cmdq_error(cmdq, "can't find last session");
return (CMD_RETURN_ERROR); return (CMD_RETURN_ERROR);
} }
} else } else {
s = cmd_find_session(cmdq, args_get(args, 't'), 0); if (tflag == NULL) {
if (s == NULL) if ((s = cmd_find_session(cmdq, tflag, 1)) == NULL)
return (CMD_RETURN_ERROR); return (CMD_RETURN_ERROR);
} else if (tflag[strcspn(tflag, ":.")] != '\0') {
if ((wl = cmd_find_pane(cmdq, tflag, &s, &wp)) == NULL)
return (CMD_RETURN_ERROR);
} else {
if ((s = cmd_find_session(cmdq, tflag, 1)) == NULL)
return (CMD_RETURN_ERROR);
w = cmd_lookup_windowid(tflag);
if (w == NULL &&
(wp = cmd_lookup_paneid(tflag)) != NULL)
w = wp->window;
if (w != NULL)
wl = winlink_find_by_window(&s->windows, w);
}
if (cmdq->client == NULL)
return (CMD_RETURN_NORMAL);
if (wl != NULL) {
if (wp != NULL)
window_set_active_pane(wp->window, wp);
session_set_current(s, wl);
}
}
if (c->session != NULL) if (c->session != NULL)
c->last_session = c->session; c->last_session = c->session;

2
cmd.c
View File

@ -125,9 +125,7 @@ struct session *cmd_lookup_session(const char *, int *);
struct session *cmd_lookup_session_id(const char *); struct session *cmd_lookup_session_id(const char *);
struct winlink *cmd_lookup_window(struct session *, const char *, int *); struct winlink *cmd_lookup_window(struct session *, const char *, int *);
int cmd_lookup_index(struct session *, const char *, int *); int cmd_lookup_index(struct session *, const char *, int *);
struct window_pane *cmd_lookup_paneid(const char *);
struct winlink *cmd_lookup_winlink_windowid(struct session *, const char *); struct winlink *cmd_lookup_winlink_windowid(struct session *, const char *);
struct window *cmd_lookup_windowid(const char *);
struct session *cmd_window_session(struct cmd_q *, struct window *, struct session *cmd_window_session(struct cmd_q *, struct window *,
struct winlink **); struct winlink **);
struct winlink *cmd_find_window_offset(const char *, struct session *, int *); struct winlink *cmd_find_window_offset(const char *, struct session *, int *);

View File

@ -321,6 +321,13 @@ format_expand(struct format_tree *ft, const char *fmt)
break; break;
fmt += n + 1; fmt += n + 1;
continue; continue;
case '#':
while (len - off < 2) {
buf = xrealloc(buf, 2, len);
len *= 2;
}
buf[off++] = '#';
continue;
default: default:
s = NULL; s = NULL;
if (ch >= 'A' && ch <= 'Z') if (ch >= 'A' && ch <= 'Z')

5
grid.c
View File

@ -37,7 +37,6 @@
/* Default grid cell data. */ /* Default grid cell data. */
const struct grid_cell grid_default_cell = { 0, 0, 8, 8, (1 << 4) | 1, " " }; const struct grid_cell grid_default_cell = { 0, 0, 8, 8, (1 << 4) | 1, " " };
const struct grid_cell grid_marker_cell = { 0, 0, 8, 8, (1 << 4) | 1, "_" };
#define grid_put_cell(gd, px, py, gc) do { \ #define grid_put_cell(gd, px, py, gc) do { \
memcpy(&gd->linedata[py].celldata[px], \ memcpy(&gd->linedata[py].celldata[px], \
@ -124,7 +123,7 @@ grid_compare(struct grid *ga, struct grid *gb)
struct grid_cell *gca, *gcb; struct grid_cell *gca, *gcb;
u_int xx, yy; u_int xx, yy;
if (ga->sx != gb->sx || ga->sy != ga->sy) if (ga->sx != gb->sx || ga->sy != gb->sy)
return (1); return (1);
for (yy = 0; yy < ga->sy; yy++) { for (yy = 0; yy < ga->sy; yy++) {
@ -644,7 +643,7 @@ grid_string_cells(struct grid *gd, u_int px, u_int py, u_int nx,
if (trim) { if (trim) {
while (off > 0 && buf[off - 1] == ' ') while (off > 0 && buf[off - 1] == ' ')
off--; off--;
} }
buf[off] = '\0'; buf[off] = '\0';
return (buf); return (buf);

57
input.c
View File

@ -74,6 +74,7 @@ void input_csi_dispatch_rm(struct input_ctx *);
void input_csi_dispatch_rm_private(struct input_ctx *); 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_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 *);
@ -154,6 +155,7 @@ enum input_csi_type {
INPUT_CSI_SM_PRIVATE, INPUT_CSI_SM_PRIVATE,
INPUT_CSI_TBC, INPUT_CSI_TBC,
INPUT_CSI_VPA, INPUT_CSI_VPA,
INPUT_CSI_WINOPS,
}; };
/* Control (CSI) command table. */ /* Control (CSI) command table. */
@ -188,6 +190,7 @@ const struct input_table_entry input_csi_table[] = {
{ 'q', " ", INPUT_CSI_DECSCUSR }, { 'q', " ", INPUT_CSI_DECSCUSR },
{ 'r', "", INPUT_CSI_DECSTBM }, { 'r', "", INPUT_CSI_DECSTBM },
{ 's', "", INPUT_CSI_SCP }, { 's', "", INPUT_CSI_SCP },
{ 't', "", INPUT_CSI_WINOPS },
{ 'u', "", INPUT_CSI_RCP }, { 'u', "", INPUT_CSI_RCP },
}; };
@ -1077,7 +1080,7 @@ input_csi_dispatch(struct input_ctx *ictx)
struct screen_write_ctx *sctx = &ictx->ctx; struct screen_write_ctx *sctx = &ictx->ctx;
struct screen *s = sctx->s; struct screen *s = sctx->s;
struct input_table_entry *entry; struct input_table_entry *entry;
int n, m; int n, m;
if (ictx->flags & INPUT_DISCARD) if (ictx->flags & INPUT_DISCARD)
return (0); return (0);
@ -1117,6 +1120,9 @@ input_csi_dispatch(struct input_ctx *ictx)
m = input_get(ictx, 1, 1, 1); m = input_get(ictx, 1, 1, 1);
screen_write_cursormove(sctx, m - 1, n - 1); screen_write_cursormove(sctx, m - 1, n - 1);
break; break;
case INPUT_CSI_WINOPS:
input_csi_dispatch_winops(ictx);
break;
case INPUT_CSI_CUU: case INPUT_CSI_CUU:
screen_write_cursorup(sctx, input_get(ictx, 0, 1, 1)); screen_write_cursorup(sctx, input_get(ictx, 0, 1, 1));
break; break;
@ -1430,6 +1436,55 @@ input_csi_dispatch_sm_private(struct input_ctx *ictx)
} }
} }
/* Handle CSI window operations. */
void
input_csi_dispatch_winops(struct input_ctx *ictx)
{
struct window_pane *wp = ictx->wp;
int n, m;
m = 0;
while ((n = input_get(ictx, m, 0, -1)) != -1) {
switch (n) {
case 1:
case 2:
case 5:
case 6:
case 7:
case 11:
case 13:
case 14:
case 19:
case 20:
case 21:
case 24:
break;
case 3:
case 4:
case 8:
m++;
if (input_get(ictx, m, 0, -1) == -1)
return;
/* FALLTHROUGH */
case 9:
case 10:
case 22:
case 23:
m++;
if (input_get(ictx, m, 0, -1) == -1)
return;
break;
case 18:
input_reply(ictx, "\033[8;%u;%u", wp->sy, wp->sx);
break;
default:
log_debug("%s: unknown '%c'", __func__, ictx->ch);
break;
}
m++;
}
}
/* Handle CSI SGR. */ /* Handle CSI SGR. */
void void
input_csi_dispatch_sgr(struct input_ctx *ictx) input_csi_dispatch_sgr(struct input_ctx *ictx)

View File

@ -195,32 +195,43 @@ const struct options_table_entry session_options_table[] = {
{ .name = "message-attr", { .name = "message-attr",
.type = OPTIONS_TABLE_ATTRIBUTES, .type = OPTIONS_TABLE_ATTRIBUTES,
.default_num = 0 .default_num = 0,
.style = "message-style"
}, },
{ .name = "message-bg", { .name = "message-bg",
.type = OPTIONS_TABLE_COLOUR, .type = OPTIONS_TABLE_COLOUR,
.default_num = 3 .default_num = 3,
.style = "message-style"
}, },
{ .name = "message-command-attr", { .name = "message-command-attr",
.type = OPTIONS_TABLE_ATTRIBUTES, .type = OPTIONS_TABLE_ATTRIBUTES,
.default_num = 0 .default_num = 0,
.style = "message-command-style"
}, },
{ .name = "message-command-bg", { .name = "message-command-bg",
.type = OPTIONS_TABLE_COLOUR, .type = OPTIONS_TABLE_COLOUR,
.default_num = 0 .default_num = 0,
.style = "message-command-style"
}, },
{ .name = "message-command-fg", { .name = "message-command-fg",
.type = OPTIONS_TABLE_COLOUR, .type = OPTIONS_TABLE_COLOUR,
.default_num = 3 .default_num = 3,
.style = "message-command-style"
},
{ .name = "message-command-style",
.type = OPTIONS_TABLE_STYLE,
.default_str = "bg=black,fg=yellow"
}, },
{ .name = "message-fg", { .name = "message-fg",
.type = OPTIONS_TABLE_COLOUR, .type = OPTIONS_TABLE_COLOUR,
.default_num = 0 .default_num = 0,
.style = "message-style"
}, },
{ .name = "message-limit", { .name = "message-limit",
@ -230,6 +241,11 @@ const struct options_table_entry session_options_table[] = {
.default_num = 20 .default_num = 20
}, },
{ .name = "message-style",
.type = OPTIONS_TABLE_STYLE,
.default_str = "bg=yellow,fg=black"
},
{ .name = "mouse-resize-pane", { .name = "mouse-resize-pane",
.type = OPTIONS_TABLE_FLAG, .type = OPTIONS_TABLE_FLAG,
.default_num = 0 .default_num = 0
@ -252,22 +268,36 @@ const struct options_table_entry session_options_table[] = {
{ .name = "pane-active-border-bg", { .name = "pane-active-border-bg",
.type = OPTIONS_TABLE_COLOUR, .type = OPTIONS_TABLE_COLOUR,
.default_num = 8 .default_num = 8,
.style = "pane-active-border-style"
}, },
{ .name = "pane-active-border-fg", { .name = "pane-active-border-fg",
.type = OPTIONS_TABLE_COLOUR, .type = OPTIONS_TABLE_COLOUR,
.default_num = 2 .default_num = 2,
.style = "pane-active-border-style"
},
{ .name = "pane-active-border-style",
.type = OPTIONS_TABLE_STYLE,
.default_str = "fg=green"
}, },
{ .name = "pane-border-bg", { .name = "pane-border-bg",
.type = OPTIONS_TABLE_COLOUR, .type = OPTIONS_TABLE_COLOUR,
.default_num = 8 .default_num = 8,
.style = "pane-border-style"
}, },
{ .name = "pane-border-fg", { .name = "pane-border-fg",
.type = OPTIONS_TABLE_COLOUR, .type = OPTIONS_TABLE_COLOUR,
.default_num = 8 .default_num = 8,
.style = "pane-border-style"
},
{ .name = "pane-border-style",
.type = OPTIONS_TABLE_STYLE,
.default_str = "default"
}, },
{ .name = "prefix", { .name = "prefix",
@ -314,17 +344,20 @@ const struct options_table_entry session_options_table[] = {
{ .name = "status-attr", { .name = "status-attr",
.type = OPTIONS_TABLE_ATTRIBUTES, .type = OPTIONS_TABLE_ATTRIBUTES,
.default_num = 0 .default_num = 0,
.style = "status-style"
}, },
{ .name = "status-bg", { .name = "status-bg",
.type = OPTIONS_TABLE_COLOUR, .type = OPTIONS_TABLE_COLOUR,
.default_num = 2 .default_num = 2,
.style = "status-style"
}, },
{ .name = "status-fg", { .name = "status-fg",
.type = OPTIONS_TABLE_COLOUR, .type = OPTIONS_TABLE_COLOUR,
.default_num = 0 .default_num = 0,
.style = "status-style"
}, },
{ .name = "status-interval", { .name = "status-interval",
@ -353,17 +386,20 @@ const struct options_table_entry session_options_table[] = {
{ .name = "status-left-attr", { .name = "status-left-attr",
.type = OPTIONS_TABLE_ATTRIBUTES, .type = OPTIONS_TABLE_ATTRIBUTES,
.default_num = 0 .default_num = 0,
.style = "status-left-style"
}, },
{ .name = "status-left-bg", { .name = "status-left-bg",
.type = OPTIONS_TABLE_COLOUR, .type = OPTIONS_TABLE_COLOUR,
.default_num = 8 .default_num = 8,
.style = "status-left-style"
}, },
{ .name = "status-left-fg", { .name = "status-left-fg",
.type = OPTIONS_TABLE_COLOUR, .type = OPTIONS_TABLE_COLOUR,
.default_num = 8 .default_num = 8,
.style = "status-left-style"
}, },
{ .name = "status-left-length", { .name = "status-left-length",
@ -373,6 +409,11 @@ const struct options_table_entry session_options_table[] = {
.default_num = 10 .default_num = 10
}, },
{ .name = "status-left-style",
.type = OPTIONS_TABLE_STYLE,
.default_str = "default"
},
{ .name = "status-position", { .name = "status-position",
.type = OPTIONS_TABLE_CHOICE, .type = OPTIONS_TABLE_CHOICE,
.choices = options_table_status_position_list, .choices = options_table_status_position_list,
@ -386,17 +427,20 @@ const struct options_table_entry session_options_table[] = {
{ .name = "status-right-attr", { .name = "status-right-attr",
.type = OPTIONS_TABLE_ATTRIBUTES, .type = OPTIONS_TABLE_ATTRIBUTES,
.default_num = 0 .default_num = 0,
.style = "status-right-style"
}, },
{ .name = "status-right-bg", { .name = "status-right-bg",
.type = OPTIONS_TABLE_COLOUR, .type = OPTIONS_TABLE_COLOUR,
.default_num = 8 .default_num = 8,
.style = "status-right-style"
}, },
{ .name = "status-right-fg", { .name = "status-right-fg",
.type = OPTIONS_TABLE_COLOUR, .type = OPTIONS_TABLE_COLOUR,
.default_num = 8 .default_num = 8,
.style = "status-right-style"
}, },
{ .name = "status-right-length", { .name = "status-right-length",
@ -406,6 +450,16 @@ const struct options_table_entry session_options_table[] = {
.default_num = 40 .default_num = 40
}, },
{ .name = "status-right-style",
.type = OPTIONS_TABLE_STYLE,
.default_str = "default"
},
{ .name = "status-style",
.type = OPTIONS_TABLE_STYLE,
.default_str = "bg=green,fg=black"
},
{ .name = "status-utf8", { .name = "status-utf8",
.type = OPTIONS_TABLE_FLAG, .type = OPTIONS_TABLE_FLAG,
.default_num = 0 /* overridden in main() */ .default_num = 0 /* overridden in main() */
@ -536,17 +590,20 @@ const struct options_table_entry window_options_table[] = {
{ .name = "mode-attr", { .name = "mode-attr",
.type = OPTIONS_TABLE_ATTRIBUTES, .type = OPTIONS_TABLE_ATTRIBUTES,
.default_num = 0 .default_num = 0,
.style = "mode-style"
}, },
{ .name = "mode-bg", { .name = "mode-bg",
.type = OPTIONS_TABLE_COLOUR, .type = OPTIONS_TABLE_COLOUR,
.default_num = 3 .default_num = 3,
.style = "mode-style"
}, },
{ .name = "mode-fg", { .name = "mode-fg",
.type = OPTIONS_TABLE_COLOUR, .type = OPTIONS_TABLE_COLOUR,
.default_num = 0 .default_num = 0,
.style = "mode-style"
}, },
{ .name = "mode-keys", { .name = "mode-keys",
@ -561,6 +618,11 @@ const struct options_table_entry window_options_table[] = {
.default_num = 0 .default_num = 0
}, },
{ .name = "mode-style",
.type = OPTIONS_TABLE_STYLE,
.default_str = "bg=yellow,fg=black"
},
{ .name = "monitor-activity", { .name = "monitor-activity",
.type = OPTIONS_TABLE_FLAG, .type = OPTIONS_TABLE_FLAG,
.default_num = 0 .default_num = 0
@ -616,72 +678,101 @@ const struct options_table_entry window_options_table[] = {
{ .name = "window-status-activity-attr", { .name = "window-status-activity-attr",
.type = OPTIONS_TABLE_ATTRIBUTES, .type = OPTIONS_TABLE_ATTRIBUTES,
.default_num = GRID_ATTR_REVERSE .default_num = GRID_ATTR_REVERSE,
.style = "window-status-activity-style"
}, },
{ .name = "window-status-activity-bg", { .name = "window-status-activity-bg",
.type = OPTIONS_TABLE_COLOUR, .type = OPTIONS_TABLE_COLOUR,
.default_num = 8 .default_num = 8,
.style = "window-status-activity-style"
}, },
{ .name = "window-status-activity-fg", { .name = "window-status-activity-fg",
.type = OPTIONS_TABLE_COLOUR, .type = OPTIONS_TABLE_COLOUR,
.default_num = 8 .default_num = 8,
.style = "window-status-activity-style"
}, },
{ .name = "window-status-bell-attr", { .name = "window-status-activity-style",
.type = OPTIONS_TABLE_ATTRIBUTES, .type = OPTIONS_TABLE_STYLE,
.default_num = GRID_ATTR_REVERSE .default_str = "reverse"
},
{ .name = "window-status-bell-bg",
.type = OPTIONS_TABLE_COLOUR,
.default_num = 8
},
{ .name = "window-status-bell-fg",
.type = OPTIONS_TABLE_COLOUR,
.default_num = 8
},
{ .name = "window-status-content-attr",
.type = OPTIONS_TABLE_ATTRIBUTES,
.default_num = GRID_ATTR_REVERSE
},
{ .name = "window-status-content-bg",
.type = OPTIONS_TABLE_COLOUR,
.default_num = 8
},
{ .name = "window-status-content-fg",
.type = OPTIONS_TABLE_COLOUR,
.default_num = 8
}, },
{ .name = "window-status-attr", { .name = "window-status-attr",
.type = OPTIONS_TABLE_ATTRIBUTES, .type = OPTIONS_TABLE_ATTRIBUTES,
.default_num = 0 .default_num = 0,
.style = "window-status-style"
},
{ .name = "window-status-bell-attr",
.type = OPTIONS_TABLE_ATTRIBUTES,
.default_num = GRID_ATTR_REVERSE,
.style = "window-status-bell-style"
},
{ .name = "window-status-bell-bg",
.type = OPTIONS_TABLE_COLOUR,
.default_num = 8,
.style = "window-status-bell-style"
},
{ .name = "window-status-bell-fg",
.type = OPTIONS_TABLE_COLOUR,
.default_num = 8,
.style = "window-status-bell-style"
},
{ .name = "window-status-bell-style",
.type = OPTIONS_TABLE_STYLE,
.default_str = "reverse"
}, },
{ .name = "window-status-bg", { .name = "window-status-bg",
.type = OPTIONS_TABLE_COLOUR, .type = OPTIONS_TABLE_COLOUR,
.default_num = 8 .default_num = 8,
.style = "window-status-style"
},
{ .name = "window-status-content-attr",
.type = OPTIONS_TABLE_ATTRIBUTES,
.default_num = GRID_ATTR_REVERSE,
.style = "window-status-content-style"
},
{ .name = "window-status-content-bg",
.type = OPTIONS_TABLE_COLOUR,
.default_num = 8,
.style = "window-status-content-style"
},
{ .name = "window-status-content-fg",
.type = OPTIONS_TABLE_COLOUR,
.default_num = 8,
.style = "window-status-content-style"
},
{ .name = "window-status-content-style",
.type = OPTIONS_TABLE_STYLE,
.default_str = "reverse"
}, },
{ .name = "window-status-current-attr", { .name = "window-status-current-attr",
.type = OPTIONS_TABLE_ATTRIBUTES, .type = OPTIONS_TABLE_ATTRIBUTES,
.default_num = 0 .default_num = 0,
.style = "window-status-current-style"
}, },
{ .name = "window-status-current-bg", { .name = "window-status-current-bg",
.type = OPTIONS_TABLE_COLOUR, .type = OPTIONS_TABLE_COLOUR,
.default_num = 8 .default_num = 8,
.style = "window-status-current-style"
}, },
{ .name = "window-status-current-fg", { .name = "window-status-current-fg",
.type = OPTIONS_TABLE_COLOUR, .type = OPTIONS_TABLE_COLOUR,
.default_num = 8 .default_num = 8,
.style = "window-status-current-style"
}, },
{ .name = "window-status-current-format", { .name = "window-status-current-format",
@ -689,24 +780,15 @@ const struct options_table_entry window_options_table[] = {
.default_str = "#I:#W#F" .default_str = "#I:#W#F"
}, },
{ .name = "window-status-last-attr", { .name = "window-status-current-style",
.type = OPTIONS_TABLE_ATTRIBUTES, .type = OPTIONS_TABLE_STYLE,
.default_num = 0 .default_str = "default"
},
{ .name = "window-status-last-bg",
.type = OPTIONS_TABLE_COLOUR,
.default_num = 8
},
{ .name = "window-status-last-fg",
.type = OPTIONS_TABLE_COLOUR,
.default_num = 8
}, },
{ .name = "window-status-fg", { .name = "window-status-fg",
.type = OPTIONS_TABLE_COLOUR, .type = OPTIONS_TABLE_COLOUR,
.default_num = 8 .default_num = 8,
.style = "window-status-style"
}, },
{ .name = "window-status-format", { .name = "window-status-format",
@ -714,11 +796,39 @@ const struct options_table_entry window_options_table[] = {
.default_str = "#I:#W#F" .default_str = "#I:#W#F"
}, },
{ .name = "window-status-last-attr",
.type = OPTIONS_TABLE_ATTRIBUTES,
.default_num = 0,
.style = "window-status-last-style"
},
{ .name = "window-status-last-bg",
.type = OPTIONS_TABLE_COLOUR,
.default_num = 8,
.style = "window-status-last-style"
},
{ .name = "window-status-last-fg",
.type = OPTIONS_TABLE_COLOUR,
.default_num = 8,
.style = "window-status-last-style"
},
{ .name = "window-status-last-style",
.type = OPTIONS_TABLE_STYLE,
.default_str = "default"
},
{ .name = "window-status-separator", { .name = "window-status-separator",
.type = OPTIONS_TABLE_STRING, .type = OPTIONS_TABLE_STRING,
.default_str = " " .default_str = " "
}, },
{ .name = "window-status-style",
.type = OPTIONS_TABLE_STYLE,
.default_str = "default"
},
{ .name = "wrap-search", { .name = "wrap-search",
.type = OPTIONS_TABLE_FLAG, .type = OPTIONS_TABLE_FLAG,
.default_num = 1 .default_num = 1
@ -740,10 +850,17 @@ options_table_populate_tree(
const struct options_table_entry *oe; const struct options_table_entry *oe;
for (oe = table; oe->name != NULL; oe++) { for (oe = table; oe->name != NULL; oe++) {
if (oe->default_str != NULL) switch (oe->type) {
case OPTIONS_TABLE_STRING:
options_set_string(oo, oe->name, "%s", oe->default_str); options_set_string(oo, oe->name, "%s", oe->default_str);
else break;
case OPTIONS_TABLE_STYLE:
options_set_style(oo, oe->name, oe->default_str, 0);
break;
default:
options_set_number(oo, oe->name, oe->default_num); options_set_number(oo, oe->name, oe->default_num);
break;
}
} }
} }
@ -788,6 +905,10 @@ options_table_print_entry(const struct options_table_entry *oe,
s = oe->choices[o->num]; s = oe->choices[o->num];
xsnprintf(out, sizeof out, "%s", s); xsnprintf(out, sizeof out, "%s", s);
break; break;
case OPTIONS_TABLE_STYLE:
s = style_tostring(&o->style);
xsnprintf(out, sizeof out, "%s", s);
break;
} }
return (out); return (out);
} }

View File

@ -26,7 +26,7 @@
/* /*
* Option handling; each option has a name, type and value and is stored in * Option handling; each option has a name, type and value and is stored in
* a splay tree. * a red-black tree.
*/ */
RB_GENERATE(options_tree, options_entry, entry, options_cmp); RB_GENERATE(options_tree, options_entry, entry, options_cmp);
@ -109,6 +109,7 @@ options_set_string(struct options *oo, const char *name, const char *fmt, ...)
o = xmalloc(sizeof *o); o = xmalloc(sizeof *o);
o->name = xstrdup(name); o->name = xstrdup(name);
RB_INSERT(options_tree, &oo->tree, o); RB_INSERT(options_tree, &oo->tree, o);
memcpy(&o->style, &grid_default_cell, sizeof o->style);
} else if (o->type == OPTIONS_STRING) } else if (o->type == OPTIONS_STRING)
free(o->str); free(o->str);
@ -140,6 +141,7 @@ options_set_number(struct options *oo, const char *name, long long value)
o = xmalloc(sizeof *o); o = xmalloc(sizeof *o);
o->name = xstrdup(name); o->name = xstrdup(name);
RB_INSERT(options_tree, &oo->tree, o); RB_INSERT(options_tree, &oo->tree, o);
memcpy(&o->style, &grid_default_cell, sizeof o->style);
} else if (o->type == OPTIONS_STRING) } else if (o->type == OPTIONS_STRING)
free(o->str); free(o->str);
@ -159,3 +161,37 @@ options_get_number(struct options *oo, const char *name)
fatalx("option not a number"); fatalx("option not a number");
return (o->num); return (o->num);
} }
struct options_entry *
options_set_style(struct options *oo, const char *name, const char *value,
int append)
{
struct options_entry *o;
if ((o = options_find1(oo, name)) == NULL) {
o = xmalloc(sizeof *o);
o->name = xstrdup(name);
RB_INSERT(options_tree, &oo->tree, o);
} else if (o->type == OPTIONS_STRING)
free(o->str);
if (!append)
memcpy(&o->style, &grid_default_cell, sizeof o->style);
o->type = OPTIONS_STYLE;
if (style_parse(&grid_default_cell, &o->style, value) == -1)
return (NULL);
return (o);
}
struct grid_cell *
options_get_style(struct options *oo, const char *name)
{
struct options_entry *o;
if ((o = options_find(oo, name)) == NULL)
fatalx("missing option");
if (o->type != OPTIONS_STYLE)
fatalx("option not a style");
return (&o->style);
}

View File

@ -29,6 +29,9 @@ int screen_redraw_check_cell(struct client *, u_int, u_int,
int screen_redraw_check_active(u_int, u_int, int, struct window *, int screen_redraw_check_active(u_int, u_int, int, struct window *,
struct window_pane *); struct window_pane *);
void screen_redraw_draw_borders(struct client *, int, u_int);
void screen_redraw_draw_panes(struct client *, u_int);
void screen_redraw_draw_status(struct client *, u_int);
void screen_redraw_draw_number(struct client *, struct window_pane *); void screen_redraw_draw_number(struct client *, struct window_pane *);
#define CELL_INSIDE 0 #define CELL_INSIDE 0
@ -216,15 +219,13 @@ screen_redraw_check_active(u_int px, u_int py, int type, struct window *w,
/* Redraw entire screen. */ /* Redraw entire screen. */
void void
screen_redraw_screen(struct client *c, int status_only, int borders_only) screen_redraw_screen(struct client *c, int draw_panes, int draw_status,
int draw_borders)
{ {
struct window *w = c->session->curw->window; struct options *oo = &c->session->options;
struct options *oo = &c->session->options; struct tty *tty = &c->tty;
struct tty *tty = &c->tty; u_int top;
struct window_pane *wp; int status, spos;
struct grid_cell active_gc, other_gc;
u_int i, j, type, top;
int status, spos, fg, bg;
/* Suspended clients should not be updated. */ /* Suspended clients should not be updated. */
if (c->flags & CLIENT_SUSPENDED) if (c->flags & CLIENT_SUSPENDED)
@ -239,80 +240,15 @@ screen_redraw_screen(struct client *c, int status_only, int borders_only)
top = 0; top = 0;
if (status && spos == 0) if (status && spos == 0)
top = 1; top = 1;
if (!status)
draw_status = 0;
/* If only drawing status and it is present, don't need the rest. */ if (draw_borders)
if (status_only && status) { screen_redraw_draw_borders(c, status, top);
if (top) if (draw_panes)
tty_draw_line(tty, &c->status, 0, 0, 0); screen_redraw_draw_panes(c, top);
else if (draw_status)
tty_draw_line(tty, &c->status, 0, 0, tty->sy - 1); screen_redraw_draw_status(c, top);
tty_reset(tty);
return;
}
/* Set up pane border attributes. */
memcpy(&other_gc, &grid_marker_cell, sizeof other_gc);
memcpy(&active_gc, &grid_marker_cell, sizeof active_gc);
active_gc.attr = other_gc.attr = GRID_ATTR_CHARSET;
fg = options_get_number(oo, "pane-border-fg");
colour_set_fg(&other_gc, fg);
bg = options_get_number(oo, "pane-border-bg");
colour_set_bg(&other_gc, bg);
fg = options_get_number(oo, "pane-active-border-fg");
colour_set_fg(&active_gc, fg);
bg = options_get_number(oo, "pane-active-border-bg");
colour_set_bg(&active_gc, bg);
/* Draw background and borders. */
for (j = 0; j < tty->sy - status; j++) {
if (status_only) {
if (spos == 1 && j != tty->sy - 1)
continue;
else if (spos == 0 && j != 0)
break;
}
for (i = 0; i < tty->sx; i++) {
type = screen_redraw_check_cell(c, i, j, &wp);
if (type == CELL_INSIDE)
continue;
if (screen_redraw_check_active(i, j, type, w, wp))
tty_attributes(tty, &active_gc);
else
tty_attributes(tty, &other_gc);
tty_cursor(tty, i, top + j);
tty_putc(tty, CELL_BORDERS[type]);
}
}
/* If only drawing borders, that's it. */
if (borders_only)
return;
/* Draw the panes, if necessary. */
TAILQ_FOREACH(wp, &w->panes, entry) {
if (!window_pane_visible(wp))
continue;
for (i = 0; i < wp->sy; i++) {
if (status_only) {
if (spos == 1 && wp->yoff + i != tty->sy - 1)
continue;
else if (spos == 0 && wp->yoff + i != 0)
break;
}
tty_draw_line(
tty, wp->screen, i, wp->xoff, top + wp->yoff);
}
if (c->flags & CLIENT_IDENTIFY)
screen_redraw_draw_number(c, wp);
}
/* Draw the status line. */
if (status) {
if (top)
tty_draw_line(tty, &c->status, 0, 0, 0);
else
tty_draw_line(tty, &c->status, 0, 0, tty->sy - 1);
}
tty_reset(tty); tty_reset(tty);
} }
@ -334,6 +270,69 @@ screen_redraw_pane(struct client *c, struct window_pane *wp)
tty_reset(&c->tty); tty_reset(&c->tty);
} }
/* Draw the borders. */
void
screen_redraw_draw_borders(struct client *c, int status, u_int top)
{
struct window *w = c->session->curw->window;
struct options *oo = &c->session->options;
struct tty *tty = &c->tty;
struct window_pane *wp;
struct grid_cell active_gc, other_gc;
u_int i, j, type;
style_apply(&other_gc, oo, "pane-border-style");
style_apply(&active_gc, oo, "pane-active-border-style");
active_gc.attr = other_gc.attr = GRID_ATTR_CHARSET;
for (j = 0; j < tty->sy - status; j++) {
for (i = 0; i < tty->sx; i++) {
type = screen_redraw_check_cell(c, i, j, &wp);
if (type == CELL_INSIDE)
continue;
if (screen_redraw_check_active(i, j, type, w, wp))
tty_attributes(tty, &active_gc);
else
tty_attributes(tty, &other_gc);
tty_cursor(tty, i, top + j);
tty_putc(tty, CELL_BORDERS[type]);
}
}
}
/* Draw the panes. */
void
screen_redraw_draw_panes(struct client *c, u_int top)
{
struct window *w = c->session->curw->window;
struct tty *tty = &c->tty;
struct window_pane *wp;
struct screen *s;
u_int i;
TAILQ_FOREACH(wp, &w->panes, entry) {
if (!window_pane_visible(wp))
continue;
s = wp->screen;
for (i = 0; i < wp->sy; i++)
tty_draw_line(tty, s, i, wp->xoff, top + wp->yoff);
if (c->flags & CLIENT_IDENTIFY)
screen_redraw_draw_number(c, wp);
}
}
/* Draw the status line. */
void
screen_redraw_draw_status(struct client *c, u_int top)
{
struct tty *tty = &c->tty;
if (top)
tty_draw_line(tty, &c->status, 0, 0, 0);
else
tty_draw_line(tty, &c->status, 0, 0, tty->sy - 1);
}
/* Draw number on a pane. */ /* Draw number on a pane. */
void void
screen_redraw_draw_number(struct client *c, struct window_pane *wp) screen_redraw_draw_number(struct client *c, struct window_pane *wp)
@ -368,7 +367,7 @@ screen_redraw_draw_number(struct client *c, struct window_pane *wp)
px -= len * 3; px -= len * 3;
py -= 2; py -= 2;
memcpy(&gc, &grid_marker_cell, sizeof gc); memcpy(&gc, &grid_default_cell, sizeof gc);
if (w->active == wp) if (w->active == wp)
colour_set_bg(&gc, active_colour); colour_set_bg(&gc, active_colour);
else else
@ -395,7 +394,7 @@ screen_redraw_draw_number(struct client *c, struct window_pane *wp)
tty_cursor(tty, xoff + wp->sx - len, yoff); tty_cursor(tty, xoff + wp->sx - len, yoff);
draw_text: draw_text:
memcpy(&gc, &grid_marker_cell, sizeof gc); memcpy(&gc, &grid_default_cell, sizeof gc);
if (w->active == wp) if (w->active == wp)
colour_set_fg(&gc, active_colour); colour_set_fg(&gc, active_colour);
else else

View File

@ -248,7 +248,7 @@ screen_write_cnputs(struct screen_write_ctx *ctx,
} }
*last = '\0'; *last = '\0';
screen_write_parsestyle(gc, &lgc, ptr); style_parse(gc, &lgc, ptr);
ptr = last + 1; ptr = last + 1;
continue; continue;
} }
@ -288,89 +288,6 @@ screen_write_cnputs(struct screen_write_ctx *ctx,
free(msg); free(msg);
} }
/* Parse an embedded style of the form "fg=colour,bg=colour,bright,...". */
void
screen_write_parsestyle(
struct grid_cell *defgc, struct grid_cell *gc, const char *in)
{
const char delimiters[] = " ,";
char tmp[32];
int val;
size_t end;
u_char fg, bg, attr, flags;
if (*in == '\0')
return;
if (strchr(delimiters, in[strlen(in) - 1]) != NULL)
return;
fg = gc->fg;
bg = gc->bg;
attr = gc->attr;
flags = gc->flags;
do {
end = strcspn(in, delimiters);
if (end > (sizeof tmp) - 1)
return;
memcpy(tmp, in, end);
tmp[end] = '\0';
if (strcasecmp(tmp, "default") == 0) {
fg = defgc->fg;
bg = defgc->bg;
attr = defgc->attr;
flags &= ~(GRID_FLAG_FG256|GRID_FLAG_BG256);
flags |=
defgc->flags & (GRID_FLAG_FG256|GRID_FLAG_BG256);
} else if (end > 3 && strncasecmp(tmp + 1, "g=", 2) == 0) {
if ((val = colour_fromstring(tmp + 3)) == -1)
return;
if (*in == 'f' || *in == 'F') {
if (val != 8) {
if (val & 0x100) {
flags |= GRID_FLAG_FG256;
val &= ~0x100;
} else
flags &= ~GRID_FLAG_FG256;
fg = val;
} else {
fg = defgc->fg;
flags &= ~GRID_FLAG_FG256;
flags |= defgc->flags & GRID_FLAG_FG256;
}
} else if (*in == 'b' || *in == 'B') {
if (val != 8) {
if (val & 0x100) {
flags |= GRID_FLAG_BG256;
val &= ~0x100;
} else
flags &= ~GRID_FLAG_BG256;
bg = val;
} else {
bg = defgc->bg;
flags &= ~GRID_FLAG_BG256;
flags |= defgc->flags & GRID_FLAG_BG256;
}
} else
return;
} else if (end > 2 && strncasecmp(tmp, "no", 2) == 0) {
if ((val = attributes_fromstring(tmp + 2)) == -1)
return;
attr &= ~val;
} else {
if ((val = attributes_fromstring(tmp)) == -1)
return;
attr |= val;
}
in += end + strspn(in + end, delimiters);
} while (*in != '\0');
gc->fg = fg;
gc->bg = bg;
gc->attr = attr;
gc->flags = flags;
}
/* Copy from another screen. */ /* Copy from another screen. */
void void
screen_write_copy(struct screen_write_ctx *ctx, screen_write_copy(struct screen_write_ctx *ctx,

View File

@ -111,12 +111,8 @@ screen_set_cursor_colour(struct screen *s, const char *colour_string)
void void
screen_set_title(struct screen *s, const char *title) screen_set_title(struct screen *s, const char *title)
{ {
char tmp[BUFSIZ];
strlcpy(tmp, title, sizeof tmp);
free(s->title); free(s->title);
s->title = xstrdup(tmp); s->title = xstrdup(title);
} }
/* Resize screen. */ /* Resize screen. */

View File

@ -742,7 +742,7 @@ server_client_check_redraw(struct client *c)
} }
if (c->flags & CLIENT_REDRAW) { if (c->flags & CLIENT_REDRAW) {
screen_redraw_screen(c, 0, 0); screen_redraw_screen(c, 1, 1, 1);
c->flags &= ~(CLIENT_STATUS|CLIENT_BORDERS); c->flags &= ~(CLIENT_STATUS|CLIENT_BORDERS);
} else if (c->flags & CLIENT_REDRAWWINDOW) { } else if (c->flags & CLIENT_REDRAWWINDOW) {
TAILQ_FOREACH(wp, &c->session->curw->window->panes, entry) TAILQ_FOREACH(wp, &c->session->curw->window->panes, entry)
@ -756,10 +756,10 @@ server_client_check_redraw(struct client *c)
} }
if (c->flags & CLIENT_BORDERS) if (c->flags & CLIENT_BORDERS)
screen_redraw_screen(c, 0, 1); screen_redraw_screen(c, 0, 0, 1);
if (c->flags & CLIENT_STATUS) if (c->flags & CLIENT_STATUS)
screen_redraw_screen(c, 1, 0); screen_redraw_screen(c, 0, 1, 0);
c->tty.flags |= flags; c->tty.flags |= flags;

View File

@ -174,11 +174,11 @@ session_destroy(struct session *s)
RB_INSERT(sessions, &dead_sessions, s); RB_INSERT(sessions, &dead_sessions, s);
} }
/* Check a session name is valid: not empty and no colons. */ /* Check a session name is valid: not empty and no colons or periods. */
int int
session_check_name(const char *name) session_check_name(const char *name)
{ {
return (*name != '\0' && strchr(name, ':') == NULL); return (*name != '\0' && name[strcspn(name, ":.")] == '\0');
} }
/* Update session active time. */ /* Update session active time. */

118
status.c
View File

@ -80,18 +80,9 @@ status_redraw_get_left(struct client *c,
{ {
struct session *s = c->session; struct session *s = c->session;
char *left; char *left;
int fg, bg, attr;
size_t leftlen; size_t leftlen;
fg = options_get_number(&s->options, "status-left-fg"); style_apply_update(gc, &s->options, "status-left-style");
if (fg != 8)
colour_set_fg(gc, fg);
bg = options_get_number(&s->options, "status-left-bg");
if (bg != 8)
colour_set_bg(gc, bg);
attr = options_get_number(&s->options, "status-left-attr");
if (attr != 0)
gc->attr = attr;
left = status_replace(c, NULL, left = status_replace(c, NULL,
NULL, NULL, options_get_string(&s->options, "status-left"), t, 1); NULL, NULL, options_get_string(&s->options, "status-left"), t, 1);
@ -110,18 +101,9 @@ status_redraw_get_right(struct client *c,
{ {
struct session *s = c->session; struct session *s = c->session;
char *right; char *right;
int fg, bg, attr;
size_t rightlen; size_t rightlen;
fg = options_get_number(&s->options, "status-right-fg"); style_apply_update(gc, &s->options, "status-right-style");
if (fg != 8)
colour_set_fg(gc, fg);
bg = options_get_number(&s->options, "status-right-bg");
if (bg != 8)
colour_set_bg(gc, bg);
attr = options_get_number(&s->options, "status-right-attr");
if (attr != 0)
gc->attr = attr;
right = status_replace(c, NULL, right = status_replace(c, NULL,
NULL, NULL, options_get_string(&s->options, "status-right"), t, 1); NULL, NULL, options_get_string(&s->options, "status-right"), t, 1);
@ -177,10 +159,7 @@ status_redraw(struct client *c)
t = c->status_timer.tv_sec; t = c->status_timer.tv_sec;
/* Set up default colour. */ /* Set up default colour. */
memcpy(&stdgc, &grid_default_cell, sizeof gc); style_apply(&stdgc, &s->options, "status-style");
colour_set_fg(&stdgc, options_get_number(&s->options, "status-fg"));
colour_set_bg(&stdgc, options_get_number(&s->options, "status-bg"));
stdgc.attr |= options_get_number(&s->options, "status-attr");
/* Create the target screen. */ /* Create the target screen. */
memcpy(&old_status, &c->status, sizeof old_status); memcpy(&old_status, &c->status, sizeof old_status);
@ -646,73 +625,22 @@ status_print(
struct session *s = c->session; struct session *s = c->session;
const char *fmt; const char *fmt;
char *text; char *text;
int fg, bg, attr;
fg = options_get_number(oo, "window-status-fg"); style_apply_update(gc, oo, "window-status-style");
if (fg != 8)
colour_set_fg(gc, fg);
bg = options_get_number(oo, "window-status-bg");
if (bg != 8)
colour_set_bg(gc, bg);
attr = options_get_number(oo, "window-status-attr");
if (attr != 0)
gc->attr = attr;
fmt = options_get_string(oo, "window-status-format"); fmt = options_get_string(oo, "window-status-format");
if (wl == s->curw) { if (wl == s->curw) {
fg = options_get_number(oo, "window-status-current-fg"); style_apply_update(gc, oo, "window-status-current-style");
if (fg != 8)
colour_set_fg(gc, fg);
bg = options_get_number(oo, "window-status-current-bg");
if (bg != 8)
colour_set_bg(gc, bg);
attr = options_get_number(oo, "window-status-current-attr");
if (attr != 0)
gc->attr = attr;
fmt = options_get_string(oo, "window-status-current-format"); fmt = options_get_string(oo, "window-status-current-format");
} }
if (wl == TAILQ_FIRST(&s->lastw)) { if (wl == TAILQ_FIRST(&s->lastw))
fg = options_get_number(oo, "window-status-last-fg"); style_apply_update(gc, oo, "window-status-last-style");
if (fg != 8)
colour_set_fg(gc, fg);
bg = options_get_number(oo, "window-status-last-bg");
if (bg != 8)
colour_set_bg(gc, bg);
attr = options_get_number(oo, "window-status-last-attr");
if (attr != 0)
gc->attr = attr;
}
if (wl->flags & WINLINK_BELL) { if (wl->flags & WINLINK_BELL)
fg = options_get_number(oo, "window-status-bell-fg"); style_apply_update(gc, oo, "window-status-bell-style");
if (fg != 8) else if (wl->flags & WINLINK_CONTENT)
colour_set_fg(gc, fg); style_apply_update(gc, oo, "window-status-content-style");
bg = options_get_number(oo, "window-status-bell-bg"); else if (wl->flags & (WINLINK_ACTIVITY|WINLINK_SILENCE))
if (bg != 8) style_apply_update(gc, oo, "window-status-activity-style");
colour_set_bg(gc, bg);
attr = options_get_number(oo, "window-status-bell-attr");
if (attr != 0)
gc->attr = attr;
} else if (wl->flags & WINLINK_CONTENT) {
fg = options_get_number(oo, "window-status-content-fg");
if (fg != 8)
colour_set_fg(gc, fg);
bg = options_get_number(oo, "window-status-content-bg");
if (bg != 8)
colour_set_bg(gc, bg);
attr = options_get_number(oo, "window-status-content-attr");
if (attr != 0)
gc->attr = attr;
} else if (wl->flags & (WINLINK_ACTIVITY|WINLINK_SILENCE)) {
fg = options_get_number(oo, "window-status-activity-fg");
if (fg != 8)
colour_set_fg(gc, fg);
bg = options_get_number(oo, "window-status-activity-bg");
if (bg != 8)
colour_set_bg(gc, bg);
attr = options_get_number(oo, "window-status-activity-attr");
if (attr != 0)
gc->attr = attr;
}
text = status_replace(c, NULL, wl, NULL, fmt, t, 1); text = status_replace(c, NULL, wl, NULL, fmt, t, 1);
return (text); return (text);
@ -814,10 +742,7 @@ status_message_redraw(struct client *c)
if (len > c->tty.sx) if (len > c->tty.sx)
len = c->tty.sx; len = c->tty.sx;
memcpy(&gc, &grid_default_cell, sizeof gc); style_apply(&gc, &s->options, "message-style");
colour_set_fg(&gc, options_get_number(&s->options, "message-fg"));
colour_set_bg(&gc, options_get_number(&s->options, "message-bg"));
gc.attr |= options_get_number(&s->options, "message-attr");
screen_write_start(&ctx, NULL, &c->status); screen_write_start(&ctx, NULL, &c->status);
@ -935,18 +860,11 @@ status_prompt_redraw(struct client *c)
len = c->tty.sx; len = c->tty.sx;
off = 0; off = 0;
memcpy(&gc, &grid_default_cell, sizeof gc);
/* Change colours for command mode. */ /* Change colours for command mode. */
if (c->prompt_mdata.mode == 1) { if (c->prompt_mdata.mode == 1)
colour_set_fg(&gc, options_get_number(&s->options, "message-command-fg")); style_apply(&gc, &s->options, "message-command-style");
colour_set_bg(&gc, options_get_number(&s->options, "message-command-bg")); else
gc.attr |= options_get_number(&s->options, "message-command-attr"); style_apply(&gc, &s->options, "message-style");
} else {
colour_set_fg(&gc, options_get_number(&s->options, "message-fg"));
colour_set_bg(&gc, options_get_number(&s->options, "message-bg"));
gc.attr |= options_get_number(&s->options, "message-attr");
}
screen_write_start(&ctx, NULL, &c->status); screen_write_start(&ctx, NULL, &c->status);

224
style.c Normal file
View File

@ -0,0 +1,224 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
* Copyright (c) 2014 Tiago Cunha <tcunha@users.sourceforge.net>
*
* 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 <string.h>
#include "tmux.h"
/* Parse an embedded style of the form "fg=colour,bg=colour,bright,...". */
int
style_parse(const struct grid_cell *defgc, struct grid_cell *gc,
const char *in)
{
const char delimiters[] = " ,";
char tmp[32];
int val;
size_t end;
u_char fg, bg, attr, flags;
if (*in == '\0')
return (0);
if (strchr(delimiters, in[strlen(in) - 1]) != NULL)
return (-1);
fg = gc->fg;
bg = gc->bg;
attr = gc->attr;
flags = gc->flags;
do {
end = strcspn(in, delimiters);
if (end > (sizeof tmp) - 1)
return (-1);
memcpy(tmp, in, end);
tmp[end] = '\0';
if (strcasecmp(tmp, "default") == 0) {
fg = defgc->fg;
bg = defgc->bg;
attr = defgc->attr;
flags &= ~(GRID_FLAG_FG256|GRID_FLAG_BG256);
flags |=
defgc->flags & (GRID_FLAG_FG256|GRID_FLAG_BG256);
} else if (end > 3 && strncasecmp(tmp + 1, "g=", 2) == 0) {
if ((val = colour_fromstring(tmp + 3)) == -1)
return (-1);
if (*in == 'f' || *in == 'F') {
if (val != 8) {
if (val & 0x100) {
flags |= GRID_FLAG_FG256;
val &= ~0x100;
} else
flags &= ~GRID_FLAG_FG256;
fg = val;
} else {
fg = defgc->fg;
flags &= ~GRID_FLAG_FG256;
flags |= defgc->flags & GRID_FLAG_FG256;
}
} else if (*in == 'b' || *in == 'B') {
if (val != 8) {
if (val & 0x100) {
flags |= GRID_FLAG_BG256;
val &= ~0x100;
} else
flags &= ~GRID_FLAG_BG256;
bg = val;
} else {
bg = defgc->bg;
flags &= ~GRID_FLAG_BG256;
flags |= defgc->flags & GRID_FLAG_BG256;
}
} else
return (-1);
} else if (strcasecmp(tmp, "none") == 0)
attr = 0;
else if (end > 2 && strncasecmp(tmp, "no", 2) == 0) {
if ((val = attributes_fromstring(tmp + 2)) == -1)
return (-1);
attr &= ~val;
} else {
if ((val = attributes_fromstring(tmp)) == -1)
return (-1);
attr |= val;
}
in += end + strspn(in + end, delimiters);
} while (*in != '\0');
gc->fg = fg;
gc->bg = bg;
gc->attr = attr;
gc->flags = flags;
return (0);
}
/* Convert style to a string. */
const char *
style_tostring(struct grid_cell *gc)
{
int c, off = 0, comma = 0;
static char s[256];
*s = '\0';
if (gc->fg != 8) {
if (gc->flags & GRID_FLAG_FG256)
c = gc->fg | 0x100;
else
c = gc->fg;
off += xsnprintf(s, sizeof s, "fg=%s", colour_tostring(c));
comma = 1;
}
if (gc->bg != 8) {
if (gc->flags & GRID_FLAG_BG256)
c = gc->bg | 0x100;
else
c = gc->bg;
off += xsnprintf(s + off, sizeof s - off, "%sbg=%s",
comma ? "," : "", colour_tostring(c));
comma = 1;
}
if (gc->attr != 0 && gc->attr != GRID_ATTR_CHARSET) {
xsnprintf(s + off, sizeof s - off, "%s%s",
comma ? "," : "", attributes_tostring(gc->attr));
}
if (*s == '\0')
return ("default");
return (s);
}
/* Synchronize new -style option with the old one. */
void
style_update_new(struct options *oo, const char *name, const char *newname)
{
int value;
struct grid_cell *gc;
/* It's a colour or attribute, but with no -style equivalent. */
if (newname == NULL)
return;
gc = options_get_style(oo, newname);
value = options_get_number(oo, name);
if (strstr(name, "-bg") != NULL)
colour_set_bg(gc, value);
else if (strstr(name, "-fg") != NULL)
colour_set_fg(gc, value);
else if (strstr(name, "-attr") != NULL)
gc->attr = value;
}
/* Synchronize all the old options with the new -style one. */
void
style_update_old(struct options *oo, const char *name, struct grid_cell *gc)
{
char newname[128];
int c, size;
size = strrchr(name, '-') - name;
if (gc->flags & GRID_FLAG_BG256)
c = gc->bg | 0x100;
else
c = gc->bg;
xsnprintf(newname, sizeof newname, "%.*s-bg", size, name);
options_set_number(oo, newname, c);
if (gc->flags & GRID_FLAG_FG256)
c = gc->fg | 0x100;
else
c = gc->fg;
xsnprintf(newname, sizeof newname, "%.*s-fg", size, name);
options_set_number(oo, newname, c);
xsnprintf(newname, sizeof newname, "%.*s-attr", size, name);
options_set_number(oo, newname, gc->attr);
}
/* Apply a style. */
void
style_apply(struct grid_cell *gc, struct options *oo, const char *name)
{
struct grid_cell *gcp;
memcpy(gc, &grid_default_cell, sizeof *gc);
gcp = options_get_style(oo, name);
colour_set_fg(gc, gcp->fg);
colour_set_bg(gc, gcp->bg);
gc->attr |= gcp->attr;
}
/* Apply a style, updating if default. */
void
style_apply_update(struct grid_cell *gc, struct options *oo, const char *name)
{
struct grid_cell *gcp;
gcp = options_get_style(oo, name);
if (gcp->fg != 8)
colour_set_fg(gc, gcp->fg);
if (gcp->bg != 8)
colour_set_bg(gc, gcp->bg);
if (gcp->attr != 0)
gc->attr |= gcp->attr;
}

327
tmux.1
View File

@ -774,15 +774,24 @@ is specified, only update the client's status bar.
Rename the session to Rename the session to
.Ar new-name . .Ar new-name .
.It Xo Ic show-messages .It Xo Ic show-messages
.Op Fl IJT
.Op Fl t Ar target-client .Op Fl t Ar target-client
.Xc .Xc
.D1 (alias: Ic showmsgs ) .D1 (alias: Ic showmsgs )
Show client messages or server information.
Any messages displayed on the status line are saved in a per-client message Any messages displayed on the status line are saved in a per-client message
log, up to a maximum of the limit set by the log, up to a maximum of the limit set by the
.Ar message-limit .Ar message-limit
session option for the session attached to that client. session option for the session attached to that client.
This command displays the log for With
.Fl t ,
display the log for
.Ar target-client . .Ar target-client .
.Fl I,
.Fl J
and
.Fl T
show debugging information about the running server, jobs and terminals.
.It Ic source-file Ar path .It Ic source-file Ar path
.D1 (alias: Ic source ) .D1 (alias: Ic source )
Execute commands from Execute commands from
@ -2055,11 +2064,6 @@ otherwise a session option.
If If
.Fl g .Fl g
is specified, the global session or window option is set. is specified, the global session or window option is set.
With
.Fl a ,
and if the option expects a string,
.Ar value
is appended to the existing setting.
The The
.Fl u .Fl u
flag unsets an option, so a session inherits the option from the global flag unsets an option, so a session inherits the option from the global
@ -2076,6 +2080,32 @@ flag suppresses the informational message (as if the
.Ic quiet .Ic quiet
server option was set). server option was set).
.Pp .Pp
With
.Fl a ,
and if the option expects a string or a style,
.Ar value
is appended to the existing setting.
For example:
.Bd -literal -offset indent
set -g status-left "foo"
set -ag status-left "bar"
.Ed
.Pp
Will result in
.Ql foobar .
And:
.Bd -literal -offset indent
set -g status-style "bg=red"
set -ag status-style "fg=blue"
.Ed
.Pp
Will result in a red background
.Em and
blue foreground.
Without
.Fl a ,
the result would be the default background and a blue foreground.
.Pp
Available window options are listed under Available window options are listed under
.Ic set-window-option . .Ic set-window-option .
.Pp .Pp
@ -2267,26 +2297,18 @@ the entire server will lock after
.Em all .Em all
sessions would have locked. sessions would have locked.
This has no effect as a session option; it must be set as a global option. This has no effect as a session option; it must be set as a global option.
.It Ic message-attr Ar attributes .It Ic message-command-style Ar style
Set status line message attributes, where Set status line message command style, where
.Ar attributes .Ar style
is either is a comma-separated list of characteristics to be specified.
.Ic none .Pp
or a comma-delimited list of one or more of: These may be
.Ic bright .Ql bg=colour
(or to set the background colour,
.Ic bold ) , .Ql fg=colour
.Ic dim , to set the foreground colour, and a list of attributes as specified below.
.Ic underscore , .Pp
.Ic blink , The colour is one of:
.Ic reverse ,
.Ic hidden ,
or
.Ic italics .
.It Ic message-bg Ar colour
Set status line message background colour, where
.Ar colour
is one of:
.Ic black , .Ic black ,
.Ic red , .Ic red ,
.Ic green , .Ic green ,
@ -2307,18 +2329,46 @@ from the 256-colour set,
or a hexadecimal RGB string such as or a hexadecimal RGB string such as
.Ql #ffffff , .Ql #ffffff ,
which chooses the closest match from the default 256-colour set. which chooses the closest match from the default 256-colour set.
.It Ic message-command-attr Ar attributes .Pp
Set status line message attributes when in command mode. The attributes is either
.It Ic message-command-bg Ar colour .Ic none
Set status line message background colour when in command mode. or a comma-delimited list of one or more of:
.It Ic message-command-fg Ar colour .Ic bright
Set status line message foreground colour when in command mode. (or
.It Ic message-fg Ar colour .Ic bold ) ,
Set status line message foreground colour. .Ic dim ,
.Ic underscore ,
.Ic blink ,
.Ic reverse ,
.Ic hidden ,
or
.Ic italics ,
to turn an attribute on, or an attribute prefixed with
.Ql no
to turn one off.
.Pp
Examples are:
.Bd -literal -offset indent
fg=yellow,bold,underscore,blink
bg=black,fg=default,noreverse
.Ed
.Pp
With the
.Fl a
flag to the
.Ic set-option
command the new style is added otherwise the existing style is replaced.
.It Ic message-limit Ar number .It Ic message-limit Ar number
Set the number of error or information messages to save in the message log for Set the number of error or information messages to save in the message log for
each client. each client.
The default is 20. The default is 20.
.It Ic message-style Ar style
Set status line message style.
For how to specify
.Ar style ,
see the
.Ic message-command-style
option.
.It Xo Ic mouse-resize-pane .It Xo Ic mouse-resize-pane
.Op Ic on | off .Op Ic on | off
.Xc .Xc
@ -2342,12 +2392,22 @@ window.
.Op Ic on | off .Op Ic on | off
.Xc .Xc
If enabled, request mouse input as UTF-8 on UTF-8 terminals. If enabled, request mouse input as UTF-8 on UTF-8 terminals.
.It Ic pane-active-border-bg Ar colour .It Ic pane-active-border-style Ar style
.It Ic pane-active-border-fg Ar colour Set the pane border style for the currently active pane.
Set the pane border colour for the currently active pane. For how to specify
.It Ic pane-border-bg Ar colour .Ar style ,
.It Ic pane-border-fg Ar colour see the
Set the pane border colour for panes aside from the active pane. .Ic message-command-style
option.
Attributes are ignored.
.It Ic pane-border-style Ar style
Set the pane border style for paneas aside from the active pane.
For how to specify
.Ar style ,
see the
.Ic message-command-style
option.
Attributes are ignored.
.It Ic prefix Ar key .It Ic prefix Ar key
Set the key accepted as a prefix key. Set the key accepted as a prefix key.
.It Ic prefix2 Ar key .It Ic prefix2 Ar key
@ -2413,12 +2473,6 @@ option.
.Op Ic on | off .Op Ic on | off
.Xc .Xc
Show or hide the status line. Show or hide the status line.
.It Ic status-attr Ar attributes
Set status line attributes.
.It Ic status-bg Ar colour
Set status line background colour.
.It Ic status-fg Ar colour
Set status line foreground colour.
.It Ic status-interval Ar interval .It Ic status-interval Ar interval
Update the status bar every Update the status bar every
.Ar interval .Ar interval
@ -2476,19 +2530,10 @@ section).
For details on how the names and titles can be set see the For details on how the names and titles can be set see the
.Sx "NAMES AND TITLES" .Sx "NAMES AND TITLES"
section. section.
For a list of allowed attributes see the
.Ic message-command-style
option.
.Pp .Pp
#[attributes] allows a comma-separated list of attributes to be specified,
these may be
.Ql fg=colour
to set the foreground colour,
.Ql bg=colour
to set the background colour, the name of one of the attributes (listed under
the
.Ic message-attr
option) to turn an attribute on, or an attribute prefixed with
.Ql no
to turn one off, for example
.Ic nobright .
Examples are: Examples are:
.Bd -literal -offset indent .Bd -literal -offset indent
#(sysctl vm.loadavg) #(sysctl vm.loadavg)
@ -2504,17 +2549,18 @@ By default, UTF-8 in
is not interpreted, to enable UTF-8, use the is not interpreted, to enable UTF-8, use the
.Ic status-utf8 .Ic status-utf8
option. option.
.It Ic status-left-attr Ar attributes
Set the attribute of the left part of the status line.
.It Ic status-left-bg Ar colour
Set the background colour of the left part of the status line.
.It Ic status-left-fg Ar colour
Set the foreground colour of the left part of the status line.
.It Ic status-left-length Ar length .It Ic status-left-length Ar length
Set the maximum Set the maximum
.Ar length .Ar length
of the left component of the status bar. of the left component of the status bar.
The default is 10. The default is 10.
.It Ic status-left-style Ar style
Set the style of the left part of the status line.
For how to specify
.Ar style ,
see the
.Ic message-command-style
option.
.It Xo Ic status-position .It Xo Ic status-position
.Op Ic top | bottom .Op Ic top | bottom
.Xc .Xc
@ -2533,17 +2579,25 @@ will be passed to
character pairs are replaced, and UTF-8 is dependent on the character pairs are replaced, and UTF-8 is dependent on the
.Ic status-utf8 .Ic status-utf8
option. option.
.It Ic status-right-attr Ar attributes
Set the attribute of the right part of the status line.
.It Ic status-right-bg Ar colour
Set the background colour of the right part of the status line.
.It Ic status-right-fg Ar colour
Set the foreground colour of the right part of the status line.
.It Ic status-right-length Ar length .It Ic status-right-length Ar length
Set the maximum Set the maximum
.Ar length .Ar length
of the right component of the status bar. of the right component of the status bar.
The default is 40. The default is 40.
.It Ic status-right-style Ar style
Set the style of the right part of the status line.
For how to specify
.Ar style ,
see the
.Ic message-command-style
option.
.It Ic status-style Ar style
Set status line style.
For how to specify
.Ar style ,
see the
.Ic message-command-style
option.
.It Xo Ic status-utf8 .It Xo Ic status-utf8
.Op Ic on | off .Op Ic on | off
.Xc .Xc
@ -2770,15 +2824,6 @@ or
.Ic main-vertical .Ic main-vertical
layouts. layouts.
.Pp .Pp
.It Ic mode-attr Ar attributes
Set window modes attributes.
.Pp
.It Ic mode-bg Ar colour
Set window modes background colour.
.Pp
.It Ic mode-fg Ar colour
Set window modes foreground colour.
.Pp
.It Xo Ic mode-keys .It Xo Ic mode-keys
.Op Ic vi | emacs .Op Ic vi | emacs
.Xc .Xc
@ -2804,6 +2849,14 @@ If set to
the mouse behaves as set to on, but cannot be used to enter copy the mouse behaves as set to on, but cannot be used to enter copy
mode. mode.
.Pp .Pp
.It Ic mode-style Ar style
Set window modes style.
For how to specify
.Ar style ,
see the
.Ic message-command-style
option.
.Pp
.It Xo Ic monitor-activity .It Xo Ic monitor-activity
.Op Ic on | off .Op Ic on | off
.Xc .Xc
@ -2874,64 +2927,42 @@ Instructs
.Nm .Nm
to expect UTF-8 sequences to appear in this window. to expect UTF-8 sequences to appear in this window.
.Pp .Pp
.It Ic window-status-bell-attr Ar attributes .It Ic window-status-activity-style Ar style
Set status line attributes for windows which have a bell alert. Set status line style for windows with an activity alert.
For how to specify
.Ar style ,
see the
.Ic message-command-style
option.
.Pp .Pp
.It Ic window-status-bell-bg Ar colour .It Ic window-status-bell-style Ar style
Set status line background colour for windows with a bell alert. Set status line style for windows with a bell alert.
For how to specify
.Ar style ,
see the
.Ic message-command-style
option.
.Pp .Pp
.It Ic window-status-bell-fg Ar colour .It Ic window-status-content-style Ar style
Set status line foreground colour for windows with a bell alert. Set status line style for windows with a content alert.
.Pp For how to specify
.It Ic window-status-content-attr Ar attributes .Ar style ,
Set status line attributes for windows which have a content alert. see the
.Pp .Ic message-command-style
.It Ic window-status-content-bg Ar colour option.
Set status line background colour for windows with a content alert.
.Pp
.It Ic window-status-content-fg Ar colour
Set status line foreground colour for windows with a content alert.
.Pp
.It Ic window-status-activity-attr Ar attributes
Set status line attributes for windows which have an activity (or silence) alert.
.Pp
.It Ic window-status-activity-bg Ar colour
Set status line background colour for windows with an activity alert.
.Pp
.It Ic window-status-activity-fg Ar colour
Set status line foreground colour for windows with an activity alert.
.Pp
.It Ic window-status-attr Ar attributes
Set status line attributes for a single window.
.Pp
.It Ic window-status-bg Ar colour
Set status line background colour for a single window.
.Pp
.It Ic window-status-current-attr Ar attributes
Set status line attributes for the currently active window.
.Pp
.It Ic window-status-current-bg Ar colour
Set status line background colour for the currently active window.
.Pp
.It Ic window-status-current-fg Ar colour
Set status line foreground colour for the currently active window.
.Pp .Pp
.It Ic window-status-current-format Ar string .It Ic window-status-current-format Ar string
Like Like
.Ar window-status-format , .Ar window-status-format ,
but is the format used when the window is the current window. but is the format used when the window is the current window.
.Pp .Pp
.It Ic window-status-last-attr Ar attributes .It Ic window-status-current-style Ar style
Set status line attributes for the last active window. Set status line style for the currently active window.
.Pp For how to specify
.It Ic window-status-last-bg Ar colour .Ar style ,
Set status line background colour for the last active window. see the
.Pp .Ic message-command-style
.It Ic window-status-last-fg Ar colour option.
Set status line foreground colour for the last active window.
.Pp
.It Ic window-status-fg Ar colour
Set status line foreground colour for a single window.
.Pp .Pp
.It Ic window-status-format Ar string .It Ic window-status-format Ar string
Set the format in which the window is displayed in the status line window list. Set the format in which the window is displayed in the status line window list.
@ -2941,10 +2972,26 @@ option for details of special character sequences available.
The default is The default is
.Ql #I:#W#F . .Ql #I:#W#F .
.Pp .Pp
.It Ic window-status-last-style Ar style
Set status line style for the last active window.
For how to specify
.Ar style ,
see the
.Ic message-command-style
option.
.Pp
.It Ic window-status-separator Ar string .It Ic window-status-separator Ar string
Sets the separator drawn between windows in the status line. Sets the separator drawn between windows in the status line.
The default is a single space character. The default is a single space character.
.Pp .Pp
.It Ic window-status-style Ar style
Set status line style for a single window.
For how to specify
.Ar style ,
see the
.Ic message-command-style
option.
.Pp
.It Xo Ic xterm-keys .It Xo Ic xterm-keys
.Op Ic on | off .Op Ic on | off
.Xc .Xc
@ -3015,6 +3062,9 @@ for example
.Ql #{session_name} . .Ql #{session_name} .
Some variables also have an shorter alias such as Some variables also have an shorter alias such as
.Ql #S . .Ql #S .
.Ql ##
is replaced by a single
.Ql # .
Conditionals are also accepted by prefixing with Conditionals are also accepted by prefixing with
.Ql \&? .Ql \&?
and separating two alternatives with a comma; and separating two alternatives with a comma;
@ -3281,16 +3331,10 @@ content) is present.
.Pp .Pp
The colour and attributes of the status line may be configured, the entire The colour and attributes of the status line may be configured, the entire
status line using the status line using the
.Ic status-attr , .Ic status-style
.Ic status-fg session option and individual windows using the
and .Ic window-status-style
.Ic status-bg window option.
session options and individual windows using the
.Ic window-status-attr ,
.Ic window-status-fg
and
.Ic window-status-bg
window options.
.Pp .Pp
The status line is automatically refreshed at interval if it has changed, the The status line is automatically refreshed at interval if it has changed, the
interval may be controlled with the interval may be controlled with the
@ -3568,9 +3612,6 @@ specified by
.Fl t .Fl t
or the current pane if omitted). or the current pane if omitted).
If the command doesn't return success, the exit status is also displayed. If the command doesn't return success, the exit status is also displayed.
.It Ic server-info
.D1 (alias: Ic info )
Show server information and terminal details.
.It Xo Ic wait-for .It Xo Ic wait-for
.Op Fl L | S | U .Op Fl L | S | U
.Ar channel .Ar channel
@ -3794,7 +3835,7 @@ bind-key C-a send-prefix
Turning the status line off, or changing its colour: Turning the status line off, or changing its colour:
.Bd -literal -offset indent .Bd -literal -offset indent
set-option -g status off set-option -g status off
set-option -g status-bg blue set-option -g status-style bg=blue
.Ed .Ed
.Pp .Pp
Setting other options, such as the default command, Setting other options, such as the default command,

21
tmux.c
View File

@ -205,8 +205,9 @@ int
main(int argc, char **argv) main(int argc, char **argv)
{ {
struct passwd *pw; struct passwd *pw;
char *s, *path, *label, *home, **var, tmp[MAXPATHLEN]; char *s, *path, *label, **var, tmp[MAXPATHLEN];
char in[256]; char in[256];
const char *home;
long long pid; long long pid;
int opt, flags, quiet, keys, session; int opt, flags, quiet, keys, session;
@ -331,11 +332,15 @@ main(int argc, char **argv)
pw = getpwuid(getuid()); pw = getpwuid(getuid());
if (pw != NULL) if (pw != NULL)
home = pw->pw_dir; home = pw->pw_dir;
else
home = NULL;
} }
xasprintf(&cfg_file, "%s/.tmux.conf", home); if (home != NULL) {
if (access(cfg_file, R_OK) != 0 && errno == ENOENT) { xasprintf(&cfg_file, "%s/.tmux.conf", home);
free(cfg_file); if (access(cfg_file, R_OK) != 0 && errno == ENOENT) {
cfg_file = NULL; free(cfg_file);
cfg_file = NULL;
}
} }
} }
@ -367,7 +372,11 @@ main(int argc, char **argv)
} }
} }
free(label); free(label);
strlcpy(socket_path, path, sizeof socket_path);
if (strlcpy(socket_path, path, sizeof socket_path) >= sizeof socket_path) {
fprintf(stderr, "socket path too long: %s\n", path);
exit(1);
}
free(path); free(path);
#ifdef HAVE_SETPROCTITLE #ifdef HAVE_SETPROCTITLE

42
tmux.h
View File

@ -719,11 +719,12 @@ struct options_entry {
enum { enum {
OPTIONS_STRING, OPTIONS_STRING,
OPTIONS_NUMBER, OPTIONS_NUMBER,
OPTIONS_DATA, OPTIONS_STYLE
} type; } type;
char *str; char *str;
long long num; long long num;
struct grid_cell style;
RB_ENTRY(options_entry) entry; RB_ENTRY(options_entry) entry;
}; };
@ -1021,6 +1022,8 @@ struct layout_cell {
u_int yoff; u_int yoff;
struct window_pane *wp; struct window_pane *wp;
struct window_pane *lastwp;
struct layout_cells cells; struct layout_cells cells;
TAILQ_ENTRY(layout_cell) entry; TAILQ_ENTRY(layout_cell) entry;
@ -1444,7 +1447,8 @@ enum options_table_type {
OPTIONS_TABLE_COLOUR, OPTIONS_TABLE_COLOUR,
OPTIONS_TABLE_ATTRIBUTES, OPTIONS_TABLE_ATTRIBUTES,
OPTIONS_TABLE_FLAG, OPTIONS_TABLE_FLAG,
OPTIONS_TABLE_CHOICE OPTIONS_TABLE_CHOICE,
OPTIONS_TABLE_STYLE
}; };
struct options_table_entry { struct options_table_entry {
@ -1457,6 +1461,8 @@ struct options_table_entry {
const char *default_str; const char *default_str;
long long default_num; long long default_num;
const char *style;
}; };
/* Tree of format entries. */ /* Tree of format entries. */
@ -1568,12 +1574,15 @@ void options_free(struct options *);
struct options_entry *options_find1(struct options *, const char *); struct options_entry *options_find1(struct options *, const char *);
struct options_entry *options_find(struct options *, const char *); struct options_entry *options_find(struct options *, const char *);
void options_remove(struct options *, const char *); void options_remove(struct options *, const char *);
struct options_entry *printflike3 options_set_string( struct options_entry *printflike3 options_set_string(struct options *,
struct options *, const char *, const char *, ...); const char *, const char *, ...);
char *options_get_string(struct options *, const char *); char *options_get_string(struct options *, const char *);
struct options_entry *options_set_number( struct options_entry *options_set_number(struct options *, const char *,
struct options *, const char *, long long); long long);
long long options_get_number(struct options *, const char *); long long options_get_number(struct options *, const char *);
struct options_entry *options_set_style(struct options *, const char *,
const char *, int);
struct grid_cell *options_get_style(struct options *, const char *);
/* options-table.c */ /* options-table.c */
extern const struct options_table_entry server_options_table[]; extern const struct options_table_entry server_options_table[];
@ -1732,6 +1741,8 @@ int cmd_find_index(struct cmd_q *, const char *,
struct winlink *cmd_find_pane(struct cmd_q *, const char *, struct session **, struct winlink *cmd_find_pane(struct cmd_q *, const char *, struct session **,
struct window_pane **); struct window_pane **);
char *cmd_template_replace(const char *, const char *, int); char *cmd_template_replace(const char *, const char *, int);
struct window *cmd_lookup_windowid(const char *);
struct window_pane *cmd_lookup_paneid(const char *);
extern const struct cmd_entry *cmd_table[]; extern const struct cmd_entry *cmd_table[];
extern const struct cmd_entry cmd_attach_session_entry; extern const struct cmd_entry cmd_attach_session_entry;
extern const struct cmd_entry cmd_bind_key_entry; extern const struct cmd_entry cmd_bind_key_entry;
@ -2031,8 +2042,6 @@ void printflike5 screen_write_nputs(struct screen_write_ctx *,
ssize_t, struct grid_cell *, int, const char *, ...); ssize_t, struct grid_cell *, int, const char *, ...);
void screen_write_vnputs(struct screen_write_ctx *, void screen_write_vnputs(struct screen_write_ctx *,
ssize_t, struct grid_cell *, int, const char *, va_list); ssize_t, struct grid_cell *, int, const char *, va_list);
void screen_write_parsestyle(
struct grid_cell *, struct grid_cell *, const char *);
void screen_write_putc( void screen_write_putc(
struct screen_write_ctx *, struct grid_cell *, u_char); struct screen_write_ctx *, struct grid_cell *, u_char);
void screen_write_copy(struct screen_write_ctx *, void screen_write_copy(struct screen_write_ctx *,
@ -2068,7 +2077,7 @@ void screen_write_setselection(struct screen_write_ctx *, u_char *, u_int);
void screen_write_rawstring(struct screen_write_ctx *, u_char *, u_int); void screen_write_rawstring(struct screen_write_ctx *, u_char *, u_int);
/* screen-redraw.c */ /* screen-redraw.c */
void screen_redraw_screen(struct client *, int, int); void screen_redraw_screen(struct client *, int, int, int);
void screen_redraw_pane(struct client *, struct window_pane *); void screen_redraw_pane(struct client *, struct window_pane *);
/* screen.c */ /* screen.c */
@ -2162,7 +2171,6 @@ struct window_pane *window_pane_find_right(struct window_pane *);
void window_set_name(struct window *, const char *); void window_set_name(struct window *, const char *);
void window_remove_ref(struct window *); void window_remove_ref(struct window *);
void winlink_clear_flags(struct winlink *); void winlink_clear_flags(struct winlink *);
void window_mode_attrs(struct grid_cell *, struct options *);
/* layout.c */ /* layout.c */
u_int layout_count_cells(struct layout_cell *); u_int layout_count_cells(struct layout_cell *);
@ -2336,4 +2344,14 @@ int xvasprintf(char **, const char *, va_list);
int printflike3 xsnprintf(char *, size_t, const char *, ...); int printflike3 xsnprintf(char *, size_t, const char *, ...);
int xvsnprintf(char *, size_t, const char *, va_list); int xvsnprintf(char *, size_t, const char *, va_list);
/* style.c */
int style_parse(const struct grid_cell *,
struct grid_cell *, const char *);
const char *style_tostring(struct grid_cell *);
void style_update_new(struct options *, const char *, const char *);
void style_update_old(struct options *, const char *,
struct grid_cell *);
void style_apply(struct grid_cell *, struct options *, const char *);
void style_apply_update(struct grid_cell *, struct options *, const char *);
#endif /* TMUX_H */ #endif /* TMUX_H */

View File

@ -30,38 +30,38 @@ struct tty_acs_entry {
const char *string; const char *string;
}; };
const struct tty_acs_entry tty_acs_table[] = { const struct tty_acs_entry tty_acs_table[] = {
{ '+', "\342\206\222" }, { '+', "\342\206\222" }, /* arrow pointing right */
{ ',', "\342\206\220" }, { ',', "\342\206\220" }, /* arrow pointing left */
{ '-', "\342\206\221" }, { '-', "\342\206\221" }, /* arrow pointing up */
{ '.', "\342\206\223" }, { '.', "\342\206\223" }, /* arrow pointing down */
{ '0', "\342\226\256" }, { '0', "\342\226\256" }, /* solid square block */
{ '`', "\342\227\206" }, { '`', "\342\227\206" }, /* diamond */
{ 'a', "\342\226\222" }, { 'a', "\342\226\222" }, /* checker board (stipple) */
{ 'f', "\302\260" }, { 'f', "\302\260" }, /* degree symbol */
{ 'g', "\302\261" }, { 'g', "\302\261" }, /* plus/minus */
{ 'h', "\342\226\222" }, { 'h', "\342\226\222" }, /* board of squares */
{ 'i', "\342\230\203" }, { 'i', "\342\230\203" }, /* lantern symbol */
{ 'j', "\342\224\230" }, { 'j', "\342\224\230" }, /* lower right corner */
{ 'k', "\342\224\220" }, { 'k', "\342\224\220" }, /* upper right corner */
{ 'l', "\342\224\214" }, { 'l', "\342\224\214" }, /* upper left corner */
{ 'm', "\342\224\224" }, { 'm', "\342\224\224" }, /* lower left corner */
{ 'n', "\342\224\274" }, { 'n', "\342\224\274" }, /* large plus or crossover */
{ 'o', "\342\216\272" }, { 'o', "\342\216\272" }, /* scan line 1 */
{ 'p', "\342\216\273" }, { 'p', "\342\216\273" }, /* scan line 3 */
{ 'q', "\342\224\200" }, { 'q', "\342\224\200" }, /* horizontal line */
{ 'r', "\342\216\274" }, { 'r', "\342\216\274" }, /* scan line 7 */
{ 's', "\342\216\275" }, { 's', "\342\216\275" }, /* scan line 9 */
{ 't', "\342\224\234" }, { 't', "\342\224\234" }, /* tee pointing right */
{ 'u', "\342\224\244" }, { 'u', "\342\224\244" }, /* tee pointing left */
{ 'v', "\342\224\264" }, { 'v', "\342\224\264" }, /* tee pointing up */
{ 'w', "\342\224\254" }, { 'w', "\342\224\254" }, /* tee pointing down */
{ 'x', "\342\224\202" }, { 'x', "\342\224\202" }, /* vertical line */
{ 'y', "\342\211\244" }, { 'y', "\342\211\244" }, /* less-than-or-equal-to */
{ 'z', "\342\211\245" }, { 'z', "\342\211\245" }, /* greater-than-or-equal-to */
{ '{', "\317\200" }, { '{', "\317\200" }, /* greek pi */
{ '|', "\342\211\240" }, { '|', "\342\211\240" }, /* not-equal */
{ '}', "\302\243" }, { '}', "\302\243" }, /* UK pound sign */
{ '~', "\302\267" } { '~', "\302\267" } /* bullet */
}; };
int int

3
tty.c
View File

@ -1354,8 +1354,7 @@ tty_attributes(struct tty *tty, const struct grid_cell *gc)
tty_putcode(tty, TTYC_BOLD); tty_putcode(tty, TTYC_BOLD);
if (changed & GRID_ATTR_DIM) if (changed & GRID_ATTR_DIM)
tty_putcode(tty, TTYC_DIM); tty_putcode(tty, TTYC_DIM);
if (changed & GRID_ATTR_ITALICS) if (changed & GRID_ATTR_ITALICS) {
{
if (tty_term_has(tty->term, TTYC_SITM)) if (tty_term_has(tty->term, TTYC_SITM))
tty_putcode(tty, TTYC_SITM); tty_putcode(tty, TTYC_SITM);
else else

View File

@ -345,8 +345,7 @@ window_choose_collapse(struct window_pane *wp, struct session *s)
* assign the actual result we want to render and copy the new one over * assign the actual result we want to render and copy the new one over
* the top of it. * the top of it.
*/ */
for (i = 0; i < ARRAY_LENGTH(&data->list); i++) for (i = 0; i < ARRAY_LENGTH(&data->list); i++) {
{
item = &ARRAY_ITEM(&data->list, i); item = &ARRAY_ITEM(&data->list, i);
wcd = item->wcd; wcd = item->wcd;
@ -737,7 +736,7 @@ window_choose_write_line(
utf8flag = options_get_number(&wp->window->options, "utf8"); utf8flag = options_get_number(&wp->window->options, "utf8");
memcpy(&gc, &grid_default_cell, sizeof gc); memcpy(&gc, &grid_default_cell, sizeof gc);
if (data->selected == data->top + py) if (data->selected == data->top + py)
window_mode_attrs(&gc, oo); style_apply(&gc, oo, "mode-style");
screen_write_cursormove(ctx, 0, py); screen_write_cursormove(ctx, 0, py);
if (data->top + py < ARRAY_LENGTH(&data->list)) { if (data->top + py < ARRAY_LENGTH(&data->list)) {
@ -764,7 +763,7 @@ window_choose_write_line(
screen_write_putc(ctx, &gc, ' '); screen_write_putc(ctx, &gc, ' ');
if (data->input_type != WINDOW_CHOOSE_NORMAL) { if (data->input_type != WINDOW_CHOOSE_NORMAL) {
window_mode_attrs(&gc, oo); style_apply(&gc, oo, "mode-style");
xoff = xsnprintf(hdr, sizeof hdr, xoff = xsnprintf(hdr, sizeof hdr,
"%s: %s", data->input_prompt, data->input_str); "%s: %s", data->input_prompt, data->input_str);

View File

@ -750,8 +750,10 @@ window_copy_key_input(struct window_pane *wp, int key)
{ {
struct window_copy_mode_data *data = wp->modedata; struct window_copy_mode_data *data = wp->modedata;
struct screen *s = &data->screen; struct screen *s = &data->screen;
size_t inputlen; size_t inputlen, n;
int np; int np;
struct paste_buffer *pb;
u_char ch;
switch (mode_key_lookup(&data->mdata, key, NULL)) { switch (mode_key_lookup(&data->mdata, key, NULL)) {
case MODEKEYEDIT_CANCEL: case MODEKEYEDIT_CANCEL:
@ -765,6 +767,20 @@ window_copy_key_input(struct window_pane *wp, int key)
case MODEKEYEDIT_DELETELINE: case MODEKEYEDIT_DELETELINE:
*data->inputstr = '\0'; *data->inputstr = '\0';
break; break;
case MODEKEYEDIT_PASTE:
if ((pb = paste_get_top(&global_buffers)) == NULL)
break;
for (n = 0; n < pb->size; n++) {
ch = (u_char) pb->data[n];
if (ch < 32 || ch == 127)
break;
}
inputlen = strlen(data->inputstr);
data->inputstr = xrealloc(data->inputstr, 1, inputlen + n + 1);
memcpy(data->inputstr + inputlen, pb->data, n);
data->inputstr[inputlen + n] = '\0';
break;
case MODEKEYEDIT_ENTER: case MODEKEYEDIT_ENTER:
np = data->numprefix; np = data->numprefix;
if (np <= 0) if (np <= 0)
@ -853,8 +869,12 @@ window_copy_mouse(
} else if (m->wheel == MOUSE_WHEEL_DOWN) { } else if (m->wheel == MOUSE_WHEEL_DOWN) {
for (i = 0; i < 5; i++) for (i = 0; i < 5; i++)
window_copy_cursor_down(wp, 1); window_copy_cursor_down(wp, 1);
if (data->oy == 0) /*
goto reset_mode; * We reached the bottom, leave copy mode,
* but only if no selection is in progress.
*/
if (data->oy == 0 && !s->sel.flag)
goto reset_mode;
} }
return; return;
} }
@ -1030,7 +1050,7 @@ window_copy_search_up(struct window_pane *wp, const char *searchstr)
cis = 1; cis = 1;
for (ptr = searchstr; *ptr != '\0'; ptr++) { for (ptr = searchstr; *ptr != '\0'; ptr++) {
if (*ptr != tolower(*ptr)) { if (*ptr != tolower((u_char)*ptr)) {
cis = 0; cis = 0;
break; break;
} }
@ -1097,7 +1117,7 @@ window_copy_search_down(struct window_pane *wp, const char *searchstr)
cis = 1; cis = 1;
for (ptr = searchstr; *ptr != '\0'; ptr++) { for (ptr = searchstr; *ptr != '\0'; ptr++) {
if (*ptr != tolower(*ptr)) { if (*ptr != tolower((u_char)*ptr)) {
cis = 0; cis = 0;
break; break;
} }
@ -1150,10 +1170,10 @@ window_copy_write_line(
struct screen *s = &data->screen; struct screen *s = &data->screen;
struct options *oo = &wp->window->options; struct options *oo = &wp->window->options;
struct grid_cell gc; struct grid_cell gc;
char hdr[32]; char hdr[512];
size_t last, xoff = 0, size = 0; size_t last, xoff = 0, size = 0, limit;
window_mode_attrs(&gc, oo); style_apply(&gc, oo, "mode-style");
last = screen_size_y(s) - 1; last = screen_size_y(s) - 1;
if (py == 0) { if (py == 0) {
@ -1164,11 +1184,14 @@ window_copy_write_line(
screen_write_cursormove(ctx, screen_size_x(s) - size, 0); screen_write_cursormove(ctx, screen_size_x(s) - size, 0);
screen_write_puts(ctx, &gc, "%s", hdr); screen_write_puts(ctx, &gc, "%s", hdr);
} else if (py == last && data->inputtype != WINDOW_COPY_OFF) { } else if (py == last && data->inputtype != WINDOW_COPY_OFF) {
limit = sizeof hdr;
if (limit > screen_size_x(s))
limit = screen_size_x(s);
if (data->inputtype == WINDOW_COPY_NUMERICPREFIX) { if (data->inputtype == WINDOW_COPY_NUMERICPREFIX) {
xoff = size = xsnprintf(hdr, sizeof hdr, xoff = size = xsnprintf(hdr, limit,
"Repeat: %u", data->numprefix); "Repeat: %u", data->numprefix);
} else { } else {
xoff = size = xsnprintf(hdr, sizeof hdr, xoff = size = xsnprintf(hdr, limit,
"%s: %s", data->inputprompt, data->inputstr); "%s: %s", data->inputprompt, data->inputstr);
} }
screen_write_cursormove(ctx, 0, last); screen_write_cursormove(ctx, 0, last);
@ -1267,7 +1290,7 @@ window_copy_update_selection(struct window_pane *wp, int may_redraw)
return (0); return (0);
/* Set colours. */ /* Set colours. */
window_mode_attrs(&gc, oo); style_apply(&gc, oo, "mode-style");
/* Find top of screen. */ /* Find top of screen. */
ty = screen_hsize(data->backing) - data->oy; ty = screen_hsize(data->backing) - data->oy;

View File

@ -58,6 +58,10 @@ struct window_pane_tree all_window_panes;
u_int next_window_pane_id; u_int next_window_pane_id;
u_int next_window_id; u_int next_window_id;
struct window_pane *window_pane_active_set(struct window_pane *,
struct window_pane *);
void window_pane_active_lost(struct window_pane *, struct window_pane *);
void window_pane_timer_callback(int, short, void *); void window_pane_timer_callback(int, short, void *);
void window_pane_read_callback(struct bufferevent *, void *); void window_pane_read_callback(struct bufferevent *, void *);
void window_pane_error_callback(struct bufferevent *, short, void *); void window_pane_error_callback(struct bufferevent *, short, void *);
@ -383,6 +387,59 @@ window_resize(struct window *w, u_int sx, u_int sy)
w->sy = sy; w->sy = sy;
} }
/*
* Restore previously active pane when changing from wp to nextwp. The intended
* pane is in nextwp and it returns the previously focused pane.
*/
struct window_pane *
window_pane_active_set(struct window_pane *wp, struct window_pane *nextwp)
{
struct layout_cell *lc;
struct window_pane *lastwp;
/* Target pane's parent must not be an ancestor of source pane. */
for (lc = wp->layout_cell->parent; lc != NULL; lc = lc->parent) {
if (lc == nextwp->layout_cell->parent)
return (nextwp);
}
/*
* Previously active pane, if any, must not be the same as the source
* pane.
*/
if (nextwp->layout_cell->parent != NULL) {
lastwp = nextwp->layout_cell->parent->lastwp;
if (lastwp != wp && window_pane_visible(lastwp))
return (lastwp);
}
return (nextwp);
}
/* Remember previously active pane when changing from wp to nextwp. */
void
window_pane_active_lost(struct window_pane *wp, struct window_pane *nextwp)
{
struct layout_cell *lc, *lc2;
/* Save the target pane in its parent. */
nextwp->layout_cell->parent->lastwp = nextwp;
/*
* Save the source pane in all of its parents up to, but not including,
* the common ancestor of itself and the target panes.
*/
if (wp == NULL)
return;
for (lc = wp->layout_cell->parent; lc != NULL; lc = lc->parent) {
lc2 = nextwp->layout_cell->parent;
for (; lc2 != NULL; lc2 = lc2->parent) {
if (lc == lc2)
return;
}
lc->lastwp = wp;
}
}
void void
window_set_active_pane(struct window *w, struct window_pane *wp) window_set_active_pane(struct window *w, struct window_pane *wp)
{ {
@ -390,6 +447,7 @@ window_set_active_pane(struct window *w, struct window_pane *wp)
return; return;
w->last = w->active; w->last = w->active;
w->active = wp; w->active = wp;
window_pane_active_lost(w->last, wp);
while (!window_pane_visible(w->active)) { while (!window_pane_visible(w->active)) {
w->active = TAILQ_PREV(w->active, window_panes, entry); w->active = TAILQ_PREV(w->active, window_panes, entry);
if (w->active == NULL) if (w->active == NULL)
@ -704,6 +762,16 @@ window_pane_create(struct window *w, u_int sx, u_int sy, u_int hlimit)
void void
window_pane_destroy(struct window_pane *wp) window_pane_destroy(struct window_pane *wp)
{ {
struct window_pane *wp2;
/* Forget removed pane in all layout cells that remember it. */
RB_FOREACH(wp2, window_pane_tree, &all_window_panes) {
if (wp2->layout_cell != NULL &&
wp2->layout_cell->parent != NULL &&
wp2->layout_cell->parent->lastwp == wp)
wp2->layout_cell->parent->lastwp = NULL;
}
window_pane_reset_mode(wp); window_pane_reset_mode(wp);
if (event_initialized(&wp->changes_timer)) if (event_initialized(&wp->changes_timer))
@ -1131,7 +1199,7 @@ window_pane_find_up(struct window_pane *wp)
if (wp2->yoff + wp2->sy + 1 != top) if (wp2->yoff + wp2->sy + 1 != top)
continue; continue;
if (left >= wp2->xoff && left <= wp2->xoff + wp2->sx) if (left >= wp2->xoff && left <= wp2->xoff + wp2->sx)
return (wp2); return (window_pane_active_set(wp, wp2));
} }
return (NULL); return (NULL);
} }
@ -1157,7 +1225,7 @@ window_pane_find_down(struct window_pane *wp)
if (wp2->yoff != bottom) if (wp2->yoff != bottom)
continue; continue;
if (left >= wp2->xoff && left <= wp2->xoff + wp2->sx) if (left >= wp2->xoff && left <= wp2->xoff + wp2->sx)
return (wp2); return (window_pane_active_set(wp, wp2));
} }
return (NULL); return (NULL);
} }
@ -1186,7 +1254,7 @@ window_pane_find_left(struct window_pane *wp)
if (wp2->xoff + wp2->sx + 1 != left) if (wp2->xoff + wp2->sx + 1 != left)
continue; continue;
if (top >= wp2->yoff && top <= wp2->yoff + wp2->sy) if (top >= wp2->yoff && top <= wp2->yoff + wp2->sy)
return (wp2); return (window_pane_active_set(wp, wp2));
} }
return (NULL); return (NULL);
} }
@ -1215,7 +1283,7 @@ window_pane_find_right(struct window_pane *wp)
if (wp2->xoff != right) if (wp2->xoff != right)
continue; continue;
if (top >= wp2->yoff && top <= wp2->yoff + wp2->sy) if (top >= wp2->yoff && top <= wp2->yoff + wp2->sy)
return (wp2); return (window_pane_active_set(wp, wp2));
} }
return (NULL); return (NULL);
} }
@ -1248,13 +1316,3 @@ winlink_clear_flags(struct winlink *wl)
} }
} }
} }
/* Set the grid_cell with fg/bg/attr information when window is in a mode. */
void
window_mode_attrs(struct grid_cell *gc, struct options *oo)
{
memcpy(gc, &grid_default_cell, sizeof *gc);
colour_set_fg(gc, options_get_number(oo, "mode-fg"));
colour_set_bg(gc, options_get_number(oo, "mode-bg"));
gc->attr |= options_get_number(oo, "mode-attr");
}

View File

@ -133,7 +133,7 @@ xterm_keys_match(const char *template, const char *buf, size_t len)
do { do {
if (*template != '_' && buf[pos] != *template) if (*template != '_' && buf[pos] != *template)
return (-1); return (-1);
} while (pos++ != len && *++template != '\0'); } while (*++template != '\0' && ++pos != len);
if (*template != '\0') /* partial */ if (*template != '\0') /* partial */
return (1); return (1);