Merge branch 'master' of ssh://git.code.sf.net/p/tmux/tmux-code

This commit is contained in:
Thomas 2014-02-05 10:47:57 +00:00
commit 6eef24c37a
25 changed files with 1147 additions and 825 deletions

View File

@ -122,7 +122,6 @@ dist_tmux_SOURCES = \
cmd-select-pane.c \ cmd-select-pane.c \
cmd-select-window.c \ cmd-select-window.c \
cmd-send-keys.c \ cmd-send-keys.c \
cmd-server-info.c \
cmd-set-buffer.c \ cmd-set-buffer.c \
cmd-set-environment.c \ cmd-set-environment.c \
cmd-set-option.c \ cmd-set-option.c \
@ -131,7 +130,6 @@ dist_tmux_SOURCES = \
cmd-show-options.c \ cmd-show-options.c \
cmd-source-file.c \ cmd-source-file.c \
cmd-split-window.c \ cmd-split-window.c \
cmd-start-server.c \
cmd-string.c \ cmd-string.c \
cmd-suspend-client.c \ cmd-suspend-client.c \
cmd-swap-pane.c \ cmd-swap-pane.c \
@ -175,6 +173,7 @@ dist_tmux_SOURCES = \
session.c \ session.c \
signal.c \ signal.c \
status.c \ status.c \
style.c \
tmux.c \ tmux.c \
tty-acs.c \ tty-acs.c \
tty-keys.c \ tty-keys.c \

131
TODO
View File

@ -18,14 +18,16 @@
- options bits and pieces: - options bits and pieces:
* set-remain-on-exit is a complete hack * set-remain-on-exit is a complete hack
* way to set socket path from config file * way to set socket path from config file
* -fg/-bg/-attr is crap - better just foo-style options which accept
fg=,bg=,bright and so on like #[]
- format improvements: - format improvements:
* option to quote format (#{session_name:quoted}) * option to quote format (#{session_name:quoted})
* formats need conditions for >0 (for #P) * formats need conditions for >0 (for #P)
* some way to pad # stuff with spaces, #!2T maybe * some way to pad # stuff with spaces, #!2T maybe
* status stuff is redundant with formats * status stuff is redundant with formats
* last window update time and format for it
* formats to show if a window is linked into multiple sessions, into
multiple attached sessions, and is the active window in multiple
attached sessions?
- choose mode improvements: - choose mode improvements:
* choose-pane command (augment choose-tree to do this?) * choose-pane command (augment choose-tree to do this?)
@ -40,105 +42,92 @@
* monitor changes within a region * monitor changes within a region
* perhaps monitor /all/ panes in the window not just one * perhaps monitor /all/ panes in the window not just one
- panning over window (window larger than visible)
- link panes into multiple windows
- improve mouse support: - improve mouse support:
* bind commands to mouse in different areas? * bind commands to mouse in different areas?
* more fine-grained options * more fine-grained options
* commands executed when clicking on a pattern (URL) * commands executed when clicking on a pattern (URL)
* send arrow key sequences for mouse scroll wheel in alternate screen
* mouse-select-pane will screw up with !MODE_MOUSE_STANDARD (it sets
the flag on w/o checking the others before calling tty_update_mode)
- hooks! - hooks!
- warts on current naming: - warts on current naming:
* display-time but message-fg/bg/attr * display-time but message-fg/bg/attr
* list-* vs show-* * list-* vs show-*
* server-info
* split-window -> split-pane?? * split-window -> split-pane??
- way to keep a job running just read its last line of output for #()
- better UTF-8 support: - better UTF-8 support:
* #22T can split in the middle of UTF-8 characters! * #22T can split in the middle of UTF-8 characters!
* window names and titles * window names and titles
* message display * message display
* prompt input * prompt input
* multibyte key input * multibyte key input
* buffer_sample and the choose-* could show UTF-8 properly
- live update: server started with -U connects to server, requests sessions and
windows, receives file descriptors
- there are inconsistencies in what we get from old shell and what comes from
config for new sessions and windows
- multiline status line?
- support title stack, both internally and externally (restore on detach)
http://docs.freebsd.org/cgi/getmsg.cgi?fetch=1149299+0+archive/2010/freebsd-questions/20100207.freebsd-questions
- last window update time and format for it
- bind commands to key sequences -- make it so ALL keys go through a table,
first an implicit table in which C-b is the only default binding to a command
that says "next key from $othertable" and so on. means -n can go away as well
- copy/paste improvements: - copy/paste improvements:
* case insensitive searching
* incremental searching * incremental searching
* append to buffer * append to buffer
* paste w/o trailing whitespace * paste w/o trailing whitespace
* named buffers and allow gaps in the stack * named buffers and allow gaps in the stack
* command to toggle selection not to move it in copy-mode * command to toggle selection not to move it in copy-mode
- mouse-select-pane will screw up with !MODE_MOUSE_STANDARD (it sets the flag - layout stuff
on w/o checking the others before calling tty_update_mode) * way to tag a layout as a number/name
* maybe keep last layout + size around and if size reverts just put it
back
* revamp layouts: they are too complicated, should be more closely
integrated, should support hints, layout sets should just be a
special case of custom layouts, and we should support panes that are
not attached to a cell at all. this could be the time to introduce
panelink to replace layout_cell
* way to set hints/limits about pane size for resizing
* panning over window (window larger than visible)
- way to tag a layout as a number/name - terminfo bits
* use a better termcap internally instead of screen, perhaps xterm
- optimize pane redraws, 20120318184853.GK10965@yelena.nicm.ath.cx * use screen-256color when started on 256 colour terminal?
* need a tmux terminfo entry to document the extensions we are using in
- instead of separate window and session options, just one master options list
with each option having a type (window or session), then options on window,
on session, and global. for window options we look window->session->global,
and for session we look session->global
- maybe keep last layout + size around and if size reverts just put it back
- way to set hints/limits about pane size for resizing
- revamp layouts: they are too complicated, should be more closely integrated,
should support hints, layout sets should just be a special case of custom
layouts, and we should support panes that are not attached to a cell at
all. this could be the time to introduce panelink to replace layout_cell
- use a better termcap internally instead of screen, perhaps xterm
- use screen-256color when started on 256 colour terminal?
- we need a tmux terminfo entry to document the extensions we are using in
upstream terminfo upstream terminfo
* support title stack, both internally and externally (restore on
detach) http://docs.freebsd.org/cgi/getmsg.cgi?fetch=1149299+0+archive/2010/freebsd-questions/20100207.freebsd-questions
- send arrow key sequences for mouse scroll wheel when in alternate screen - code cleanup
* instead of separate window and session options, just one master
- the way pane, window, session destroy is handled is too complicated and the options list with each option having a type (window or session), then
distinction between session.c, window.c and server-fn.c functions is not options on window, on session, and global. for window options we look
clear. could we just have kill_pane(), kill_window(), unlink_window(), window->session->global, and for session we look session->global
kill_session() that fix up all data structures (flagging sessions as dead) * the way pane, window, session destroy is handled is too complicated
and return a value to say whether clients need to be checked for dead and the distinction between session.c, window.c and server-fn.c
sessions? sort of like session_detach now but more so. or some other scheme functions is not clear. could we just have kill_pane(),
to make it simpler and clearer? also would be nice to remove/rename kill_window(), unlink_window(), kill_session() that fix up all data
server-fn.c structures (flagging sessions as dead) and return a value to say
whether clients need to be checked for dead sessions? sort of like
- more readable way to work out the various things commands need to know about session_detach now but more so. or some other scheme to make it
the client, notably: simpler and clearer? also would be nice to remove/rename server-fn.c
* more readable way to work out the various things commands need to
know about the client, notably:
- is this the config file? (cmdq->c == NULL) - is this the config file? (cmdq->c == NULL)
- is this a command client? (cmdq->c != NULL && cmdq->c->session == NULL) - is this a command client? (cmdq->c != NULL &&
cmdq->c->session == NULL)
- is this a control client? - is this a control client?
- can i do stdin or stdout to this client? - can i do stdin or stdout to this client?
or even guarantee that cmdq->c != NULL and provide a better way to tell when or even guarantee that cmdq->c != NULL and provide a better way to
in the config file - then we use cmdq->c if we need a client w/o a session tell when in the config file - then we use cmdq->c if we need a
else cmd_current_client client w/o a session else cmd_current_client
* optimize pane redraws, 20120318184853.GK10965@yelena.nicm.ath.cx
- miscellaneous
* way to keep a job running just read its last line of output for #()
link panes into multiple windows
* live update: server started with -U connects to server, requests
sessions and windows, receives file descriptors
* there are inconsistencies in what we get from old shell and what
comes from config for new sessions and windows
* multiline status line?
* bind commands to key sequences -- make it so ALL keys go through a
table, first an implicit table in which C-b is the only default
binding to a command that says "next key from $othertable" and so
on. means -n can go away as well
- buffer_sample and the choose-* could let UTF-8 through and display it
properly.

View File

@ -38,9 +38,19 @@ 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)
{ {
if (self->entry == &cmd_kill_server_entry)
kill(getpid(), SIGTERM); kill(getpid(), SIGTERM);
return (CMD_RETURN_NORMAL); return (CMD_RETURN_NORMAL);

View File

@ -1,173 +0,0 @@
/* $Id$ */
/*
* Copyright (c) 2008 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 <sys/utsname.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include "tmux.h"
/*
* Show various information about server.
*/
enum cmd_retval cmd_server_info_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_server_info_entry = {
"server-info", "info",
"", 0, 0,
"",
0,
NULL,
cmd_server_info_exec
};
enum cmd_retval
cmd_server_info_exec(unused struct cmd *self, struct cmd_q *cmdq)
{
struct tty_term *term;
struct client *c;
struct session *s;
struct winlink *wl;
struct window *w;
struct window_pane *wp;
struct tty_code *code;
const struct tty_term_code_entry *ent;
struct utsname un;
struct job *job;
struct grid *gd;
struct grid_line *gl;
u_int i, j, k, lines;
size_t size;
char out[80];
char *tim;
time_t t;
tim = ctime(&start_time);
*strchr(tim, '\n') = '\0';
cmdq_print(cmdq,
"tmux " VERSION ", pid %ld, started %s", (long) getpid(), tim);
cmdq_print(cmdq, "socket path %s, debug level %d", socket_path,
debug_level);
if (uname(&un) >= 0) {
cmdq_print(cmdq, "system is %s %s %s %s",
un.sysname, un.release, un.version, un.machine);
}
if (cfg_file != NULL)
cmdq_print(cmdq, "configuration file is %s", cfg_file);
else
cmdq_print(cmdq, "configuration file not specified");
cmdq_print(cmdq, "protocol version is %d", PROTOCOL_VERSION);
cmdq_print(cmdq, "%s", "");
cmdq_print(cmdq, "Clients:");
for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
c = ARRAY_ITEM(&clients, i);
if (c == NULL || c->session == NULL)
continue;
cmdq_print(cmdq,"%2d: %s (%d, %d): %s [%ux%u %s bs=%hho "
"class=%u] [flags=0x%x/0x%x, references=%u]", i,
c->tty.path, c->ibuf.fd, c->tty.fd, c->session->name,
c->tty.sx, c->tty.sy, c->tty.termname,
c->tty.tio.c_cc[VERASE], c->tty.class,
c->flags, c->tty.flags, c->references);
}
cmdq_print(cmdq, "%s", "");
cmdq_print(cmdq, "Sessions: [%zu]", sizeof (struct grid_cell));
RB_FOREACH(s, sessions, &sessions) {
t = s->creation_time.tv_sec;
tim = ctime(&t);
*strchr(tim, '\n') = '\0';
cmdq_print(cmdq, "%2u: %s: %u windows (created %s) [%ux%u] "
"[flags=0x%x]", s->id, s->name,
winlink_count(&s->windows), tim, s->sx, s->sy, s->flags);
RB_FOREACH(wl, winlinks, &s->windows) {
w = wl->window;
cmdq_print(cmdq, "%4u: %s [%ux%u] [flags=0x%x, "
"references=%u, last layout=%d]", wl->idx, w->name,
w->sx, w->sy, w->flags, w->references,
w->lastlayout);
j = 0;
TAILQ_FOREACH(wp, &w->panes, entry) {
lines = size = 0;
gd = wp->base.grid;
for (k = 0; k < gd->hsize + gd->sy; k++) {
gl = &gd->linedata[k];
if (gl->celldata == NULL)
continue;
lines++;
size += gl->cellsize *
sizeof *gl->celldata;
}
cmdq_print(cmdq,
"%6u: %s %lu %d %u/%u, %zu bytes", j,
wp->tty, (u_long) wp->pid, wp->fd, lines,
gd->hsize + gd->sy, size);
j++;
}
}
}
cmdq_print(cmdq, "%s", "");
cmdq_print(cmdq, "Terminals:");
LIST_FOREACH(term, &tty_terms, entry) {
cmdq_print(cmdq, "%s [references=%u, flags=0x%x]:",
term->name, term->references, term->flags);
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, "%2u: %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, "%2u: %s: (string) %s",
ent->code, ent->name, out);
break;
case TTYCODE_NUMBER:
cmdq_print(cmdq, "%2u: %s: (number) %d",
ent->code, ent->name, code->value.number);
break;
case TTYCODE_FLAG:
cmdq_print(cmdq, "%2u: %s: (flag) %s",
ent->code, ent->name,
code->value.flag ? "true" : "false");
break;
}
}
}
cmdq_print(cmdq, "%s", "");
cmdq_print(cmdq, "Jobs:");
LIST_FOREACH(job, &all_jobs, lentry) {
cmdq_print(cmdq, "%s [fd=%d, pid=%d, status=%d]",
job->cmd, job->fd, job->pid, job->status);
}
return (CMD_RETURN_NORMAL);
}

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,7 @@
#include <string.h> #include <string.h>
#include <time.h> #include <time.h>
#include <unistd.h>
#include "tmux.h" #include "tmux.h"
@ -31,13 +32,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 +132,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

@ -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

@ -16,6 +16,7 @@ AC_CANONICAL_HOST
# Set up the compiler in two different ways and say yes we may want to install. # Set up the compiler in two different ways and say yes we may want to install.
AC_PROG_CC AC_PROG_CC
AM_PROG_CC_C_O AM_PROG_CC_C_O
AC_PROG_MKDIR_P
AC_PROG_INSTALL AC_PROG_INSTALL
# Default tmux.conf goes in /etc not ${prefix}/etc. # Default tmux.conf goes in /etc not ${prefix}/etc.

1
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], \

55
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 },
}; };
@ -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

@ -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;
struct window_pane *wp; u_int top;
struct grid_cell active_gc, other_gc; int status, spos;
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

@ -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;
}

324
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
@ -3284,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
@ -3571,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
@ -3797,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,

36
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[];
@ -2033,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 *,
@ -2070,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 */
@ -2164,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 *);
@ -2338,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 */

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

@ -736,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)) {
@ -763,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,7 +869,11 @@ 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) /*
* 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; goto reset_mode;
} }
return; return;
@ -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);