mirror of
https://github.com/tmux/tmux.git
synced 2025-04-17 09:18:48 +00:00
Merge branch 'master' into 3.0-rc
This commit is contained in:
commit
da552eb73b
.github
CHANGESMakefile.amREADMEarguments.ccfg.cclient.ccmd-attach-session.ccmd-break-pane.ccmd-display-message.ccmd-display-panes.ccmd-find-window.ccmd-find.ccmd-if-shell.ccmd-join-pane.ccmd-load-buffer.ccmd-new-session.ccmd-parse.ycmd-queue.ccmd-refresh-client.ccmd-resize-pane.ccmd-run-shell.ccmd-select-pane.ccmd-send-keys.ccmd-set-option.ccmd-show-options.ccmd-source-file.ccmd-swap-pane.ccmd-wait-for.ccmd.ccolour.cconfigure.accontrol-notify.ccontrol.cformat-draw.cformat.cgrid-view.cgrid.cinput-keys.cinput.cjob.ckey-string.clayout-custom.clayout-set.clayout.cmenu.cmode-tree.coptions-table.coptions.cosdep-netbsd.cregress
regsub.cscreen-redraw.cscreen-write.cserver-client.cserver-fn.cserver.cspawn.cstyle.ctmux.1tmux.ctmux.htty-term.ctty.cwindow-buffer.cwindow-copy.cwindow.cxmalloc.c
9
.github/CONTRIBUTING.md
vendored
9
.github/CONTRIBUTING.md
vendored
@ -2,13 +2,20 @@
|
||||
|
||||
Before opening an issue, please ensure that:
|
||||
|
||||
- Your problem is a specific problem or question or suggestion, not a general
|
||||
complaint.
|
||||
|
||||
- `$TERM` inside tmux is screen, screen-256color, tmux or tmux-256color. Check
|
||||
by running `echo $TERM` inside tmux.
|
||||
|
||||
- You can reproduce the problem with the latest tmux release, or a build from
|
||||
Git master.
|
||||
|
||||
- Your question or issue is not covered in the manual (run man tmux).
|
||||
- Your question or issue is not covered [in the
|
||||
manual](https://man.openbsd.org/tmux.1) (run `man tmux`).
|
||||
|
||||
- Your problem is not mentioned in the [CHANGES
|
||||
file](https://raw.githubusercontent.com/tmux/tmux/master/CHANGES) file.
|
||||
|
||||
- Nobody else has opened the same issue recently.
|
||||
|
||||
|
3
.github/ISSUE_TEMPLATE.md
vendored
3
.github/ISSUE_TEMPLATE.md
vendored
@ -3,6 +3,9 @@
|
||||
Please read https://github.com/tmux/tmux/blob/master/.github/CONTRIBUTING.md
|
||||
before opening an issue.
|
||||
|
||||
If you have upgraded, make sure your issue is not covered in the CHANGES file
|
||||
for your version: https://raw.githubusercontent.com/tmux/tmux/master/CHANGES
|
||||
|
||||
Describe the problem and the steps to reproduce. Add a minimal tmux config if
|
||||
necessary. Screenshots can be helpful, but no more than one or two.
|
||||
|
||||
|
19
.github/README.md
vendored
19
.github/README.md
vendored
@ -30,7 +30,8 @@ configure with `--enable-utempter` to enable this.
|
||||
|
||||
### From version control
|
||||
|
||||
To get and build the latest from version control:
|
||||
To get and build the latest from version control - note that this requires
|
||||
`autoconf`, `automake` and `pkg-config`:
|
||||
|
||||
~~~bash
|
||||
git clone https://github.com/tmux/tmux.git
|
||||
@ -39,10 +40,6 @@ sh autogen.sh
|
||||
./configure && make
|
||||
~~~
|
||||
|
||||
(Note that this requires at least a working C compiler, `make`, `autoconf`,
|
||||
`automake`, `pkg-config` as well as `libevent` and `ncurses` libraries and
|
||||
headers.)
|
||||
|
||||
## Contributing
|
||||
|
||||
Bug reports, feature suggestions and especially code contributions are most
|
||||
@ -50,14 +47,12 @@ welcome. Please send by email to:
|
||||
|
||||
tmux-users@googlegroups.com
|
||||
|
||||
Or open a GitHub issue or pull request.
|
||||
Or open a GitHub issue or pull request. **Please read [this
|
||||
document](CONTRIBUTING.md) before opening an issue.**
|
||||
|
||||
There is [a TODO list](https://github.com/tmux/tmux/wiki/Contributing) which
|
||||
explains some ideas for tmux not yet developed. Please feel free to ask for
|
||||
clarifications on the mailing list if you're thinking of working on these or
|
||||
need further information.
|
||||
|
||||
Please read the CONTRIBUTING file before opening an issue.
|
||||
There is [a list of suggestions for contributions](https://github.com/tmux/tmux/wiki/Contributing).
|
||||
Please feel free to ask on the mailing list if you're thinking of working on something or need
|
||||
further information.
|
||||
|
||||
## Documentation
|
||||
|
||||
|
53
CHANGES
53
CHANGES
@ -1,3 +1,56 @@
|
||||
CHANGES FROM 3.0 to X.X
|
||||
|
||||
* Expand arguments to C and s format modifiers to match the m modifier.
|
||||
|
||||
* Add support for underscore colours (Setulc capability must be added with
|
||||
terminal-overrides as described in tmux(1)).
|
||||
|
||||
* Add a "fill" style attribute for the fill colour of the drawing area (where
|
||||
appropriate).
|
||||
|
||||
* New -H flag to send-keys to send literal keys.
|
||||
|
||||
* Format variables for pane mouse modes (mouse_utf8_flag and mouse_sgr_flag)
|
||||
and for origin mode (origin_flag).
|
||||
|
||||
* Add -F to refresh-client for flags for control mode clients, only one flag
|
||||
(no-output) supported at the moment.
|
||||
|
||||
* Add a few vi(1) keys for menus.
|
||||
|
||||
* Add pane options, set with set-option -p and displayed with show-options -p.
|
||||
Pane options inherit from window options (so every pane option is also
|
||||
a window option). The pane style is now configured by setting window-style
|
||||
and window-active-style in the pane options; select-pane -P and -g now change
|
||||
the option but are no longer documented.
|
||||
|
||||
* Do not document set-window-option and show-window-options. set-option -w and
|
||||
show-options -w should be used instead.
|
||||
|
||||
* Add a -A flag to show-options to show parent options as well (they are marked
|
||||
with a *).
|
||||
|
||||
* Resize panes lazily - do not resize unless they are in an attached, active
|
||||
window.
|
||||
|
||||
* Add regular expression support for the format search, match and substitute
|
||||
modifiers and make them able to ignore case. find-window now accepts -r to
|
||||
use regular expressions.
|
||||
|
||||
* Do not use $TMUX to find the session because for windows in multiple sessions
|
||||
it is wrong as often as it is right, and for windows in one session it is
|
||||
pointless. Instead use TMUX_PANE if it is present.
|
||||
|
||||
* Do not always resize the window back to its original size after applying a
|
||||
layout, keep it at the layout size until it must be resized (for example when
|
||||
attached and window-size is not manual).
|
||||
|
||||
* Add new-session -X and attach-session -x to send SIGHUP to parent when
|
||||
detaching (like detach-client -P).
|
||||
|
||||
* Support for octal escapes in strings (such as \007) and improve list-keys
|
||||
output so it parses correctly if copied into a configuration file.
|
||||
|
||||
CHANGES FROM 2.9 to 3.0
|
||||
|
||||
* INCOMPATIBLE: Add a new {} syntax to the configuration file. This is a string
|
||||
|
@ -151,6 +151,7 @@ dist_tmux_SOURCES = \
|
||||
options.c \
|
||||
paste.c \
|
||||
proc.c \
|
||||
regsub.c \
|
||||
resize.c \
|
||||
screen-redraw.c \
|
||||
screen-write.c \
|
||||
|
6
README
6
README
@ -26,16 +26,14 @@ To build and install tmux from a release tarball, use:
|
||||
tmux can use the utempter library to update utmp(5), if it is installed - run
|
||||
configure with --enable-utempter to enable this.
|
||||
|
||||
To get and build the latest from version control:
|
||||
To get and build the latest from version control - note that this requires
|
||||
autoconf, automake and pkg-config:
|
||||
|
||||
$ git clone https://github.com/tmux/tmux.git
|
||||
$ cd tmux
|
||||
$ sh autogen.sh
|
||||
$ ./configure && make
|
||||
|
||||
(Note that this requires at least a working C compiler, make, autoconf,
|
||||
automake, pkg-config as well as libevent and ncurses libraries and headers.)
|
||||
|
||||
* Contributing
|
||||
|
||||
Bug reports, feature suggestions and especially code contributions are most
|
||||
|
22
arguments.c
22
arguments.c
@ -37,6 +37,7 @@ TAILQ_HEAD(args_values, args_value);
|
||||
struct args_entry {
|
||||
u_char flag;
|
||||
struct args_values values;
|
||||
u_int count;
|
||||
RB_ENTRY(args_entry) entry;
|
||||
};
|
||||
|
||||
@ -173,6 +174,7 @@ args_print(struct args *args)
|
||||
size_t len;
|
||||
char *buf;
|
||||
int i;
|
||||
u_int j;
|
||||
struct args_entry *entry;
|
||||
struct args_value *value;
|
||||
|
||||
@ -186,7 +188,8 @@ args_print(struct args *args)
|
||||
|
||||
if (*buf == '\0')
|
||||
args_print_add(&buf, &len, "-");
|
||||
args_print_add(&buf, &len, "%c", entry->flag);
|
||||
for (j = 0; j < entry->count; j++)
|
||||
args_print_add(&buf, &len, "%c", entry->flag);
|
||||
}
|
||||
|
||||
/* Then the flags with arguments. */
|
||||
@ -212,12 +215,14 @@ args_escape(const char *s)
|
||||
|
||||
if (*s == '\0')
|
||||
return (xstrdup(s));
|
||||
if ((strchr(quoted, s[0]) != NULL || s[0] == '~') && s[1] == '\0') {
|
||||
if (s[0] != ' ' &&
|
||||
(strchr(quoted, s[0]) != NULL || s[0] == '~') &&
|
||||
s[1] == '\0') {
|
||||
xasprintf(&escaped, "\\%c", s[0]);
|
||||
return (escaped);
|
||||
}
|
||||
|
||||
flags = VIS_OCTAL|VIS_TAB|VIS_NL;
|
||||
flags = VIS_OCTAL|VIS_CSTYLE|VIS_TAB|VIS_NL;
|
||||
if (s[strcspn(s, quoted)] != '\0')
|
||||
flags |= VIS_DQ;
|
||||
utf8_stravis(&escaped, s, flags);
|
||||
@ -241,7 +246,12 @@ args_escape(const char *s)
|
||||
int
|
||||
args_has(struct args *args, u_char ch)
|
||||
{
|
||||
return (args_find(args, ch) != NULL);
|
||||
struct args_entry *entry;
|
||||
|
||||
entry = args_find(args, ch);
|
||||
if (entry == NULL)
|
||||
return (0);
|
||||
return (entry->count);
|
||||
}
|
||||
|
||||
/* Set argument value in the arguments tree. */
|
||||
@ -255,9 +265,11 @@ args_set(struct args *args, u_char ch, const char *s)
|
||||
if (entry == NULL) {
|
||||
entry = xcalloc(1, sizeof *entry);
|
||||
entry->flag = ch;
|
||||
entry->count = 1;
|
||||
TAILQ_INIT(&entry->values);
|
||||
RB_INSERT(args_tree, &args->tree, entry);
|
||||
}
|
||||
} else
|
||||
entry->count++;
|
||||
|
||||
if (s != NULL) {
|
||||
value = xcalloc(1, sizeof *value);
|
||||
|
10
cfg.c
10
cfg.c
@ -52,7 +52,7 @@ cfg_done(__unused struct cmdq_item *item, __unused void *data)
|
||||
cfg_show_causes(RB_MIN(sessions, &sessions));
|
||||
|
||||
if (cfg_item != NULL)
|
||||
cfg_item->flags &= ~CMDQ_WAITING;
|
||||
cmdq_continue(cfg_item);
|
||||
|
||||
status_prompt_load_history();
|
||||
|
||||
@ -90,14 +90,14 @@ start_cfg(void)
|
||||
}
|
||||
|
||||
if (cfg_file == NULL)
|
||||
load_cfg(TMUX_CONF, NULL, NULL, CMD_PARSE_QUIET, NULL);
|
||||
load_cfg(TMUX_CONF, c, NULL, CMD_PARSE_QUIET, NULL);
|
||||
|
||||
if (cfg_file == NULL && (home = find_home()) != NULL) {
|
||||
xasprintf(&cfg_file, "%s/.tmux.conf", home);
|
||||
flags = CMD_PARSE_QUIET;
|
||||
}
|
||||
if (cfg_file != NULL)
|
||||
load_cfg(cfg_file, NULL, NULL, flags, NULL);
|
||||
load_cfg(cfg_file, c, NULL, flags, NULL);
|
||||
|
||||
cmdq_append(NULL, cmdq_get_callback(cfg_done, NULL));
|
||||
}
|
||||
@ -126,6 +126,8 @@ load_cfg(const char *path, struct client *c, struct cmdq_item *item, int flags,
|
||||
pi.flags = flags;
|
||||
pi.file = path;
|
||||
pi.line = 1;
|
||||
pi.item = item;
|
||||
pi.c = c;
|
||||
|
||||
pr = cmd_parse_from_file(f, &pi);
|
||||
fclose(f);
|
||||
@ -145,7 +147,7 @@ load_cfg(const char *path, struct client *c, struct cmdq_item *item, int flags,
|
||||
if (item != NULL)
|
||||
cmdq_insert_after(item, new_item0);
|
||||
else
|
||||
cmdq_append(c, new_item0);
|
||||
cmdq_append(NULL, new_item0);
|
||||
cmd_list_free(pr->cmdlist);
|
||||
|
||||
if (new_item != NULL)
|
||||
|
4
client.c
4
client.c
@ -202,7 +202,7 @@ client_exit_message(void)
|
||||
case CLIENT_EXIT_TERMINATED:
|
||||
return ("terminated");
|
||||
case CLIENT_EXIT_LOST_SERVER:
|
||||
return ("lost server");
|
||||
return ("server exited unexpectedly");
|
||||
case CLIENT_EXIT_EXITED:
|
||||
return ("exited");
|
||||
case CLIENT_EXIT_SERVER_EXITED:
|
||||
@ -436,7 +436,7 @@ client_stdin_callback(__unused int fd, __unused short events,
|
||||
struct msg_stdin_data data;
|
||||
|
||||
data.size = read(STDIN_FILENO, data.data, sizeof data.data);
|
||||
if (data.size < 0 && (errno == EINTR || errno == EAGAIN))
|
||||
if (data.size == -1 && (errno == EINTR || errno == EAGAIN))
|
||||
return;
|
||||
|
||||
proc_send(client_peer, MSG_STDIN, -1, &data, sizeof data);
|
||||
|
@ -37,8 +37,8 @@ const struct cmd_entry cmd_attach_session_entry = {
|
||||
.name = "attach-session",
|
||||
.alias = "attach",
|
||||
|
||||
.args = { "c:dErt:", 0, 0 },
|
||||
.usage = "[-dEr] [-c working-directory] " CMD_TARGET_SESSION_USAGE,
|
||||
.args = { "c:dErt:x", 0, 0 },
|
||||
.usage = "[-dErx] [-c working-directory] " CMD_TARGET_SESSION_USAGE,
|
||||
|
||||
/* -t is special */
|
||||
|
||||
@ -48,7 +48,7 @@ const struct cmd_entry cmd_attach_session_entry = {
|
||||
|
||||
enum cmd_retval
|
||||
cmd_attach_session(struct cmdq_item *item, const char *tflag, int dflag,
|
||||
int rflag, const char *cflag, int Eflag)
|
||||
int xflag, int rflag, const char *cflag, int Eflag)
|
||||
{
|
||||
struct cmd_find_state *current = &item->shared->current;
|
||||
enum cmd_find_type type;
|
||||
@ -58,6 +58,7 @@ cmd_attach_session(struct cmdq_item *item, const char *tflag, int dflag,
|
||||
struct winlink *wl;
|
||||
struct window_pane *wp;
|
||||
char *cause;
|
||||
enum msgtype msgtype;
|
||||
|
||||
if (RB_EMPTY(&sessions)) {
|
||||
cmdq_error(item, "no sessions");
|
||||
@ -102,11 +103,15 @@ cmd_attach_session(struct cmdq_item *item, const char *tflag, int dflag,
|
||||
|
||||
c->last_session = c->session;
|
||||
if (c->session != NULL) {
|
||||
if (dflag) {
|
||||
if (dflag || xflag) {
|
||||
if (xflag)
|
||||
msgtype = MSG_DETACHKILL;
|
||||
else
|
||||
msgtype = MSG_DETACH;
|
||||
TAILQ_FOREACH(c_loop, &clients, entry) {
|
||||
if (c_loop->session != s || c == c_loop)
|
||||
continue;
|
||||
server_client_detach(c_loop, MSG_DETACH);
|
||||
server_client_detach(c_loop, msgtype);
|
||||
}
|
||||
}
|
||||
if (!Eflag)
|
||||
@ -131,11 +136,15 @@ cmd_attach_session(struct cmdq_item *item, const char *tflag, int dflag,
|
||||
if (rflag)
|
||||
c->flags |= CLIENT_READONLY;
|
||||
|
||||
if (dflag) {
|
||||
if (dflag || xflag) {
|
||||
if (xflag)
|
||||
msgtype = MSG_DETACHKILL;
|
||||
else
|
||||
msgtype = MSG_DETACH;
|
||||
TAILQ_FOREACH(c_loop, &clients, entry) {
|
||||
if (c_loop->session != s || c == c_loop)
|
||||
continue;
|
||||
server_client_detach(c_loop, MSG_DETACH);
|
||||
server_client_detach(c_loop, msgtype);
|
||||
}
|
||||
}
|
||||
if (!Eflag)
|
||||
@ -169,6 +178,6 @@ cmd_attach_session_exec(struct cmd *self, struct cmdq_item *item)
|
||||
struct args *args = self->args;
|
||||
|
||||
return (cmd_attach_session(item, args_get(args, 't'),
|
||||
args_has(args, 'd'), args_has(args, 'r'), args_get(args, 'c'),
|
||||
args_has(args, 'E')));
|
||||
args_has(args, 'd'), args_has(args, 'x'), args_has(args, 'r'),
|
||||
args_get(args, 'c'), args_has(args, 'E')));
|
||||
}
|
||||
|
@ -77,6 +77,8 @@ cmd_break_pane_exec(struct cmd *self, struct cmdq_item *item)
|
||||
layout_close_pane(wp);
|
||||
|
||||
w = wp->window = window_create(w->sx, w->sy);
|
||||
options_set_parent(wp->options, w->options);
|
||||
wp->flags |= PANE_STYLECHANGED;
|
||||
TAILQ_INSERT_HEAD(&w->panes, wp, entry);
|
||||
w->active = wp;
|
||||
|
||||
|
@ -109,8 +109,7 @@ cmd_display_message_exec(struct cmd *self, struct cmdq_item *item)
|
||||
format_defaults(ft, target_c, s, wl, wp);
|
||||
|
||||
if (args_has(args, 'a')) {
|
||||
if (item != NULL)
|
||||
format_each(ft, cmd_display_message_each, item);
|
||||
format_each(ft, cmd_display_message_each, item);
|
||||
return (CMD_RETURN_NORMAL);
|
||||
}
|
||||
|
||||
|
@ -188,7 +188,7 @@ cmd_display_panes_free(struct client *c)
|
||||
struct cmd_display_panes_data *cdata = c->overlay_data;
|
||||
|
||||
if (cdata->item != NULL)
|
||||
cdata->item->flags &= ~CMDQ_WAITING;
|
||||
cmdq_continue(cdata->item);
|
||||
free(cdata->command);
|
||||
free(cdata);
|
||||
}
|
||||
|
@ -32,8 +32,8 @@ const struct cmd_entry cmd_find_window_entry = {
|
||||
.name = "find-window",
|
||||
.alias = "findw",
|
||||
|
||||
.args = { "CNt:TZ", 1, 1 },
|
||||
.usage = "[-CNTZ] " CMD_TARGET_PANE_USAGE " match-string",
|
||||
.args = { "CNrt:TZ", 1, 1 },
|
||||
.usage = "[-CNrTZ] " CMD_TARGET_PANE_USAGE " match-string",
|
||||
|
||||
.target = { 't', CMD_FIND_PANE, 0 },
|
||||
|
||||
@ -57,30 +57,59 @@ cmd_find_window_exec(struct cmd *self, struct cmdq_item *item)
|
||||
if (!C && !N && !T)
|
||||
C = N = T = 1;
|
||||
|
||||
if (C && N && T) {
|
||||
xasprintf(&filter,
|
||||
"#{||:"
|
||||
"#{C:%s},#{||:#{m:*%s*,#{window_name}},"
|
||||
"#{m:*%s*,#{pane_title}}}}",
|
||||
s, s, s);
|
||||
} else if (C && N) {
|
||||
xasprintf(&filter,
|
||||
"#{||:#{C:%s},#{m:*%s*,#{window_name}}}",
|
||||
s, s);
|
||||
} else if (C && T) {
|
||||
xasprintf(&filter,
|
||||
"#{||:#{C:%s},#{m:*%s*,#{pane_title}}}",
|
||||
s, s);
|
||||
} else if (N && T) {
|
||||
xasprintf(&filter,
|
||||
"#{||:#{m:*%s*,#{window_name}},#{m:*%s*,#{pane_title}}}",
|
||||
s, s);
|
||||
} else if (C)
|
||||
xasprintf(&filter, "#{C:%s}", s);
|
||||
else if (N)
|
||||
xasprintf(&filter, "#{m:*%s*,#{window_name}}", s);
|
||||
else
|
||||
xasprintf(&filter, "#{m:*%s*,#{pane_title}}", s);
|
||||
if (!args_has(args, 'r')) {
|
||||
if (C && N && T) {
|
||||
xasprintf(&filter,
|
||||
"#{||:"
|
||||
"#{C:%s},#{||:#{m:*%s*,#{window_name}},"
|
||||
"#{m:*%s*,#{pane_title}}}}",
|
||||
s, s, s);
|
||||
} else if (C && N) {
|
||||
xasprintf(&filter,
|
||||
"#{||:#{C:%s},#{m:*%s*,#{window_name}}}",
|
||||
s, s);
|
||||
} else if (C && T) {
|
||||
xasprintf(&filter,
|
||||
"#{||:#{C:%s},#{m:*%s*,#{pane_title}}}",
|
||||
s, s);
|
||||
} else if (N && T) {
|
||||
xasprintf(&filter,
|
||||
"#{||:#{m:*%s*,#{window_name}},"
|
||||
"#{m:*%s*,#{pane_title}}}",
|
||||
s, s);
|
||||
} else if (C)
|
||||
xasprintf(&filter, "#{C:%s}", s);
|
||||
else if (N)
|
||||
xasprintf(&filter, "#{m:*%s*,#{window_name}}", s);
|
||||
else
|
||||
xasprintf(&filter, "#{m:*%s*,#{pane_title}}", s);
|
||||
} else {
|
||||
if (C && N && T) {
|
||||
xasprintf(&filter,
|
||||
"#{||:"
|
||||
"#{C/r:%s},#{||:#{m/r:%s,#{window_name}},"
|
||||
"#{m/r:%s,#{pane_title}}}}",
|
||||
s, s, s);
|
||||
} else if (C && N) {
|
||||
xasprintf(&filter,
|
||||
"#{||:#{C/r:%s},#{m/r:%s,#{window_name}}}",
|
||||
s, s);
|
||||
} else if (C && T) {
|
||||
xasprintf(&filter,
|
||||
"#{||:#{C/r:%s},#{m/r:%s,#{pane_title}}}",
|
||||
s, s);
|
||||
} else if (N && T) {
|
||||
xasprintf(&filter,
|
||||
"#{||:#{m/r:%s,#{window_name}},"
|
||||
"#{m/r:%s,#{pane_title}}}",
|
||||
s, s);
|
||||
} else if (C)
|
||||
xasprintf(&filter, "#{C/r:%s}", s);
|
||||
else if (N)
|
||||
xasprintf(&filter, "#{m/r:%s,#{window_name}}", s);
|
||||
else
|
||||
xasprintf(&filter, "#{m/r:%s,#{pane_title}}", s);
|
||||
}
|
||||
|
||||
new_args = args_parse("", 1, &argv);
|
||||
if (args_has(args, 'Z'))
|
||||
|
73
cmd-find.c
73
cmd-find.c
@ -75,38 +75,12 @@ static const char *cmd_find_pane_table[][2] = {
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
/* Get session from TMUX if present. */
|
||||
static struct session *
|
||||
cmd_find_try_TMUX(struct client *c)
|
||||
{
|
||||
struct environ_entry *envent;
|
||||
char tmp[256];
|
||||
long long pid;
|
||||
u_int session;
|
||||
struct session *s;
|
||||
|
||||
envent = environ_find(c->environ, "TMUX");
|
||||
if (envent == NULL)
|
||||
return (NULL);
|
||||
|
||||
if (sscanf(envent->value, "%255[^,],%lld,%d", tmp, &pid, &session) != 3)
|
||||
return (NULL);
|
||||
if (pid != getpid())
|
||||
return (NULL);
|
||||
log_debug("%s: client %p TMUX %s (session $%u)", __func__, c,
|
||||
envent->value, session);
|
||||
|
||||
s = session_find_by_id(session);
|
||||
if (s != NULL)
|
||||
log_debug("%s: session $%u still exists", __func__, s->id);
|
||||
return (s);
|
||||
}
|
||||
|
||||
/* Find pane containing client if any. */
|
||||
static struct window_pane *
|
||||
cmd_find_inside_pane(struct client *c)
|
||||
{
|
||||
struct window_pane *wp;
|
||||
struct environ_entry *envent;
|
||||
|
||||
if (c == NULL)
|
||||
return (NULL);
|
||||
@ -115,6 +89,11 @@ cmd_find_inside_pane(struct client *c)
|
||||
if (wp->fd != -1 && strcmp(wp->tty, c->ttyname) == 0)
|
||||
break;
|
||||
}
|
||||
if (wp == NULL) {
|
||||
envent = environ_find(c->environ, "TMUX_PANE");
|
||||
if (envent != NULL)
|
||||
wp = window_pane_find_by_id_str(envent->value);
|
||||
}
|
||||
if (wp != NULL)
|
||||
log_debug("%s: got pane %%%u (%s)", __func__, wp->id, wp->tty);
|
||||
return (wp);
|
||||
@ -879,8 +858,6 @@ cmd_find_from_mouse(struct cmd_find_state *fs, struct mouse_event *m, int flags)
|
||||
int
|
||||
cmd_find_from_client(struct cmd_find_state *fs, struct client *c, int flags)
|
||||
{
|
||||
struct session *s;
|
||||
struct winlink *wl;
|
||||
struct window_pane *wp;
|
||||
|
||||
/* If no client, treat as from nothing. */
|
||||
@ -902,30 +879,6 @@ cmd_find_from_client(struct cmd_find_state *fs, struct client *c, int flags)
|
||||
if (wp == NULL)
|
||||
goto unknown_pane;
|
||||
|
||||
/* If we have a session in TMUX, see if it has this pane. */
|
||||
s = cmd_find_try_TMUX(c);
|
||||
if (s != NULL) {
|
||||
RB_FOREACH(wl, winlinks, &s->windows) {
|
||||
if (window_has_pane(wl->window, wp))
|
||||
break;
|
||||
}
|
||||
if (wl != NULL) {
|
||||
log_debug("%s: session $%u has pane %%%u", __func__,
|
||||
s->id, wp->id);
|
||||
|
||||
fs->s = s;
|
||||
fs->wl = s->curw; /* use current session */
|
||||
fs->w = fs->wl->window;
|
||||
fs->wp = fs->w->active; /* use active pane */
|
||||
|
||||
cmd_find_log_state(__func__, fs);
|
||||
return (0);
|
||||
} else {
|
||||
log_debug("%s: session $%u does not have pane %%%u",
|
||||
__func__, s->id, wp->id);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Don't have a session, or it doesn't have this pane. Try all
|
||||
* sessions.
|
||||
@ -947,17 +900,7 @@ cmd_find_from_client(struct cmd_find_state *fs, struct client *c, int flags)
|
||||
return (0);
|
||||
|
||||
unknown_pane:
|
||||
/*
|
||||
* We're not running in a known pane, but maybe this client has TMUX
|
||||
* in the environment. That'd give us a session.
|
||||
*/
|
||||
s = cmd_find_try_TMUX(c);
|
||||
if (s != NULL) {
|
||||
cmd_find_from_session(fs, s, flags);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Otherwise we need to guess. */
|
||||
/* We can't find the pane so need to guess. */
|
||||
return (cmd_find_from_nothing(fs, flags));
|
||||
}
|
||||
|
||||
@ -1005,6 +948,8 @@ cmd_find_target(struct cmd_find_state *fs, struct cmdq_item *item,
|
||||
strlcat(tmp, "CANFAIL,", sizeof tmp);
|
||||
if (*tmp != '\0')
|
||||
tmp[strlen(tmp) - 1] = '\0';
|
||||
else
|
||||
strlcat(tmp, "NONE", sizeof tmp);
|
||||
log_debug("%s: target %s, type %s, item %p, flags %s", __func__,
|
||||
target == NULL ? "none" : target, s, item, tmp);
|
||||
|
||||
|
@ -67,10 +67,11 @@ cmd_if_shell_exec(struct cmd *self, struct cmdq_item *item)
|
||||
struct cmd_if_shell_data *cdata;
|
||||
char *shellcmd, *cmd;
|
||||
struct cmdq_item *new_item;
|
||||
struct cmd_find_state *fs = &item->target;
|
||||
struct client *c = cmd_find_client(item, NULL, 1);
|
||||
struct session *s = item->target.s;
|
||||
struct winlink *wl = item->target.wl;
|
||||
struct window_pane *wp = item->target.wp;
|
||||
struct session *s = fs->s;
|
||||
struct winlink *wl = fs->wl;
|
||||
struct window_pane *wp = fs->wp;
|
||||
struct cmd_parse_input pi;
|
||||
struct cmd_parse_result *pr;
|
||||
|
||||
@ -92,7 +93,7 @@ cmd_if_shell_exec(struct cmd *self, struct cmdq_item *item)
|
||||
pi.line = self->line;
|
||||
pi.item = item;
|
||||
pi.c = c;
|
||||
cmd_find_copy_state(&pi.fs, &item->target);
|
||||
cmd_find_copy_state(&pi.fs, fs);
|
||||
|
||||
pr = cmd_parse_from_string(cmd, &pi);
|
||||
switch (pr->status) {
|
||||
@ -103,7 +104,7 @@ cmd_if_shell_exec(struct cmd *self, struct cmdq_item *item)
|
||||
free(pr->error);
|
||||
return (CMD_RETURN_ERROR);
|
||||
case CMD_PARSE_SUCCESS:
|
||||
new_item = cmdq_get_command(pr->cmdlist, NULL, m, 0);
|
||||
new_item = cmdq_get_command(pr->cmdlist, fs, m, 0);
|
||||
cmdq_insert_after(item, new_item);
|
||||
cmd_list_free(pr->cmdlist);
|
||||
break;
|
||||
@ -120,7 +121,10 @@ cmd_if_shell_exec(struct cmd *self, struct cmdq_item *item)
|
||||
cdata->cmd_else = NULL;
|
||||
memcpy(&cdata->mouse, m, sizeof cdata->mouse);
|
||||
|
||||
cdata->client = item->client;
|
||||
if (!args_has(args, 'b'))
|
||||
cdata->client = item->client;
|
||||
else
|
||||
cdata->client = c;
|
||||
if (cdata->client != NULL)
|
||||
cdata->client->references++;
|
||||
|
||||
@ -137,7 +141,7 @@ cmd_if_shell_exec(struct cmd *self, struct cmdq_item *item)
|
||||
cdata->input.c = c;
|
||||
if (cdata->input.c != NULL)
|
||||
cdata->input.c->references++;
|
||||
cmd_find_copy_state(&cdata->input.fs, &item->target);
|
||||
cmd_find_copy_state(&cdata->input.fs, fs);
|
||||
|
||||
if (job_run(shellcmd, s, server_client_get_cwd(item->client, s), NULL,
|
||||
cmd_if_shell_callback, cmd_if_shell_free, cdata, 0) == NULL) {
|
||||
@ -195,7 +199,7 @@ cmd_if_shell_callback(struct job *job)
|
||||
|
||||
out:
|
||||
if (cdata->item != NULL)
|
||||
cdata->item->flags &= ~CMDQ_WAITING;
|
||||
cmdq_continue(cdata->item);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -139,6 +139,8 @@ cmd_join_pane_exec(struct cmd *self, struct cmdq_item *item)
|
||||
TAILQ_REMOVE(&src_w->panes, src_wp, entry);
|
||||
|
||||
src_wp->window = dst_w;
|
||||
options_set_parent(src_wp->options, dst_w->options);
|
||||
src_wp->flags |= PANE_STYLECHANGED;
|
||||
TAILQ_INSERT_AFTER(&dst_w->panes, dst_wp, src_wp, entry);
|
||||
layout_assign_pane(lc, src_wp);
|
||||
|
||||
|
@ -176,7 +176,7 @@ cmd_load_buffer_callback(struct client *c, int closed, void *data)
|
||||
free(cause);
|
||||
}
|
||||
out:
|
||||
cdata->item->flags &= ~CMDQ_WAITING;
|
||||
cmdq_continue(cdata->item);
|
||||
|
||||
free(cdata->bufname);
|
||||
free(cdata);
|
||||
|
@ -39,8 +39,8 @@ const struct cmd_entry cmd_new_session_entry = {
|
||||
.name = "new-session",
|
||||
.alias = "new",
|
||||
|
||||
.args = { "Ac:dDEF:n:Ps:t:x:y:", 0, -1 },
|
||||
.usage = "[-AdDEP] [-c start-directory] [-F format] [-n window-name] "
|
||||
.args = { "Ac:dDEF:n:Ps:t:x:Xy:", 0, -1 },
|
||||
.usage = "[-AdDEPX] [-c start-directory] [-F format] [-n window-name] "
|
||||
"[-s session-name] " CMD_TARGET_SESSION_USAGE " [-x width] "
|
||||
"[-y height] [command]",
|
||||
|
||||
@ -105,7 +105,8 @@ cmd_new_session_exec(struct cmd *self, struct cmdq_item *item)
|
||||
if (args_has(args, 'A')) {
|
||||
retval = cmd_attach_session(item,
|
||||
newname, args_has(args, 'D'),
|
||||
0, NULL, args_has(args, 'E'));
|
||||
args_has(args, 'X'), 0, NULL,
|
||||
args_has(args, 'E'));
|
||||
free(newname);
|
||||
return (retval);
|
||||
}
|
||||
|
61
cmd-parse.y
61
cmd-parse.y
@ -77,6 +77,8 @@ static char *cmd_parse_get_error(const char *, u_int, const char *);
|
||||
static void cmd_parse_free_command(struct cmd_parse_command *);
|
||||
static struct cmd_parse_commands *cmd_parse_new_commands(void);
|
||||
static void cmd_parse_free_commands(struct cmd_parse_commands *);
|
||||
static void cmd_parse_print_commands(struct cmd_parse_input *, u_int,
|
||||
struct cmd_list *);
|
||||
|
||||
%}
|
||||
|
||||
@ -507,6 +509,22 @@ cmd_parse_get_error(const char *file, u_int line, const char *error)
|
||||
return (s);
|
||||
}
|
||||
|
||||
static void
|
||||
cmd_parse_print_commands(struct cmd_parse_input *pi, u_int line,
|
||||
struct cmd_list *cmdlist)
|
||||
{
|
||||
char *s;
|
||||
|
||||
if (pi->item != NULL && (pi->flags & CMD_PARSE_VERBOSE)) {
|
||||
s = cmd_list_print(cmdlist, 0);
|
||||
if (pi->file != NULL)
|
||||
cmdq_print(pi->item, "%s:%u: %s", pi->file, line, s);
|
||||
else
|
||||
cmdq_print(pi->item, "%u: %s", line, s);
|
||||
free(s);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
cmd_parse_free_command(struct cmd_parse_command *cmd)
|
||||
{
|
||||
@ -663,6 +681,7 @@ cmd_parse_build_commands(struct cmd_parse_commands *cmds,
|
||||
|
||||
if (cmdlist == NULL || cmd->line != line) {
|
||||
if (cmdlist != NULL) {
|
||||
cmd_parse_print_commands(pi, line, cmdlist);
|
||||
cmd_list_move(result, cmdlist);
|
||||
cmd_list_free(cmdlist);
|
||||
}
|
||||
@ -682,6 +701,7 @@ cmd_parse_build_commands(struct cmd_parse_commands *cmds,
|
||||
cmd_list_append(cmdlist, add);
|
||||
}
|
||||
if (cmdlist != NULL) {
|
||||
cmd_parse_print_commands(pi, line, cmdlist);
|
||||
cmd_list_move(result, cmdlist);
|
||||
cmd_list_free(cmdlist);
|
||||
}
|
||||
@ -1124,17 +1144,54 @@ error:
|
||||
static int
|
||||
yylex_token_escape(char **buf, size_t *len)
|
||||
{
|
||||
int ch, type;
|
||||
int ch, type, o2, o3;
|
||||
u_int size, i, tmp;
|
||||
char s[9];
|
||||
struct utf8_data ud;
|
||||
|
||||
switch (ch = yylex_getc()) {
|
||||
ch = yylex_getc();
|
||||
|
||||
if (ch >= '4' && ch <= '7') {
|
||||
yyerror("invalid octal escape");
|
||||
return (0);
|
||||
}
|
||||
if (ch >= '0' && ch <= '3') {
|
||||
o2 = yylex_getc();
|
||||
if (o2 >= '0' && o2 <= '7') {
|
||||
o3 = yylex_getc();
|
||||
if (o3 >= '0' && o3 <= '7') {
|
||||
ch = 64 * (ch - '0') +
|
||||
8 * (o2 - '0') +
|
||||
(o3 - '0');
|
||||
yylex_append1(buf, len, ch);
|
||||
return (1);
|
||||
}
|
||||
}
|
||||
yyerror("invalid octal escape");
|
||||
return (0);
|
||||
}
|
||||
|
||||
switch (ch) {
|
||||
case EOF:
|
||||
return (0);
|
||||
case 'a':
|
||||
ch = '\a';
|
||||
break;
|
||||
case 'b':
|
||||
ch = '\b';
|
||||
break;
|
||||
case 'e':
|
||||
ch = '\033';
|
||||
break;
|
||||
case 'f':
|
||||
ch = '\f';
|
||||
break;
|
||||
case 's':
|
||||
ch = ' ';
|
||||
break;
|
||||
case 'v':
|
||||
ch = '\v';
|
||||
break;
|
||||
case 'r':
|
||||
ch = '\r';
|
||||
break;
|
||||
|
@ -156,6 +156,13 @@ cmdq_insert_hook(struct session *s, struct cmdq_item *item,
|
||||
free(name);
|
||||
}
|
||||
|
||||
/* Continue processing command queue. */
|
||||
void
|
||||
cmdq_continue(struct cmdq_item *item)
|
||||
{
|
||||
item->flags &= ~CMDQ_WAITING;
|
||||
}
|
||||
|
||||
/* Remove an item. */
|
||||
static void
|
||||
cmdq_remove(struct cmdq_item *item)
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "tmux.h"
|
||||
|
||||
@ -33,8 +34,9 @@ const struct cmd_entry cmd_refresh_client_entry = {
|
||||
.name = "refresh-client",
|
||||
.alias = "refresh",
|
||||
|
||||
.args = { "cC:DlLRSt:U", 0, 1 },
|
||||
.usage = "[-cDlLRSU] [-C size] " CMD_TARGET_CLIENT_USAGE " [adjustment]",
|
||||
.args = { "cC:DF:lLRSt:U", 0, 1 },
|
||||
.usage = "[-cDlLRSU] [-C XxY] [-F flags] " CMD_TARGET_CLIENT_USAGE
|
||||
" [adjustment]",
|
||||
|
||||
.flags = CMD_AFTERHOOK,
|
||||
.exec = cmd_refresh_client_exec
|
||||
@ -48,6 +50,7 @@ cmd_refresh_client_exec(struct cmd *self, struct cmdq_item *item)
|
||||
struct tty *tty;
|
||||
struct window *w;
|
||||
const char *size, *errstr;
|
||||
char *copy, *next, *s;
|
||||
u_int x, y, adjust;
|
||||
|
||||
if ((c = cmd_find_client(item, args_get(args, 't'), 0)) == NULL)
|
||||
@ -107,28 +110,43 @@ cmd_refresh_client_exec(struct cmd *self, struct cmdq_item *item)
|
||||
if (args_has(args, 'l')) {
|
||||
if (c->session != NULL)
|
||||
tty_putcode_ptr2(&c->tty, TTYC_MS, "", "?");
|
||||
} else if (args_has(args, 'C')) {
|
||||
if ((size = args_get(args, 'C')) == NULL) {
|
||||
cmdq_error(item, "missing size");
|
||||
return (CMD_RETURN_ERROR);
|
||||
return (CMD_RETURN_NORMAL);
|
||||
}
|
||||
|
||||
if (args_has(args, 'C') || args_has(args, 'F')) {
|
||||
if (args_has(args, 'C')) {
|
||||
if (!(c->flags & CLIENT_CONTROL)) {
|
||||
cmdq_error(item, "not a control client");
|
||||
return (CMD_RETURN_ERROR);
|
||||
}
|
||||
size = args_get(args, 'C');
|
||||
if (sscanf(size, "%u,%u", &x, &y) != 2 &&
|
||||
sscanf(size, "%ux%u", &x, &y) != 2) {
|
||||
cmdq_error(item, "bad size argument");
|
||||
return (CMD_RETURN_ERROR);
|
||||
}
|
||||
if (x < WINDOW_MINIMUM || x > WINDOW_MAXIMUM ||
|
||||
y < WINDOW_MINIMUM || y > WINDOW_MAXIMUM) {
|
||||
cmdq_error(item, "size too small or too big");
|
||||
return (CMD_RETURN_ERROR);
|
||||
}
|
||||
tty_set_size(&c->tty, x, y);
|
||||
c->flags |= CLIENT_SIZECHANGED;
|
||||
recalculate_sizes();
|
||||
}
|
||||
if (sscanf(size, "%u,%u", &x, &y) != 2 &&
|
||||
sscanf(size, "%ux%u", &x, &y)) {
|
||||
cmdq_error(item, "bad size argument");
|
||||
return (CMD_RETURN_ERROR);
|
||||
if (args_has(args, 'F')) {
|
||||
if (!(c->flags & CLIENT_CONTROL)) {
|
||||
cmdq_error(item, "not a control client");
|
||||
return (CMD_RETURN_ERROR);
|
||||
}
|
||||
s = copy = xstrdup(args_get(args, 'F'));
|
||||
while ((next = strsep(&s, ",")) != NULL) {
|
||||
/* Unknown flags are ignored. */
|
||||
if (strcmp(next, "no-output") == 0)
|
||||
c->flags |= CLIENT_CONTROL_NOOUTPUT;
|
||||
}
|
||||
free(copy);
|
||||
}
|
||||
if (x < WINDOW_MINIMUM || x > WINDOW_MAXIMUM ||
|
||||
y < WINDOW_MINIMUM || y > WINDOW_MAXIMUM) {
|
||||
cmdq_error(item, "size too small or too big");
|
||||
return (CMD_RETURN_ERROR);
|
||||
}
|
||||
if (!(c->flags & CLIENT_CONTROL)) {
|
||||
cmdq_error(item, "not a control client");
|
||||
return (CMD_RETURN_ERROR);
|
||||
}
|
||||
tty_set_size(&c->tty, x, y);
|
||||
c->flags |= CLIENT_SIZECHANGED;
|
||||
recalculate_sizes();
|
||||
return (CMD_RETURN_NORMAL);
|
||||
}
|
||||
|
||||
|
@ -144,13 +144,13 @@ cmd_resize_pane_mouse_update(struct client *c, struct mouse_event *m)
|
||||
w = wl->window;
|
||||
|
||||
y = m->y + m->oy; x = m->x + m->ox;
|
||||
if (m->statusat == 0 && y > 0)
|
||||
y--;
|
||||
if (m->statusat == 0 && y >= m->statuslines)
|
||||
y -= m->statuslines;
|
||||
else if (m->statusat > 0 && y >= (u_int)m->statusat)
|
||||
y = m->statusat - 1;
|
||||
ly = m->ly + m->oy; lx = m->lx + m->ox;
|
||||
if (m->statusat == 0 && ly > 0)
|
||||
ly--;
|
||||
if (m->statusat == 0 && ly >= m->statuslines)
|
||||
ly -= m->statuslines;
|
||||
else if (m->statusat > 0 && ly >= (u_int)m->statusat)
|
||||
ly = m->statusat - 1;
|
||||
|
||||
|
@ -155,7 +155,7 @@ cmd_run_shell_callback(struct job *job)
|
||||
free(msg);
|
||||
|
||||
if (cdata->item != NULL)
|
||||
cdata->item->flags &= ~CMDQ_WAITING;
|
||||
cmdq_continue(cdata->item);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -33,8 +33,8 @@ const struct cmd_entry cmd_select_pane_entry = {
|
||||
.name = "select-pane",
|
||||
.alias = "selectp",
|
||||
|
||||
.args = { "DdegLlMmP:RT:t:U", 0, 0 },
|
||||
.usage = "[-DdegLlMmRU] [-P style] [-T title] " CMD_TARGET_PANE_USAGE,
|
||||
.args = { "DdegLlMmP:RT:t:U", 0, 0 }, /* -P and -g deprecated */
|
||||
.usage = "[-DdeLlMmRU] [-T title] " CMD_TARGET_PANE_USAGE,
|
||||
|
||||
.target = { 't', CMD_FIND_PANE, 0 },
|
||||
|
||||
@ -90,9 +90,10 @@ cmd_select_pane_exec(struct cmd *self, struct cmdq_item *item)
|
||||
struct window *w = wl->window;
|
||||
struct session *s = item->target.s;
|
||||
struct window_pane *wp = item->target.wp, *lastwp, *markedwp;
|
||||
struct style *sy = &wp->style;
|
||||
char *pane_title;
|
||||
const char *style;
|
||||
struct style *sy;
|
||||
struct options_entry *o;
|
||||
|
||||
if (self->entry == &cmd_last_pane_entry || args_has(args, 'l')) {
|
||||
lastwp = w->last;
|
||||
@ -144,15 +145,18 @@ cmd_select_pane_exec(struct cmd *self, struct cmdq_item *item)
|
||||
|
||||
if (args_has(self->args, 'P') || args_has(self->args, 'g')) {
|
||||
if ((style = args_get(args, 'P')) != NULL) {
|
||||
style_set(sy, &grid_default_cell);
|
||||
if (style_parse(sy, &grid_default_cell, style) == -1) {
|
||||
o = options_set_style(wp->options, "window-style", 0,
|
||||
style);
|
||||
if (o == NULL) {
|
||||
cmdq_error(item, "bad style: %s", style);
|
||||
return (CMD_RETURN_ERROR);
|
||||
}
|
||||
wp->flags |= PANE_REDRAW;
|
||||
wp->flags |= (PANE_REDRAW|PANE_STYLECHANGED);
|
||||
}
|
||||
if (args_has(self->args, 'g'))
|
||||
if (args_has(self->args, 'g')) {
|
||||
sy = options_get_style(wp->options, "window-style");
|
||||
cmdq_print(item, "%s", style_tostring(sy));
|
||||
}
|
||||
return (CMD_RETURN_NORMAL);
|
||||
}
|
||||
|
||||
|
@ -33,8 +33,8 @@ const struct cmd_entry cmd_send_keys_entry = {
|
||||
.name = "send-keys",
|
||||
.alias = "send",
|
||||
|
||||
.args = { "lXRMN:t:", 0, -1 },
|
||||
.usage = "[-lXRM] [-N repeat-count] " CMD_TARGET_PANE_USAGE " key ...",
|
||||
.args = { "HlXRMN:t:", 0, -1 },
|
||||
.usage = "[-HlXRM] [-N repeat-count] " CMD_TARGET_PANE_USAGE " key ...",
|
||||
|
||||
.target = { 't', CMD_FIND_PANE, 0 },
|
||||
|
||||
@ -56,7 +56,7 @@ const struct cmd_entry cmd_send_prefix_entry = {
|
||||
};
|
||||
|
||||
static struct cmdq_item *
|
||||
cmd_send_keys_inject(struct client *c, struct cmd_find_state *fs,
|
||||
cmd_send_keys_inject_key(struct client *c, struct cmd_find_state *fs,
|
||||
struct cmdq_item *item, key_code key)
|
||||
{
|
||||
struct window_mode_entry *wme;
|
||||
@ -81,20 +81,56 @@ cmd_send_keys_inject(struct client *c, struct cmd_find_state *fs,
|
||||
return (item);
|
||||
}
|
||||
|
||||
static struct cmdq_item *
|
||||
cmd_send_keys_inject_string(struct client *c, struct cmd_find_state *fs,
|
||||
struct cmdq_item *item, struct args *args, int i)
|
||||
{
|
||||
const char *s = args->argv[i];
|
||||
struct utf8_data *ud, *uc;
|
||||
wchar_t wc;
|
||||
key_code key;
|
||||
char *endptr;
|
||||
long n;
|
||||
int literal;
|
||||
|
||||
if (args_has(args, 'H')) {
|
||||
n = strtol(s, &endptr, 16);
|
||||
if (*s =='\0' || n < 0 || n > 0xff || *endptr != '\0')
|
||||
return (item);
|
||||
return (cmd_send_keys_inject_key(c, fs, item, KEYC_LITERAL|n));
|
||||
}
|
||||
|
||||
literal = args_has(args, 'l');
|
||||
if (!literal) {
|
||||
key = key_string_lookup_string(s);
|
||||
if (key != KEYC_NONE && key != KEYC_UNKNOWN)
|
||||
return (cmd_send_keys_inject_key(c, fs, item, key));
|
||||
literal = 1;
|
||||
}
|
||||
if (literal) {
|
||||
ud = utf8_fromcstr(s);
|
||||
for (uc = ud; uc->size != 0; uc++) {
|
||||
if (utf8_combine(uc, &wc) != UTF8_DONE)
|
||||
continue;
|
||||
item = cmd_send_keys_inject_key(c, fs, item, wc);
|
||||
}
|
||||
free(ud);
|
||||
}
|
||||
return (item);
|
||||
}
|
||||
|
||||
static enum cmd_retval
|
||||
cmd_send_keys_exec(struct cmd *self, struct cmdq_item *item)
|
||||
{
|
||||
struct args *args = self->args;
|
||||
struct client *c = cmd_find_client(item, NULL, 1);
|
||||
struct cmd_find_state *fs = &item->target;
|
||||
struct window_pane *wp = item->target.wp;
|
||||
struct session *s = item->target.s;
|
||||
struct winlink *wl = item->target.wl;
|
||||
struct mouse_event *m = &item->shared->mouse;
|
||||
struct cmd_find_state *fs = &item->target;
|
||||
struct window_mode_entry *wme = TAILQ_FIRST(&wp->modes);
|
||||
struct utf8_data *ud, *uc;
|
||||
wchar_t wc;
|
||||
int i, literal;
|
||||
int i;
|
||||
key_code key;
|
||||
u_int np = 1;
|
||||
char *cause = NULL;
|
||||
@ -141,7 +177,7 @@ cmd_send_keys_exec(struct cmd *self, struct cmdq_item *item)
|
||||
key = options_get_number(s->options, "prefix2");
|
||||
else
|
||||
key = options_get_number(s->options, "prefix");
|
||||
cmd_send_keys_inject(c, fs, item, key);
|
||||
cmd_send_keys_inject_key(c, fs, item, key);
|
||||
return (CMD_RETURN_NORMAL);
|
||||
}
|
||||
|
||||
@ -151,28 +187,8 @@ cmd_send_keys_exec(struct cmd *self, struct cmdq_item *item)
|
||||
}
|
||||
|
||||
for (; np != 0; np--) {
|
||||
for (i = 0; i < args->argc; i++) {
|
||||
literal = args_has(args, 'l');
|
||||
if (!literal) {
|
||||
key = key_string_lookup_string(args->argv[i]);
|
||||
if (key != KEYC_NONE && key != KEYC_UNKNOWN) {
|
||||
item = cmd_send_keys_inject(c, fs, item,
|
||||
key);
|
||||
} else
|
||||
literal = 1;
|
||||
}
|
||||
if (literal) {
|
||||
ud = utf8_fromcstr(args->argv[i]);
|
||||
for (uc = ud; uc->size != 0; uc++) {
|
||||
if (utf8_combine(uc, &wc) != UTF8_DONE)
|
||||
continue;
|
||||
item = cmd_send_keys_inject(c, fs, item,
|
||||
wc);
|
||||
}
|
||||
free(ud);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < args->argc; i++)
|
||||
item = cmd_send_keys_inject_string(c, fs, item, args, i);
|
||||
}
|
||||
|
||||
return (CMD_RETURN_NORMAL);
|
||||
|
@ -43,10 +43,10 @@ const struct cmd_entry cmd_set_option_entry = {
|
||||
.name = "set-option",
|
||||
.alias = "set",
|
||||
|
||||
.args = { "aFgoqst:uw", 1, 2 },
|
||||
.usage = "[-aFgosquw] [-t target-window] option [value]",
|
||||
.args = { "aFgopqst:uw", 1, 2 },
|
||||
.usage = "[-aFgopqsuw] " CMD_TARGET_PANE_USAGE " option [value]",
|
||||
|
||||
.target = { 't', CMD_FIND_WINDOW, CMD_FIND_CANFAIL },
|
||||
.target = { 't', CMD_FIND_PANE, CMD_FIND_CANFAIL },
|
||||
|
||||
.flags = CMD_AFTERHOOK,
|
||||
.exec = cmd_set_option_exec
|
||||
@ -88,20 +88,24 @@ cmd_set_option_exec(struct cmd *self, struct cmdq_item *item)
|
||||
struct session *s = fs->s;
|
||||
struct winlink *wl = fs->wl;
|
||||
struct window *w;
|
||||
enum options_table_scope scope;
|
||||
struct window_pane *wp;
|
||||
struct options *oo;
|
||||
struct options_entry *parent, *o;
|
||||
char *name, *argument, *value = NULL, *cause;
|
||||
const char *target;
|
||||
int window, idx, already, error, ambiguous;
|
||||
int scope;
|
||||
struct style *sy;
|
||||
|
||||
window = (self->entry == &cmd_set_window_option_entry);
|
||||
|
||||
/* Expand argument. */
|
||||
c = cmd_find_client(item, NULL, 1);
|
||||
argument = format_single(item, args->argv[0], c, s, wl, NULL);
|
||||
|
||||
/* If set-hook -R, fire the hook straight away. */
|
||||
if (self->entry == &cmd_set_hook_entry && args_has(args, 'R')) {
|
||||
notify_hook(item, argument);
|
||||
free(argument);
|
||||
return (CMD_RETURN_NORMAL);
|
||||
}
|
||||
|
||||
@ -123,25 +127,8 @@ cmd_set_option_exec(struct cmd *self, struct cmdq_item *item)
|
||||
else
|
||||
value = xstrdup(args->argv[1]);
|
||||
|
||||
/*
|
||||
* Figure out the scope: for user options it comes from the arguments,
|
||||
* otherwise from the option name.
|
||||
*/
|
||||
if (*name == '@') {
|
||||
window = (self->entry == &cmd_set_window_option_entry);
|
||||
scope = options_scope_from_flags(args, window, fs, &oo, &cause);
|
||||
} else {
|
||||
if (options_get_only(global_options, name) != NULL)
|
||||
scope = OPTIONS_TABLE_SERVER;
|
||||
else if (options_get_only(global_s_options, name) != NULL)
|
||||
scope = OPTIONS_TABLE_SESSION;
|
||||
else if (options_get_only(global_w_options, name) != NULL)
|
||||
scope = OPTIONS_TABLE_WINDOW;
|
||||
else {
|
||||
scope = OPTIONS_TABLE_NONE;
|
||||
xasprintf(&cause, "unknown option: %s", argument);
|
||||
}
|
||||
}
|
||||
/* Get the scope and table for the option .*/
|
||||
scope = options_scope_from_name(args, window, name, fs, &oo, &cause);
|
||||
if (scope == OPTIONS_TABLE_NONE) {
|
||||
if (args_has(args, 'q'))
|
||||
goto out;
|
||||
@ -149,35 +136,6 @@ cmd_set_option_exec(struct cmd *self, struct cmdq_item *item)
|
||||
free(cause);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Which table should this option go into? */
|
||||
if (scope == OPTIONS_TABLE_SERVER)
|
||||
oo = global_options;
|
||||
else if (scope == OPTIONS_TABLE_SESSION) {
|
||||
if (args_has(self->args, 'g'))
|
||||
oo = global_s_options;
|
||||
else if (s == NULL) {
|
||||
target = args_get(args, 't');
|
||||
if (target != NULL)
|
||||
cmdq_error(item, "no such session: %s", target);
|
||||
else
|
||||
cmdq_error(item, "no current session");
|
||||
goto fail;
|
||||
} else
|
||||
oo = s->options;
|
||||
} else if (scope == OPTIONS_TABLE_WINDOW) {
|
||||
if (args_has(self->args, 'g'))
|
||||
oo = global_w_options;
|
||||
else if (wl == NULL) {
|
||||
target = args_get(args, 't');
|
||||
if (target != NULL)
|
||||
cmdq_error(item, "no such window: %s", target);
|
||||
else
|
||||
cmdq_error(item, "no current window");
|
||||
goto fail;
|
||||
} else
|
||||
oo = wl->window->options;
|
||||
}
|
||||
o = options_get_only(oo, name);
|
||||
parent = options_get(oo, name);
|
||||
|
||||
@ -292,8 +250,8 @@ cmd_set_option_exec(struct cmd *self, struct cmdq_item *item)
|
||||
alerts_reset_all();
|
||||
if (strcmp(name, "window-style") == 0 ||
|
||||
strcmp(name, "window-active-style") == 0) {
|
||||
RB_FOREACH(w, windows, &windows)
|
||||
w->flags |= WINDOW_STYLECHANGED;
|
||||
RB_FOREACH(wp, window_pane_tree, &all_window_panes)
|
||||
wp->flags |= PANE_STYLECHANGED;
|
||||
}
|
||||
if (strcmp(name, "pane-border-status") == 0) {
|
||||
RB_FOREACH(w, windows, &windows)
|
||||
|
@ -30,18 +30,18 @@
|
||||
static enum cmd_retval cmd_show_options_exec(struct cmd *, struct cmdq_item *);
|
||||
|
||||
static void cmd_show_options_print(struct cmd *, struct cmdq_item *,
|
||||
struct options_entry *, int);
|
||||
struct options_entry *, int, int);
|
||||
static enum cmd_retval cmd_show_options_all(struct cmd *, struct cmdq_item *,
|
||||
struct options *);
|
||||
int, struct options *);
|
||||
|
||||
const struct cmd_entry cmd_show_options_entry = {
|
||||
.name = "show-options",
|
||||
.alias = "show",
|
||||
|
||||
.args = { "gHqst:vw", 0, 1 },
|
||||
.usage = "[-gHqsvw] [-t target-session|target-window] [option]",
|
||||
.args = { "AgHpqst:vw", 0, 1 },
|
||||
.usage = "[-AgHpqsvw] " CMD_TARGET_PANE_USAGE " [option]",
|
||||
|
||||
.target = { 't', CMD_FIND_WINDOW, CMD_FIND_CANFAIL },
|
||||
.target = { 't', CMD_FIND_PANE, CMD_FIND_CANFAIL },
|
||||
|
||||
.flags = CMD_AFTERHOOK,
|
||||
.exec = cmd_show_options_exec
|
||||
@ -82,13 +82,12 @@ cmd_show_options_exec(struct cmd *self, struct cmdq_item *item)
|
||||
struct session *s = item->target.s;
|
||||
struct winlink *wl = item->target.wl;
|
||||
struct options *oo;
|
||||
enum options_table_scope scope;
|
||||
char *argument, *name = NULL, *cause;
|
||||
const char *target;
|
||||
int window, idx, ambiguous;
|
||||
int window, idx, ambiguous, parent, scope;
|
||||
struct options_entry *o;
|
||||
|
||||
window = (self->entry == &cmd_show_window_options_entry);
|
||||
|
||||
if (args->argc == 0) {
|
||||
scope = options_scope_from_flags(args, window, fs, &oo, &cause);
|
||||
if (scope == OPTIONS_TABLE_NONE) {
|
||||
@ -98,7 +97,7 @@ cmd_show_options_exec(struct cmd *self, struct cmdq_item *item)
|
||||
free(cause);
|
||||
return (CMD_RETURN_ERROR);
|
||||
}
|
||||
return (cmd_show_options_all(self, item, oo));
|
||||
return (cmd_show_options_all(self, item, scope, oo));
|
||||
}
|
||||
argument = format_single(item, args->argv[0], c, s, wl, NULL);
|
||||
|
||||
@ -112,49 +111,7 @@ cmd_show_options_exec(struct cmd *self, struct cmdq_item *item)
|
||||
cmdq_error(item, "invalid option: %s", argument);
|
||||
goto fail;
|
||||
}
|
||||
if (*name == '@')
|
||||
scope = options_scope_from_flags(args, window, fs, &oo, &cause);
|
||||
else {
|
||||
if (options_get_only(global_options, name) != NULL)
|
||||
scope = OPTIONS_TABLE_SERVER;
|
||||
else if (options_get_only(global_s_options, name) != NULL)
|
||||
scope = OPTIONS_TABLE_SESSION;
|
||||
else if (options_get_only(global_w_options, name) != NULL)
|
||||
scope = OPTIONS_TABLE_WINDOW;
|
||||
else {
|
||||
scope = OPTIONS_TABLE_NONE;
|
||||
xasprintf(&cause, "unknown option: %s", argument);
|
||||
}
|
||||
if (scope == OPTIONS_TABLE_SERVER)
|
||||
oo = global_options;
|
||||
else if (scope == OPTIONS_TABLE_SESSION) {
|
||||
if (args_has(self->args, 'g'))
|
||||
oo = global_s_options;
|
||||
else if (s == NULL) {
|
||||
target = args_get(args, 't');
|
||||
if (target != NULL) {
|
||||
cmdq_error(item, "no such session: %s",
|
||||
target);
|
||||
} else
|
||||
cmdq_error(item, "no current session");
|
||||
goto fail;
|
||||
} else
|
||||
oo = s->options;
|
||||
} else if (scope == OPTIONS_TABLE_WINDOW) {
|
||||
if (args_has(self->args, 'g'))
|
||||
oo = global_w_options;
|
||||
else if (wl == NULL) {
|
||||
target = args_get(args, 't');
|
||||
if (target != NULL) {
|
||||
cmdq_error(item, "no such window: %s",
|
||||
target);
|
||||
} else
|
||||
cmdq_error(item, "no current window");
|
||||
goto fail;
|
||||
} else
|
||||
oo = wl->window->options;
|
||||
}
|
||||
}
|
||||
scope = options_scope_from_name(args, window, name, fs, &oo, &cause);
|
||||
if (scope == OPTIONS_TABLE_NONE) {
|
||||
if (args_has(args, 'q'))
|
||||
goto fail;
|
||||
@ -163,8 +120,13 @@ cmd_show_options_exec(struct cmd *self, struct cmdq_item *item)
|
||||
goto fail;
|
||||
}
|
||||
o = options_get_only(oo, name);
|
||||
if (args_has(args, 'A') && o == NULL) {
|
||||
o = options_get(oo, name);
|
||||
parent = 1;
|
||||
} else
|
||||
parent = 0;
|
||||
if (o != NULL)
|
||||
cmd_show_options_print(self, item, o, idx);
|
||||
cmd_show_options_print(self, item, o, idx, parent);
|
||||
|
||||
free(name);
|
||||
free(argument);
|
||||
@ -178,7 +140,7 @@ fail:
|
||||
|
||||
static void
|
||||
cmd_show_options_print(struct cmd *self, struct cmdq_item *item,
|
||||
struct options_entry *o, int idx)
|
||||
struct options_entry *o, int idx, int parent)
|
||||
{
|
||||
struct options_array_item *a;
|
||||
const char *name = options_name(o);
|
||||
@ -197,7 +159,8 @@ cmd_show_options_print(struct cmd *self, struct cmdq_item *item,
|
||||
}
|
||||
while (a != NULL) {
|
||||
idx = options_array_item_index(a);
|
||||
cmd_show_options_print(self, item, o, idx);
|
||||
cmd_show_options_print(self, item, o, idx,
|
||||
parent);
|
||||
a = options_array_next(a);
|
||||
}
|
||||
return;
|
||||
@ -209,50 +172,81 @@ cmd_show_options_print(struct cmd *self, struct cmdq_item *item,
|
||||
cmdq_print(item, "%s", value);
|
||||
else if (options_isstring(o)) {
|
||||
escaped = args_escape(value);
|
||||
cmdq_print(item, "%s %s", name, escaped);
|
||||
if (parent)
|
||||
cmdq_print(item, "%s* %s", name, escaped);
|
||||
else
|
||||
cmdq_print(item, "%s %s", name, escaped);
|
||||
free(escaped);
|
||||
} else
|
||||
cmdq_print(item, "%s %s", name, value);
|
||||
} else {
|
||||
if (parent)
|
||||
cmdq_print(item, "%s* %s", name, value);
|
||||
else
|
||||
cmdq_print(item, "%s %s", name, value);
|
||||
}
|
||||
free(value);
|
||||
|
||||
free(tmp);
|
||||
}
|
||||
|
||||
static enum cmd_retval
|
||||
cmd_show_options_all(struct cmd *self, struct cmdq_item *item,
|
||||
cmd_show_options_all(struct cmd *self, struct cmdq_item *item, int scope,
|
||||
struct options *oo)
|
||||
{
|
||||
const struct options_table_entry *oe;
|
||||
struct options_entry *o;
|
||||
struct options_array_item *a;
|
||||
const char *name;
|
||||
u_int idx;
|
||||
const struct options_table_entry *oe;
|
||||
int parent;
|
||||
|
||||
o = options_first(oo);
|
||||
while (o != NULL) {
|
||||
oe = options_table_entry(o);
|
||||
if (options_table_entry(o) == NULL)
|
||||
cmd_show_options_print(self, item, o, -1, 0);
|
||||
o = options_next(o);
|
||||
}
|
||||
for (oe = options_table; oe->name != NULL; oe++) {
|
||||
if (~oe->scope & scope)
|
||||
continue;
|
||||
|
||||
if ((self->entry != &cmd_show_hooks_entry &&
|
||||
!args_has(self->args, 'H') &&
|
||||
oe != NULL &&
|
||||
(oe->flags & OPTIONS_TABLE_IS_HOOK)) ||
|
||||
(self->entry == &cmd_show_hooks_entry &&
|
||||
(oe == NULL ||
|
||||
(~oe->flags & OPTIONS_TABLE_IS_HOOK)))) {
|
||||
o = options_next(o);
|
||||
(~oe->flags & OPTIONS_TABLE_IS_HOOK))))
|
||||
continue;
|
||||
}
|
||||
|
||||
o = options_get_only(oo, oe->name);
|
||||
if (o == NULL) {
|
||||
if (!args_has(self->args, 'A'))
|
||||
continue;
|
||||
o = options_get(oo, oe->name);
|
||||
if (o == NULL)
|
||||
continue;
|
||||
parent = 1;
|
||||
} else
|
||||
parent = 0;
|
||||
|
||||
if (!options_isarray(o))
|
||||
cmd_show_options_print(self, item, o, -1);
|
||||
cmd_show_options_print(self, item, o, -1, parent);
|
||||
else if ((a = options_array_first(o)) == NULL) {
|
||||
if (!args_has(self->args, 'v'))
|
||||
cmdq_print(item, "%s", options_name(o));
|
||||
if (!args_has(self->args, 'v')) {
|
||||
name = options_name(o);
|
||||
if (parent)
|
||||
cmdq_print(item, "%s*", name);
|
||||
else
|
||||
cmdq_print(item, "%s", name);
|
||||
}
|
||||
} else {
|
||||
while (a != NULL) {
|
||||
idx = options_array_item_index(a);
|
||||
cmd_show_options_print(self, item, o, idx);
|
||||
cmd_show_options_print(self, item, o, idx,
|
||||
parent);
|
||||
a = options_array_next(a);
|
||||
}
|
||||
}
|
||||
o = options_next(o);
|
||||
}
|
||||
return (CMD_RETURN_NORMAL);
|
||||
}
|
||||
|
@ -37,8 +37,8 @@ const struct cmd_entry cmd_source_file_entry = {
|
||||
.name = "source-file",
|
||||
.alias = "source",
|
||||
|
||||
.args = { "nq", 1, -1 },
|
||||
.usage = "[-nq] path ...",
|
||||
.args = { "nqv", 1, -1 },
|
||||
.usage = "[-nqv] path ...",
|
||||
|
||||
.flags = 0,
|
||||
.exec = cmd_source_file_exec
|
||||
@ -62,6 +62,8 @@ cmd_source_file_exec(struct cmd *self, struct cmdq_item *item)
|
||||
flags |= CMD_PARSE_QUIET;
|
||||
if (args_has(args, 'n'))
|
||||
flags |= CMD_PARSE_PARSEONLY;
|
||||
if (args_has(args, 'v'))
|
||||
flags |= CMD_PARSE_VERBOSE;
|
||||
utf8_stravis(&cwd, server_client_get_cwd(c, NULL), VIS_GLOB);
|
||||
|
||||
retval = CMD_RETURN_NORMAL;
|
||||
|
@ -90,7 +90,11 @@ cmd_swap_pane_exec(struct cmd *self, struct cmdq_item *item)
|
||||
src_wp->layout_cell = dst_lc;
|
||||
|
||||
src_wp->window = dst_w;
|
||||
options_set_parent(src_wp->options, dst_w->options);
|
||||
src_wp->flags |= PANE_STYLECHANGED;
|
||||
dst_wp->window = src_w;
|
||||
options_set_parent(dst_wp->options, src_w->options);
|
||||
dst_wp->flags |= PANE_STYLECHANGED;
|
||||
|
||||
sx = src_wp->sx; sy = src_wp->sy;
|
||||
xoff = src_wp->xoff; yoff = src_wp->yoff;
|
||||
|
@ -153,7 +153,7 @@ cmd_wait_for_signal(__unused struct cmdq_item *item, const char *name,
|
||||
log_debug("signal wait channel %s, with waiters", wc->name);
|
||||
|
||||
TAILQ_FOREACH_SAFE(wi, &wc->waiters, entry, wi1) {
|
||||
wi->item->flags &= ~CMDQ_WAITING;
|
||||
cmdq_continue(wi->item);
|
||||
|
||||
TAILQ_REMOVE(&wc->waiters, wi, entry);
|
||||
free(wi);
|
||||
@ -229,7 +229,7 @@ cmd_wait_for_unlock(struct cmdq_item *item, const char *name,
|
||||
}
|
||||
|
||||
if ((wi = TAILQ_FIRST(&wc->lockers)) != NULL) {
|
||||
wi->item->flags &= ~CMDQ_WAITING;
|
||||
cmdq_continue(wi->item);
|
||||
TAILQ_REMOVE(&wc->lockers, wi, entry);
|
||||
free(wi);
|
||||
} else {
|
||||
@ -248,13 +248,13 @@ cmd_wait_for_flush(void)
|
||||
|
||||
RB_FOREACH_SAFE(wc, wait_channels, &wait_channels, wc1) {
|
||||
TAILQ_FOREACH_SAFE(wi, &wc->waiters, entry, wi1) {
|
||||
wi->item->flags &= ~CMDQ_WAITING;
|
||||
cmdq_continue(wi->item);
|
||||
TAILQ_REMOVE(&wc->waiters, wi, entry);
|
||||
free(wi);
|
||||
}
|
||||
wc->woken = 1;
|
||||
TAILQ_FOREACH_SAFE(wi, &wc->lockers, entry, wi1) {
|
||||
wi->item->flags &= ~CMDQ_WAITING;
|
||||
cmdq_continue(wi->item);
|
||||
TAILQ_REMOVE(&wc->lockers, wi, entry);
|
||||
free(wi);
|
||||
}
|
||||
|
4
cmd.c
4
cmd.c
@ -596,8 +596,8 @@ cmd_mouse_at(struct window_pane *wp, struct mouse_event *m, u_int *xp,
|
||||
}
|
||||
log_debug("%s: x=%u, y=%u%s", __func__, x, y, last ? " (last)" : "");
|
||||
|
||||
if (m->statusat == 0 && y > 0)
|
||||
y--;
|
||||
if (m->statusat == 0 && y >= m->statuslines)
|
||||
y -= m->statuslines;
|
||||
|
||||
if (x < wp->xoff || x >= wp->xoff + wp->sx)
|
||||
return (-1);
|
||||
|
84
colour.c
84
colour.c
@ -230,11 +230,85 @@ colour_fromstring(const char *s)
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/* Convert 256 colour palette to 16. */
|
||||
u_char
|
||||
colour_256to16(u_char c)
|
||||
/* Convert 256 colour to RGB colour. */
|
||||
int
|
||||
colour_256toRGB(int c)
|
||||
{
|
||||
static const u_char table[256] = {
|
||||
static const int table[256] = {
|
||||
0x000000, 0x800000, 0x008000, 0x808000,
|
||||
0x000080, 0x800080, 0x008080, 0xc0c0c0,
|
||||
0x808080, 0xff0000, 0x00ff00, 0xffff00,
|
||||
0x0000ff, 0xff00ff, 0x00ffff, 0xffffff,
|
||||
0x000000, 0x00005f, 0x000087, 0x0000af,
|
||||
0x0000d7, 0x0000ff, 0x005f00, 0x005f5f,
|
||||
0x005f87, 0x005faf, 0x005fd7, 0x005fff,
|
||||
0x008700, 0x00875f, 0x008787, 0x0087af,
|
||||
0x0087d7, 0x0087ff, 0x00af00, 0x00af5f,
|
||||
0x00af87, 0x00afaf, 0x00afd7, 0x00afff,
|
||||
0x00d700, 0x00d75f, 0x00d787, 0x00d7af,
|
||||
0x00d7d7, 0x00d7ff, 0x00ff00, 0x00ff5f,
|
||||
0x00ff87, 0x00ffaf, 0x00ffd7, 0x00ffff,
|
||||
0x5f0000, 0x5f005f, 0x5f0087, 0x5f00af,
|
||||
0x5f00d7, 0x5f00ff, 0x5f5f00, 0x5f5f5f,
|
||||
0x5f5f87, 0x5f5faf, 0x5f5fd7, 0x5f5fff,
|
||||
0x5f8700, 0x5f875f, 0x5f8787, 0x5f87af,
|
||||
0x5f87d7, 0x5f87ff, 0x5faf00, 0x5faf5f,
|
||||
0x5faf87, 0x5fafaf, 0x5fafd7, 0x5fafff,
|
||||
0x5fd700, 0x5fd75f, 0x5fd787, 0x5fd7af,
|
||||
0x5fd7d7, 0x5fd7ff, 0x5fff00, 0x5fff5f,
|
||||
0x5fff87, 0x5fffaf, 0x5fffd7, 0x5fffff,
|
||||
0x870000, 0x87005f, 0x870087, 0x8700af,
|
||||
0x8700d7, 0x8700ff, 0x875f00, 0x875f5f,
|
||||
0x875f87, 0x875faf, 0x875fd7, 0x875fff,
|
||||
0x878700, 0x87875f, 0x878787, 0x8787af,
|
||||
0x8787d7, 0x8787ff, 0x87af00, 0x87af5f,
|
||||
0x87af87, 0x87afaf, 0x87afd7, 0x87afff,
|
||||
0x87d700, 0x87d75f, 0x87d787, 0x87d7af,
|
||||
0x87d7d7, 0x87d7ff, 0x87ff00, 0x87ff5f,
|
||||
0x87ff87, 0x87ffaf, 0x87ffd7, 0x87ffff,
|
||||
0xaf0000, 0xaf005f, 0xaf0087, 0xaf00af,
|
||||
0xaf00d7, 0xaf00ff, 0xaf5f00, 0xaf5f5f,
|
||||
0xaf5f87, 0xaf5faf, 0xaf5fd7, 0xaf5fff,
|
||||
0xaf8700, 0xaf875f, 0xaf8787, 0xaf87af,
|
||||
0xaf87d7, 0xaf87ff, 0xafaf00, 0xafaf5f,
|
||||
0xafaf87, 0xafafaf, 0xafafd7, 0xafafff,
|
||||
0xafd700, 0xafd75f, 0xafd787, 0xafd7af,
|
||||
0xafd7d7, 0xafd7ff, 0xafff00, 0xafff5f,
|
||||
0xafff87, 0xafffaf, 0xafffd7, 0xafffff,
|
||||
0xd70000, 0xd7005f, 0xd70087, 0xd700af,
|
||||
0xd700d7, 0xd700ff, 0xd75f00, 0xd75f5f,
|
||||
0xd75f87, 0xd75faf, 0xd75fd7, 0xd75fff,
|
||||
0xd78700, 0xd7875f, 0xd78787, 0xd787af,
|
||||
0xd787d7, 0xd787ff, 0xd7af00, 0xd7af5f,
|
||||
0xd7af87, 0xd7afaf, 0xd7afd7, 0xd7afff,
|
||||
0xd7d700, 0xd7d75f, 0xd7d787, 0xd7d7af,
|
||||
0xd7d7d7, 0xd7d7ff, 0xd7ff00, 0xd7ff5f,
|
||||
0xd7ff87, 0xd7ffaf, 0xd7ffd7, 0xd7ffff,
|
||||
0xff0000, 0xff005f, 0xff0087, 0xff00af,
|
||||
0xff00d7, 0xff00ff, 0xff5f00, 0xff5f5f,
|
||||
0xff5f87, 0xff5faf, 0xff5fd7, 0xff5fff,
|
||||
0xff8700, 0xff875f, 0xff8787, 0xff87af,
|
||||
0xff87d7, 0xff87ff, 0xffaf00, 0xffaf5f,
|
||||
0xffaf87, 0xffafaf, 0xffafd7, 0xffafff,
|
||||
0xffd700, 0xffd75f, 0xffd787, 0xffd7af,
|
||||
0xffd7d7, 0xffd7ff, 0xffff00, 0xffff5f,
|
||||
0xffff87, 0xffffaf, 0xffffd7, 0xffffff,
|
||||
0x080808, 0x121212, 0x1c1c1c, 0x262626,
|
||||
0x303030, 0x3a3a3a, 0x444444, 0x4e4e4e,
|
||||
0x585858, 0x626262, 0x6c6c6c, 0x767676,
|
||||
0x808080, 0x8a8a8a, 0x949494, 0x9e9e9e,
|
||||
0xa8a8a8, 0xb2b2b2, 0xbcbcbc, 0xc6c6c6,
|
||||
0xd0d0d0, 0xdadada, 0xe4e4e4, 0xeeeeee
|
||||
};
|
||||
|
||||
return (table[c & 0xff] | COLOUR_FLAG_RGB);
|
||||
}
|
||||
|
||||
/* Convert 256 colour to 16 colour. */
|
||||
int
|
||||
colour_256to16(int c)
|
||||
{
|
||||
static const char table[256] = {
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
|
||||
0, 4, 4, 4, 12, 12, 2, 6, 4, 4, 12, 12, 2, 2, 6, 4,
|
||||
12, 12, 2, 2, 2, 6, 12, 12, 10, 10, 10, 10, 14, 12, 10, 10,
|
||||
@ -253,5 +327,5 @@ colour_256to16(u_char c)
|
||||
8, 8, 8, 8, 7, 7, 7, 7, 7, 7, 15, 15, 15, 15, 15, 15
|
||||
};
|
||||
|
||||
return (table[c]);
|
||||
return (table[c & 0xff]);
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
# configure.ac
|
||||
|
||||
AC_INIT([tmux], 3.0-rc3)
|
||||
AC_INIT([tmux], next-3.1)
|
||||
AC_PREREQ([2.60])
|
||||
|
||||
AC_CONFIG_AUX_DIR(etc)
|
||||
|
@ -36,6 +36,9 @@ control_notify_input(struct client *c, struct window_pane *wp,
|
||||
if (c->session == NULL)
|
||||
return;
|
||||
|
||||
if (c->flags & CLIENT_CONTROL_NOOUTPUT)
|
||||
return;
|
||||
|
||||
/*
|
||||
* Only write input if the window pane is linked to a window belonging
|
||||
* to the client's session.
|
||||
|
@ -80,6 +80,7 @@ control_callback(struct client *c, int closed, __unused void *data)
|
||||
if (line == NULL)
|
||||
break;
|
||||
if (*line == '\0') { /* empty line exit */
|
||||
free(line);
|
||||
c->flags |= CLIENT_EXIT;
|
||||
break;
|
||||
}
|
||||
|
@ -511,8 +511,9 @@ format_draw(struct screen_write_ctx *octx, const struct grid_cell *base,
|
||||
u_int ocx = os->cx, ocy = os->cy, i, width[TOTAL];
|
||||
u_int map[] = { LEFT, LEFT, CENTRE, RIGHT };
|
||||
int focus_start = -1, focus_end = -1;
|
||||
int list_state = -1;
|
||||
int list_state = -1, fill = -1;
|
||||
enum style_align list_align = STYLE_ALIGN_DEFAULT;
|
||||
struct grid_cell gc;
|
||||
struct style sy;
|
||||
struct utf8_data *ud = &sy.gc.data;
|
||||
const char *cp, *end;
|
||||
@ -564,7 +565,7 @@ format_draw(struct screen_write_ctx *octx, const struct grid_cell *base,
|
||||
cp++;
|
||||
}
|
||||
|
||||
/* Draw the cell to th current screen. */
|
||||
/* Draw the cell to the current screen. */
|
||||
screen_write_cell(&ctx[current], &sy.gc);
|
||||
width[current] += ud->width;
|
||||
continue;
|
||||
@ -590,6 +591,10 @@ format_draw(struct screen_write_ctx *octx, const struct grid_cell *base,
|
||||
style_tostring(&sy));
|
||||
free(tmp);
|
||||
|
||||
/* If this style has a fill colour, store it for later. */
|
||||
if (sy.fill != 8)
|
||||
fill = sy.fill;
|
||||
|
||||
/* Check the list state. */
|
||||
switch (sy.list) {
|
||||
case STYLE_LIST_ON:
|
||||
@ -711,6 +716,14 @@ format_draw(struct screen_write_ctx *octx, const struct grid_cell *base,
|
||||
fr->argument, names[fr->index], fr->start, fr->end);
|
||||
}
|
||||
|
||||
/* Clear the available area. */
|
||||
if (fill != -1) {
|
||||
memcpy(&gc, &grid_default_cell, sizeof gc);
|
||||
gc.bg = fill;
|
||||
for (i = 0; i < available; i++)
|
||||
screen_write_putc(octx, &gc, ' ');
|
||||
}
|
||||
|
||||
/*
|
||||
* Draw the screens. How they are arranged depends on where the list
|
||||
* appearsq.
|
||||
|
131
format.c
131
format.c
@ -23,6 +23,7 @@
|
||||
#include <errno.h>
|
||||
#include <fnmatch.h>
|
||||
#include <libgen.h>
|
||||
#include <regex.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@ -1067,6 +1068,8 @@ format_find(struct format_tree *ft, const char *key, int modifiers)
|
||||
|
||||
if (~modifiers & FORMAT_TIMESTRING) {
|
||||
o = options_parse_get(global_options, key, &idx, 0);
|
||||
if (o == NULL && ft->wp != NULL)
|
||||
o = options_parse_get(ft->wp->options, key, &idx, 0);
|
||||
if (o == NULL && ft->w != NULL)
|
||||
o = options_parse_get(ft->w->options, key, &idx, 0);
|
||||
if (o == NULL)
|
||||
@ -1263,7 +1266,7 @@ format_build_modifiers(struct format_tree *ft, const char **s, u_int *count)
|
||||
cp++;
|
||||
|
||||
/* Check single character modifiers with no arguments. */
|
||||
if (strchr("lmCbdtqETSWP<>", cp[0]) != NULL &&
|
||||
if (strchr("lbdtqETSWP<>", cp[0]) != NULL &&
|
||||
format_is_end(cp[1])) {
|
||||
format_add_modifier(&list, count, cp, 1, NULL, 0);
|
||||
cp++;
|
||||
@ -1284,7 +1287,7 @@ format_build_modifiers(struct format_tree *ft, const char **s, u_int *count)
|
||||
}
|
||||
|
||||
/* Now try single character with arguments. */
|
||||
if (strchr("s=", cp[0]) == NULL)
|
||||
if (strchr("mCs=", cp[0]) == NULL)
|
||||
break;
|
||||
c = cp[0];
|
||||
|
||||
@ -1345,39 +1348,67 @@ format_build_modifiers(struct format_tree *ft, const char **s, u_int *count)
|
||||
return list;
|
||||
}
|
||||
|
||||
/* Match against an fnmatch(3) pattern or regular expression. */
|
||||
static char *
|
||||
format_match(struct format_modifier *fm, const char *pattern, const char *text)
|
||||
{
|
||||
const char *s = "";
|
||||
regex_t r;
|
||||
int flags = 0;
|
||||
|
||||
if (fm->argc >= 1)
|
||||
s = fm->argv[0];
|
||||
if (strchr(s, 'r') == NULL) {
|
||||
if (strchr(s, 'i') != NULL)
|
||||
flags |= FNM_CASEFOLD;
|
||||
if (fnmatch(pattern, text, flags) != 0)
|
||||
return (xstrdup("0"));
|
||||
} else {
|
||||
flags = REG_EXTENDED|REG_NOSUB;
|
||||
if (strchr(s, 'i') != NULL)
|
||||
flags |= REG_ICASE;
|
||||
if (regcomp(&r, pattern, flags) != 0)
|
||||
return (xstrdup("0"));
|
||||
if (regexec(&r, text, 0, NULL, 0) != 0) {
|
||||
regfree(&r);
|
||||
return (xstrdup("0"));
|
||||
}
|
||||
regfree(&r);
|
||||
}
|
||||
return (xstrdup("1"));
|
||||
}
|
||||
|
||||
/* Perform substitution in string. */
|
||||
static char *
|
||||
format_substitute(const char *source, const char *from, const char *to)
|
||||
format_sub(struct format_modifier *fm, const char *text, const char *pattern,
|
||||
const char *with)
|
||||
{
|
||||
char *copy, *new;
|
||||
const char *cp;
|
||||
size_t fromlen, tolen, newlen, used;
|
||||
char *value;
|
||||
int flags = REG_EXTENDED;
|
||||
|
||||
fromlen = strlen(from);
|
||||
tolen = strlen(to);
|
||||
if (fm->argc >= 3 && strchr(fm->argv[2], 'i') != NULL)
|
||||
flags |= REG_ICASE;
|
||||
value = regsub(pattern, with, text, flags);
|
||||
if (value == NULL)
|
||||
return (xstrdup(text));
|
||||
return (value);
|
||||
}
|
||||
|
||||
newlen = strlen(source) + 1;
|
||||
copy = new = xmalloc(newlen);
|
||||
/* Search inside pane. */
|
||||
static char *
|
||||
format_search(struct format_modifier *fm, struct window_pane *wp, const char *s)
|
||||
{
|
||||
int ignore = 0, regex = 0;
|
||||
char *value;
|
||||
|
||||
for (cp = source; *cp != '\0'; /* nothing */) {
|
||||
if (strncmp(cp, from, fromlen) != 0) {
|
||||
*new++ = *cp++;
|
||||
continue;
|
||||
}
|
||||
used = new - copy;
|
||||
|
||||
newlen += tolen;
|
||||
copy = xrealloc(copy, newlen);
|
||||
|
||||
new = copy + used;
|
||||
memcpy(new, to, tolen);
|
||||
|
||||
new += tolen;
|
||||
cp += fromlen;
|
||||
if (fm->argc >= 1) {
|
||||
if (strchr(fm->argv[0], 'i') != NULL)
|
||||
ignore = 1;
|
||||
if (strchr(fm->argv[0], 'r') != NULL)
|
||||
regex = 1;
|
||||
}
|
||||
|
||||
*new = '\0';
|
||||
return (copy);
|
||||
xasprintf(&value, "%u", window_pane_search(wp, s, regex, ignore));
|
||||
return (value);
|
||||
}
|
||||
|
||||
/* Loop over sessions. */
|
||||
@ -1522,11 +1553,10 @@ format_replace(struct format_tree *ft, const char *key, size_t keylen,
|
||||
char *copy0, *condition, *found, *new;
|
||||
char *value, *left, *right;
|
||||
size_t valuelen;
|
||||
int modifiers = 0, limit = 0;
|
||||
int modifiers = 0, limit = 0, j;
|
||||
struct format_modifier *list, *fm, *cmp = NULL, *search = NULL;
|
||||
struct format_modifier *sub = NULL;
|
||||
u_int i, count;
|
||||
int j;
|
||||
|
||||
/* Make a copy of the key. */
|
||||
copy = copy0 = xstrndup(key, keylen);
|
||||
@ -1553,18 +1583,18 @@ format_replace(struct format_tree *ft, const char *key, size_t keylen,
|
||||
search = fm;
|
||||
break;
|
||||
case 's':
|
||||
if (fm->argc != 2)
|
||||
if (fm->argc < 2)
|
||||
break;
|
||||
sub = fm;
|
||||
break;
|
||||
case '=':
|
||||
if (fm->argc != 1 && fm->argc != 2)
|
||||
if (fm->argc < 1)
|
||||
break;
|
||||
limit = strtonum(fm->argv[0], INT_MIN, INT_MAX,
|
||||
&errptr);
|
||||
if (errptr != NULL)
|
||||
limit = 0;
|
||||
if (fm->argc == 2 && fm->argv[1] != NULL)
|
||||
if (fm->argc >= 2 && fm->argv[1] != NULL)
|
||||
marker = fm->argv[1];
|
||||
break;
|
||||
case 'l':
|
||||
@ -1630,13 +1660,15 @@ format_replace(struct format_tree *ft, const char *key, size_t keylen,
|
||||
goto fail;
|
||||
} else if (search != NULL) {
|
||||
/* Search in pane. */
|
||||
new = format_expand(ft, copy);
|
||||
if (wp == NULL) {
|
||||
format_log(ft, "search '%s' but no pane", copy);
|
||||
format_log(ft, "search '%s' but no pane", new);
|
||||
value = xstrdup("0");
|
||||
} else {
|
||||
format_log(ft, "search '%s' pane %%%u", copy, wp->id);
|
||||
xasprintf(&value, "%u", window_pane_search(wp, copy));
|
||||
format_log(ft, "search '%s' pane %%%u", new, wp->id);
|
||||
value = format_search(fm, wp, new);
|
||||
}
|
||||
free(new);
|
||||
} else if (cmp != NULL) {
|
||||
/* Comparison of left and right. */
|
||||
if (format_choose(ft, copy, &left, &right, 1) != 0) {
|
||||
@ -1687,12 +1719,8 @@ format_replace(struct format_tree *ft, const char *key, size_t keylen,
|
||||
value = xstrdup("1");
|
||||
else
|
||||
value = xstrdup("0");
|
||||
} else if (strcmp(cmp->modifier, "m") == 0) {
|
||||
if (fnmatch(left, right, 0) == 0)
|
||||
value = xstrdup("1");
|
||||
else
|
||||
value = xstrdup("0");
|
||||
}
|
||||
} else if (strcmp(cmp->modifier, "m") == 0)
|
||||
value = format_match(cmp, left, right);
|
||||
|
||||
free(right);
|
||||
free(left);
|
||||
@ -1770,11 +1798,14 @@ done:
|
||||
|
||||
/* Perform substitution if any. */
|
||||
if (sub != NULL) {
|
||||
new = format_substitute(value, sub->argv[0], sub->argv[1]);
|
||||
format_log(ft, "substituted '%s' to '%s: %s", sub->argv[0],
|
||||
sub->argv[1], new);
|
||||
left = format_expand(ft, sub->argv[0]);
|
||||
right = format_expand(ft, sub->argv[1]);
|
||||
new = format_sub(sub, value, left, right);
|
||||
format_log(ft, "substitute '%s' to '%s': %s", left, right, new);
|
||||
free(value);
|
||||
value = new;
|
||||
free(right);
|
||||
free(left);
|
||||
}
|
||||
|
||||
/* Truncate the value if needed. */
|
||||
@ -1998,10 +2029,10 @@ void
|
||||
format_defaults(struct format_tree *ft, struct client *c, struct session *s,
|
||||
struct winlink *wl, struct window_pane *wp)
|
||||
{
|
||||
if (c != NULL)
|
||||
if (c != NULL && c->name != NULL)
|
||||
log_debug("%s: c=%s", __func__, c->name);
|
||||
else
|
||||
log_debug("%s: s=none", __func__);
|
||||
log_debug("%s: c=none", __func__);
|
||||
if (s != NULL)
|
||||
log_debug("%s: s=$%u", __func__, s->id);
|
||||
else
|
||||
@ -2286,6 +2317,8 @@ format_defaults_pane(struct format_tree *ft, struct window_pane *wp)
|
||||
!!(wp->base.mode & MODE_KKEYPAD));
|
||||
format_add(ft, "wrap_flag", "%d",
|
||||
!!(wp->base.mode & MODE_WRAP));
|
||||
format_add(ft, "origin_flag", "%d",
|
||||
!!(wp->base.mode & MODE_ORIGIN));
|
||||
|
||||
format_add(ft, "mouse_any_flag", "%d",
|
||||
!!(wp->base.mode & ALL_MOUSE_MODES));
|
||||
@ -2295,6 +2328,10 @@ format_defaults_pane(struct format_tree *ft, struct window_pane *wp)
|
||||
!!(wp->base.mode & MODE_MOUSE_BUTTON));
|
||||
format_add(ft, "mouse_all_flag", "%d",
|
||||
!!(wp->base.mode & MODE_MOUSE_ALL));
|
||||
format_add(ft, "mouse_utf8_flag", "%d",
|
||||
!!(wp->base.mode & MODE_MOUSE_UTF8));
|
||||
format_add(ft, "mouse_sgr_flag", "%d",
|
||||
!!(wp->base.mode & MODE_MOUSE_SGR));
|
||||
|
||||
format_add_cb(ft, "pane_tabs", format_cb_pane_tabs);
|
||||
}
|
||||
|
@ -214,7 +214,6 @@ grid_view_delete_cells(struct grid *gd, u_int px, u_int py, u_int nx, u_int bg)
|
||||
sx = grid_view_x(gd, gd->sx);
|
||||
|
||||
grid_move_cells(gd, px, px + nx, py, sx - px - nx, bg);
|
||||
grid_clear(gd, sx - nx, py, px + nx - (sx - nx), 1, bg);
|
||||
}
|
||||
|
||||
/* Convert cells into a string. */
|
||||
|
35
grid.c
35
grid.c
@ -37,12 +37,12 @@
|
||||
|
||||
/* Default grid cell data. */
|
||||
const struct grid_cell grid_default_cell = {
|
||||
0, 0, 8, 8, { { ' ' }, 0, 1, 1 }
|
||||
{ { ' ' }, 0, 1, 1 }, 0, 0, 8, 8, 0
|
||||
};
|
||||
|
||||
/* Cleared grid cell data. */
|
||||
const struct grid_cell grid_cleared_cell = {
|
||||
GRID_FLAG_CLEARED, 0, 8, 8, { { ' ' }, 0, 1, 1 }
|
||||
{ { ' ' }, 0, 1, 1 }, 0, GRID_FLAG_CLEARED, 8, 8, 0
|
||||
};
|
||||
static const struct grid_cell_entry grid_cleared_entry = {
|
||||
GRID_FLAG_CLEARED, { .data = { 0, 8, 8, ' ' } }
|
||||
@ -82,6 +82,8 @@ grid_need_extended_cell(const struct grid_cell_entry *gce,
|
||||
return (1);
|
||||
if ((gc->fg & COLOUR_FLAG_RGB) || (gc->bg & COLOUR_FLAG_RGB))
|
||||
return (1);
|
||||
if (gc->us != 0) /* only supports 256 or RGB */
|
||||
return (1);
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -473,6 +475,7 @@ grid_get_cell1(struct grid_line *gl, u_int px, struct grid_cell *gc)
|
||||
gc->bg = gce->data.bg;
|
||||
if (gce->flags & GRID_FLAG_BG256)
|
||||
gc->bg |= COLOUR_FLAG_256;
|
||||
gc->us = 0;
|
||||
utf8_set(&gc->data, gce->data.data);
|
||||
}
|
||||
|
||||
@ -544,7 +547,7 @@ void
|
||||
grid_clear(struct grid *gd, u_int px, u_int py, u_int nx, u_int ny, u_int bg)
|
||||
{
|
||||
struct grid_line *gl;
|
||||
u_int xx, yy;
|
||||
u_int xx, yy, ox, sx;
|
||||
|
||||
if (nx == 0 || ny == 0)
|
||||
return;
|
||||
@ -561,16 +564,20 @@ grid_clear(struct grid *gd, u_int px, u_int py, u_int nx, u_int ny, u_int bg)
|
||||
|
||||
for (yy = py; yy < py + ny; yy++) {
|
||||
gl = &gd->linedata[yy];
|
||||
if (px + nx >= gd->sx && px < gl->cellused)
|
||||
gl->cellused = px;
|
||||
if (px > gl->cellsize && COLOUR_DEFAULT(bg))
|
||||
continue;
|
||||
if (px + nx >= gl->cellsize && COLOUR_DEFAULT(bg)) {
|
||||
gl->cellsize = px;
|
||||
continue;
|
||||
|
||||
sx = gd->sx;
|
||||
if (sx > gl->cellsize)
|
||||
sx = gl->cellsize;
|
||||
ox = nx;
|
||||
if (COLOUR_DEFAULT(bg)) {
|
||||
if (px > sx)
|
||||
continue;
|
||||
if (px + nx > sx)
|
||||
ox = sx - px;
|
||||
}
|
||||
grid_expand_line(gd, yy, px + nx, 8); /* default bg first */
|
||||
for (xx = px; xx < px + nx; xx++)
|
||||
|
||||
grid_expand_line(gd, yy, px + ox, 8); /* default bg first */
|
||||
for (xx = px; xx < px + ox; xx++)
|
||||
grid_clear_cell(gd, xx, yy, bg);
|
||||
}
|
||||
}
|
||||
@ -1213,6 +1220,10 @@ grid_reflow(struct grid *gd, u_int sx)
|
||||
struct grid_cell gc;
|
||||
u_int yy, width, i, at, first;
|
||||
|
||||
/* Do not reflow to the same size. */
|
||||
if (sx == gd->sx)
|
||||
return;
|
||||
|
||||
/*
|
||||
* Create a destination grid. This is just used as a container for the
|
||||
* line data and may not be fully valid.
|
||||
|
@ -172,6 +172,13 @@ input_key(struct window_pane *wp, key_code key, struct mouse_event *m)
|
||||
return;
|
||||
}
|
||||
|
||||
/* Literal keys go as themselves (can't be more than eight bits). */
|
||||
if (key & KEYC_LITERAL) {
|
||||
ud.data[0] = (u_char)key;
|
||||
bufferevent_write(wp->event, &ud.data[0], 1);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* If this is a normal 7-bit key, just send it, with a leading escape
|
||||
* if necessary. If it is a UTF-8 key, split it and send it.
|
||||
|
29
input.c
29
input.c
@ -1829,6 +1829,8 @@ input_csi_dispatch_sgr_256_do(struct input_ctx *ictx, int fgbg, int c)
|
||||
gc->fg = c | COLOUR_FLAG_256;
|
||||
else if (fgbg == 48)
|
||||
gc->bg = c | COLOUR_FLAG_256;
|
||||
else if (fgbg == 58)
|
||||
gc->us = c | COLOUR_FLAG_256;
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
@ -1862,6 +1864,8 @@ input_csi_dispatch_sgr_rgb_do(struct input_ctx *ictx, int fgbg, int r, int g,
|
||||
gc->fg = colour_join_rgb(r, g, b);
|
||||
else if (fgbg == 48)
|
||||
gc->bg = colour_join_rgb(r, g, b);
|
||||
else if (fgbg == 58)
|
||||
gc->us = colour_join_rgb(r, g, b);
|
||||
return (1);
|
||||
}
|
||||
|
||||
@ -1938,7 +1942,7 @@ input_csi_dispatch_sgr_colon(struct input_ctx *ictx, u_int i)
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (n < 2 || (p[0] != 38 && p[0] != 48))
|
||||
if (n < 2 || (p[0] != 38 && p[0] != 48 && p[0] != 58))
|
||||
return;
|
||||
switch (p[1]) {
|
||||
case 2:
|
||||
@ -1983,7 +1987,7 @@ input_csi_dispatch_sgr(struct input_ctx *ictx)
|
||||
if (n == -1)
|
||||
continue;
|
||||
|
||||
if (n == 38 || n == 48) {
|
||||
if (n == 38 || n == 48 || n == 58) {
|
||||
i++;
|
||||
switch (input_get(ictx, i, 0, -1)) {
|
||||
case 2:
|
||||
@ -2078,6 +2082,9 @@ input_csi_dispatch_sgr(struct input_ctx *ictx)
|
||||
case 55:
|
||||
gc->attr &= ~GRID_ATTR_OVERLINE;
|
||||
break;
|
||||
case 59:
|
||||
gc->us = 0;
|
||||
break;
|
||||
case 90:
|
||||
case 91:
|
||||
case 92:
|
||||
@ -2259,7 +2266,7 @@ input_exit_rename(struct input_ctx *ictx)
|
||||
{
|
||||
if (ictx->flags & INPUT_DISCARD)
|
||||
return;
|
||||
if (!options_get_number(ictx->wp->window->options, "allow-rename"))
|
||||
if (!options_get_number(ictx->wp->options, "allow-rename"))
|
||||
return;
|
||||
log_debug("%s: \"%s\"", __func__, ictx->input_buf);
|
||||
|
||||
@ -2347,12 +2354,14 @@ input_osc_10(struct input_ctx *ictx, const char *p)
|
||||
{
|
||||
struct window_pane *wp = ictx->wp;
|
||||
u_int r, g, b;
|
||||
char tmp[16];
|
||||
|
||||
if (sscanf(p, "rgb:%2x/%2x/%2x", &r, &g, &b) != 3)
|
||||
goto bad;
|
||||
|
||||
wp->style.gc.fg = colour_join_rgb(r, g, b);
|
||||
wp->flags |= PANE_REDRAW;
|
||||
xsnprintf(tmp, sizeof tmp, "fg=#%02x%02x%02x", r, g, b);
|
||||
options_set_style(wp->options, "window-style", 1, tmp);
|
||||
options_set_style(wp->options, "window-active-style", 1, tmp);
|
||||
wp->flags |= (PANE_REDRAW|PANE_STYLECHANGED);
|
||||
|
||||
return;
|
||||
|
||||
@ -2366,12 +2375,14 @@ input_osc_11(struct input_ctx *ictx, const char *p)
|
||||
{
|
||||
struct window_pane *wp = ictx->wp;
|
||||
u_int r, g, b;
|
||||
char tmp[16];
|
||||
|
||||
if (sscanf(p, "rgb:%2x/%2x/%2x", &r, &g, &b) != 3)
|
||||
goto bad;
|
||||
|
||||
wp->style.gc.bg = colour_join_rgb(r, g, b);
|
||||
wp->flags |= PANE_REDRAW;
|
||||
xsnprintf(tmp, sizeof tmp, "bg=#%02x%02x%02x", r, g, b);
|
||||
options_set_style(wp->options, "window-style", 1, tmp);
|
||||
options_set_style(wp->options, "window-active-style", 1, tmp);
|
||||
wp->flags |= (PANE_REDRAW|PANE_STYLECHANGED);
|
||||
|
||||
return;
|
||||
|
||||
|
2
job.c
2
job.c
@ -117,7 +117,7 @@ job_run(const char *cmd, struct session *s, const char *cwd,
|
||||
close(out[0]);
|
||||
|
||||
nullfd = open(_PATH_DEVNULL, O_RDWR, 0);
|
||||
if (nullfd < 0)
|
||||
if (nullfd == -1)
|
||||
fatal("open failed");
|
||||
if (dup2(nullfd, STDERR_FILENO) == -1)
|
||||
fatal("dup2 failed");
|
||||
|
@ -284,6 +284,12 @@ key_string_lookup_key(key_code key)
|
||||
return (out);
|
||||
}
|
||||
|
||||
/* Literal keys are themselves. */
|
||||
if (key & KEYC_LITERAL) {
|
||||
snprintf(out, sizeof out, "%c", (int)(key & 0xff));
|
||||
return (out);
|
||||
}
|
||||
|
||||
/*
|
||||
* Special case: display C-@ as C-Space. Could do this below in
|
||||
* the (key >= 0 && key <= 32), but this way we let it be found
|
||||
|
@ -122,7 +122,7 @@ layout_parse(struct window *w, const char *layout)
|
||||
{
|
||||
struct layout_cell *lc, *lcchild;
|
||||
struct window_pane *wp;
|
||||
u_int npanes, ncells, sx, sy;
|
||||
u_int npanes, ncells;
|
||||
u_short csum;
|
||||
|
||||
/* Check validity. */
|
||||
@ -153,8 +153,7 @@ layout_parse(struct window *w, const char *layout)
|
||||
layout_destroy_cell(w, lcchild, &lc);
|
||||
}
|
||||
|
||||
/* Save the old window size and resize to the layout size. */
|
||||
sx = w->sx; sy = w->sy;
|
||||
/* Resize to the layout size. */
|
||||
window_resize(w, lc->sx, lc->sy);
|
||||
|
||||
/* Destroy the old layout and swap to the new. */
|
||||
@ -166,12 +165,9 @@ layout_parse(struct window *w, const char *layout)
|
||||
layout_assign(&wp, lc);
|
||||
|
||||
/* Update pane offsets and sizes. */
|
||||
layout_fix_offsets(lc);
|
||||
layout_fix_offsets(w);
|
||||
layout_fix_panes(w);
|
||||
|
||||
/* Then resize the layout back to the original window size. */
|
||||
layout_resize(w, sx, sy);
|
||||
window_resize(w, sx, sy);
|
||||
recalculate_sizes();
|
||||
|
||||
layout_print_cell(lc, __func__, 0);
|
||||
|
||||
|
@ -158,7 +158,7 @@ layout_set_even(struct window *w, enum layout_type type)
|
||||
layout_spread_cell(w, lc);
|
||||
|
||||
/* Fix cell offsets. */
|
||||
layout_fix_offsets(lc);
|
||||
layout_fix_offsets(w);
|
||||
layout_fix_panes(w);
|
||||
|
||||
layout_print_cell(w->layout_root, __func__, 1);
|
||||
@ -257,7 +257,7 @@ layout_set_main_h(struct window *w)
|
||||
}
|
||||
|
||||
/* Fix cell offsets. */
|
||||
layout_fix_offsets(lc);
|
||||
layout_fix_offsets(w);
|
||||
layout_fix_panes(w);
|
||||
|
||||
layout_print_cell(w->layout_root, __func__, 1);
|
||||
@ -344,7 +344,7 @@ layout_set_main_v(struct window *w)
|
||||
}
|
||||
|
||||
/* Fix cell offsets. */
|
||||
layout_fix_offsets(lc);
|
||||
layout_fix_offsets(w);
|
||||
layout_fix_panes(w);
|
||||
|
||||
layout_print_cell(w->layout_root, __func__, 1);
|
||||
@ -453,7 +453,7 @@ layout_set_tiled(struct window *w)
|
||||
}
|
||||
|
||||
/* Fix cell offsets. */
|
||||
layout_fix_offsets(lc);
|
||||
layout_fix_offsets(w);
|
||||
layout_fix_panes(w);
|
||||
|
||||
layout_print_cell(w->layout_root, __func__, 1);
|
||||
|
141
layout.c
141
layout.c
@ -39,7 +39,6 @@ static int layout_resize_pane_grow(struct window *, struct layout_cell *,
|
||||
enum layout_type, int, int);
|
||||
static int layout_resize_pane_shrink(struct window *, struct layout_cell *,
|
||||
enum layout_type, int);
|
||||
static int layout_need_status(struct layout_cell *, int);
|
||||
static u_int layout_new_pane_size(struct window *, u_int,
|
||||
struct layout_cell *, enum layout_type, u_int, u_int,
|
||||
u_int);
|
||||
@ -199,9 +198,9 @@ layout_make_node(struct layout_cell *lc, enum layout_type type)
|
||||
lc->wp = NULL;
|
||||
}
|
||||
|
||||
/* Fix cell offsets based on their sizes. */
|
||||
void
|
||||
layout_fix_offsets(struct layout_cell *lc)
|
||||
/* Fix cell offsets for a child cell. */
|
||||
static void
|
||||
layout_fix_offsets1(struct layout_cell *lc)
|
||||
{
|
||||
struct layout_cell *lcchild;
|
||||
u_int xoff, yoff;
|
||||
@ -212,7 +211,7 @@ layout_fix_offsets(struct layout_cell *lc)
|
||||
lcchild->xoff = xoff;
|
||||
lcchild->yoff = lc->yoff;
|
||||
if (lcchild->type != LAYOUT_WINDOWPANE)
|
||||
layout_fix_offsets(lcchild);
|
||||
layout_fix_offsets1(lcchild);
|
||||
xoff += lcchild->sx + 1;
|
||||
}
|
||||
} else {
|
||||
@ -221,61 +220,92 @@ layout_fix_offsets(struct layout_cell *lc)
|
||||
lcchild->xoff = lc->xoff;
|
||||
lcchild->yoff = yoff;
|
||||
if (lcchild->type != LAYOUT_WINDOWPANE)
|
||||
layout_fix_offsets(lcchild);
|
||||
layout_fix_offsets1(lcchild);
|
||||
yoff += lcchild->sy + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns 1 if we need to reserve space for the pane status line. This is the
|
||||
* case for the most upper panes only.
|
||||
*/
|
||||
static int
|
||||
layout_need_status(struct layout_cell *lc, int at_top)
|
||||
/* Update cell offsets based on their sizes. */
|
||||
void
|
||||
layout_fix_offsets(struct window *w)
|
||||
{
|
||||
struct layout_cell *first_lc;
|
||||
struct layout_cell *lc = w->layout_root;
|
||||
|
||||
if (lc->parent != NULL) {
|
||||
if (lc->parent->type == LAYOUT_LEFTRIGHT)
|
||||
return (layout_need_status(lc->parent, at_top));
|
||||
lc->xoff = 0;
|
||||
lc->yoff = 0;
|
||||
|
||||
if (at_top)
|
||||
first_lc = TAILQ_FIRST(&lc->parent->cells);
|
||||
else
|
||||
first_lc = TAILQ_LAST(&lc->parent->cells,layout_cells);
|
||||
if (lc == first_lc)
|
||||
return (layout_need_status(lc->parent, at_top));
|
||||
return (0);
|
||||
layout_fix_offsets1(lc);
|
||||
}
|
||||
|
||||
/* Is this a top cell? */
|
||||
static int
|
||||
layout_cell_is_top(struct window *w, struct layout_cell *lc)
|
||||
{
|
||||
struct layout_cell *next;
|
||||
|
||||
while (lc != w->layout_root) {
|
||||
next = lc->parent;
|
||||
if (next->type == LAYOUT_TOPBOTTOM &&
|
||||
lc != TAILQ_FIRST(&next->cells))
|
||||
return (0);
|
||||
lc = next;
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
|
||||
/* Is this a bottom cell? */
|
||||
static int
|
||||
layout_cell_is_bottom(struct window *w, struct layout_cell *lc)
|
||||
{
|
||||
struct layout_cell *next;
|
||||
|
||||
while (lc != w->layout_root) {
|
||||
next = lc->parent;
|
||||
if (next->type == LAYOUT_TOPBOTTOM &&
|
||||
lc != TAILQ_LAST(&next->cells, layout_cells))
|
||||
return (0);
|
||||
lc = next;
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns 1 if we need to add an extra line for the pane status line. This is
|
||||
* the case for the most upper or lower panes only.
|
||||
*/
|
||||
static int
|
||||
layout_add_border(struct window *w, struct layout_cell *lc, int status)
|
||||
{
|
||||
if (status == PANE_STATUS_TOP)
|
||||
return (layout_cell_is_top(w, lc));
|
||||
if (status == PANE_STATUS_BOTTOM)
|
||||
return (layout_cell_is_bottom(w, lc));
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Update pane offsets and sizes based on their cells. */
|
||||
void
|
||||
layout_fix_panes(struct window *w)
|
||||
{
|
||||
struct window_pane *wp;
|
||||
struct layout_cell *lc;
|
||||
int shift, status;
|
||||
int status;
|
||||
|
||||
status = options_get_number(w->options, "pane-border-status");
|
||||
TAILQ_FOREACH(wp, &w->panes, entry) {
|
||||
if ((lc = wp->layout_cell) == NULL)
|
||||
continue;
|
||||
|
||||
if (status != 0)
|
||||
shift = layout_need_status(lc, status == 1);
|
||||
else
|
||||
shift = 0;
|
||||
|
||||
wp->xoff = lc->xoff;
|
||||
wp->yoff = lc->yoff;
|
||||
|
||||
if (shift && status == 1)
|
||||
wp->yoff += 1;
|
||||
|
||||
window_pane_resize(wp, lc->sx, lc->sy - shift);
|
||||
if (layout_add_border(w, lc, status)) {
|
||||
if (status == PANE_STATUS_TOP)
|
||||
wp->yoff++;
|
||||
window_pane_resize(wp, lc->sx, lc->sy - 1);
|
||||
} else
|
||||
window_pane_resize(wp, lc->sx, lc->sy);
|
||||
}
|
||||
}
|
||||
|
||||
@ -312,13 +342,15 @@ layout_resize_check(struct window *w, struct layout_cell *lc,
|
||||
status = options_get_number(w->options, "pane-border-status");
|
||||
if (lc->type == LAYOUT_WINDOWPANE) {
|
||||
/* Space available in this cell only. */
|
||||
minimum = PANE_MINIMUM;
|
||||
if (type == LAYOUT_LEFTRIGHT)
|
||||
if (type == LAYOUT_LEFTRIGHT) {
|
||||
available = lc->sx;
|
||||
else {
|
||||
minimum = PANE_MINIMUM;
|
||||
} else {
|
||||
available = lc->sy;
|
||||
if (status != 0)
|
||||
minimum += layout_need_status(lc, status == 1);
|
||||
if (layout_add_border(w, lc, status))
|
||||
minimum = PANE_MINIMUM + 1;
|
||||
else
|
||||
minimum = PANE_MINIMUM;
|
||||
}
|
||||
if (available > minimum)
|
||||
available -= minimum;
|
||||
@ -507,7 +539,7 @@ layout_resize(struct window *w, u_int sx, u_int sy)
|
||||
layout_resize_adjust(w, lc, LAYOUT_TOPBOTTOM, ychange);
|
||||
|
||||
/* Fix cell offsets. */
|
||||
layout_fix_offsets(lc);
|
||||
layout_fix_offsets(w);
|
||||
layout_fix_panes(w);
|
||||
}
|
||||
|
||||
@ -567,7 +599,7 @@ layout_resize_layout(struct window *w, struct layout_cell *lc,
|
||||
}
|
||||
|
||||
/* Fix cell offsets. */
|
||||
layout_fix_offsets(w->layout_root);
|
||||
layout_fix_offsets(w);
|
||||
layout_fix_panes(w);
|
||||
notify_window("window-layout-changed", w);
|
||||
}
|
||||
@ -861,9 +893,10 @@ layout_split_pane(struct window_pane *wp, enum layout_type type, int size,
|
||||
return (NULL);
|
||||
break;
|
||||
case LAYOUT_TOPBOTTOM:
|
||||
minimum = PANE_MINIMUM * 2 + 1;
|
||||
if (status != 0)
|
||||
minimum += layout_need_status(lc, status == 1);
|
||||
if (layout_add_border(wp->window, lc, status))
|
||||
minimum = PANE_MINIMUM * 2 + 2;
|
||||
else
|
||||
minimum = PANE_MINIMUM * 2 + 1;
|
||||
if (sy < minimum)
|
||||
return (NULL);
|
||||
break;
|
||||
@ -988,7 +1021,7 @@ layout_split_pane(struct window_pane *wp, enum layout_type type, int size,
|
||||
if (full_size) {
|
||||
if (!resize_first)
|
||||
layout_resize_child_cells(wp->window, lc);
|
||||
layout_fix_offsets(wp->window->layout_root);
|
||||
layout_fix_offsets(wp->window);
|
||||
} else
|
||||
layout_make_leaf(lc, wp);
|
||||
|
||||
@ -1006,7 +1039,7 @@ layout_close_pane(struct window_pane *wp)
|
||||
|
||||
/* Fix pane offsets and sizes. */
|
||||
if (w->layout_root != NULL) {
|
||||
layout_fix_offsets(w->layout_root);
|
||||
layout_fix_offsets(w);
|
||||
layout_fix_panes(w);
|
||||
}
|
||||
notify_window("window-layout-changed", w);
|
||||
@ -1021,7 +1054,7 @@ layout_spread_cell(struct window *w, struct layout_cell *parent)
|
||||
|
||||
number = 0;
|
||||
TAILQ_FOREACH (lc, &parent->cells, entry)
|
||||
number++;
|
||||
number++;
|
||||
if (number <= 1)
|
||||
return (0);
|
||||
status = options_get_number(w->options, "pane-border-status");
|
||||
@ -1029,9 +1062,10 @@ layout_spread_cell(struct window *w, struct layout_cell *parent)
|
||||
if (parent->type == LAYOUT_LEFTRIGHT)
|
||||
size = parent->sx;
|
||||
else if (parent->type == LAYOUT_TOPBOTTOM) {
|
||||
size = parent->sy;
|
||||
if (status != 0)
|
||||
size -= layout_need_status(parent, status == 1);
|
||||
if (layout_add_border(w, parent, status))
|
||||
size = parent->sy - 1;
|
||||
else
|
||||
size = parent->sy;
|
||||
} else
|
||||
return (0);
|
||||
if (size < number - 1)
|
||||
@ -1049,9 +1083,10 @@ layout_spread_cell(struct window *w, struct layout_cell *parent)
|
||||
change = each - (int)lc->sx;
|
||||
layout_resize_adjust(w, lc, LAYOUT_LEFTRIGHT, change);
|
||||
} else if (parent->type == LAYOUT_TOPBOTTOM) {
|
||||
this = each;
|
||||
if (status != 0)
|
||||
this += layout_need_status(lc, status == 1);
|
||||
if (layout_add_border(w, lc, status))
|
||||
this = each + 1;
|
||||
else
|
||||
this = each;
|
||||
change = this - (int)lc->sy;
|
||||
layout_resize_adjust(w, lc, LAYOUT_TOPBOTTOM, change);
|
||||
}
|
||||
@ -1073,7 +1108,7 @@ layout_spread_out(struct window_pane *wp)
|
||||
|
||||
do {
|
||||
if (layout_spread_cell(w, parent)) {
|
||||
layout_fix_offsets(parent);
|
||||
layout_fix_offsets(w);
|
||||
layout_fix_panes(w);
|
||||
break;
|
||||
}
|
||||
|
22
menu.c
22
menu.c
@ -161,7 +161,7 @@ menu_free_cb(struct client *c)
|
||||
struct menu_data *md = c->overlay_data;
|
||||
|
||||
if (md->item != NULL)
|
||||
md->item->flags &= ~CMDQ_WAITING;
|
||||
cmdq_continue(md->item);
|
||||
|
||||
if (md->cb != NULL)
|
||||
md->cb(md->menu, UINT_MAX, KEYC_NONE, md->data);
|
||||
@ -206,8 +206,18 @@ menu_key_cb(struct client *c, struct key_event *event)
|
||||
c->flags |= CLIENT_REDRAWOVERLAY;
|
||||
return (0);
|
||||
}
|
||||
for (i = 0; i < (u_int)count; i++) {
|
||||
name = menu->items[i].name;
|
||||
if (name == NULL || *name == '-')
|
||||
continue;
|
||||
if (event->key == menu->items[i].key) {
|
||||
md->choice = i;
|
||||
goto chosen;
|
||||
}
|
||||
}
|
||||
switch (event->key) {
|
||||
case KEYC_UP:
|
||||
case 'k':
|
||||
if (old == -1)
|
||||
old = 0;
|
||||
do {
|
||||
@ -220,6 +230,7 @@ menu_key_cb(struct client *c, struct key_event *event)
|
||||
c->flags |= CLIENT_REDRAWOVERLAY;
|
||||
return (0);
|
||||
case KEYC_DOWN:
|
||||
case 'j':
|
||||
if (old == -1)
|
||||
old = 0;
|
||||
do {
|
||||
@ -239,15 +250,6 @@ menu_key_cb(struct client *c, struct key_event *event)
|
||||
case 'q':
|
||||
return (1);
|
||||
}
|
||||
for (i = 0; i < (u_int)count; i++) {
|
||||
name = menu->items[i].name;
|
||||
if (name == NULL || *name == '-')
|
||||
continue;
|
||||
if (event->key == menu->items[i].key) {
|
||||
md->choice = i;
|
||||
goto chosen;
|
||||
}
|
||||
}
|
||||
return (0);
|
||||
|
||||
chosen:
|
||||
|
@ -480,7 +480,7 @@ mode_tree_add(struct mode_tree_data *mtd, struct mode_tree_item *parent,
|
||||
|
||||
saved = mode_tree_find_item(&mtd->saved, tag);
|
||||
if (saved != NULL) {
|
||||
if (parent == NULL || (parent != NULL && parent->expanded))
|
||||
if (parent == NULL || parent->expanded)
|
||||
mti->tagged = saved->tagged;
|
||||
mti->expanded = saved->expanded;
|
||||
} else if (expanded == -1)
|
||||
@ -933,6 +933,7 @@ mode_tree_key(struct mode_tree_data *mtd, struct client *c, key_code *key,
|
||||
case '\016': /* C-n */
|
||||
mode_tree_down(mtd, 1);
|
||||
break;
|
||||
case 'g':
|
||||
case KEYC_PPAGE:
|
||||
case '\002': /* C-b */
|
||||
for (i = 0; i < mtd->height; i++) {
|
||||
@ -941,6 +942,7 @@ mode_tree_key(struct mode_tree_data *mtd, struct client *c, key_code *key,
|
||||
mode_tree_up(mtd, 1);
|
||||
}
|
||||
break;
|
||||
case 'G':
|
||||
case KEYC_NPAGE:
|
||||
case '\006': /* C-f */
|
||||
for (i = 0; i < mtd->height; i++) {
|
||||
@ -1019,6 +1021,8 @@ mode_tree_key(struct mode_tree_data *mtd, struct client *c, key_code *key,
|
||||
mode_tree_build(mtd);
|
||||
}
|
||||
break;
|
||||
case '?':
|
||||
case '/':
|
||||
case '\023': /* C-s */
|
||||
mtd->references++;
|
||||
status_prompt_set(c, "(search) ", "",
|
||||
|
@ -562,13 +562,13 @@ const struct options_table_entry options_table[] = {
|
||||
|
||||
{ .name = "allow-rename",
|
||||
.type = OPTIONS_TABLE_FLAG,
|
||||
.scope = OPTIONS_TABLE_WINDOW,
|
||||
.scope = OPTIONS_TABLE_WINDOW|OPTIONS_TABLE_PANE,
|
||||
.default_num = 0
|
||||
},
|
||||
|
||||
{ .name = "alternate-screen",
|
||||
.type = OPTIONS_TABLE_FLAG,
|
||||
.scope = OPTIONS_TABLE_WINDOW,
|
||||
.scope = OPTIONS_TABLE_WINDOW|OPTIONS_TABLE_PANE,
|
||||
.default_num = 1
|
||||
},
|
||||
|
||||
@ -688,7 +688,7 @@ const struct options_table_entry options_table[] = {
|
||||
.type = OPTIONS_TABLE_CHOICE,
|
||||
.scope = OPTIONS_TABLE_WINDOW,
|
||||
.choices = options_table_pane_status_list,
|
||||
.default_num = 0
|
||||
.default_num = PANE_STATUS_OFF
|
||||
},
|
||||
|
||||
{ .name = "pane-border-style",
|
||||
@ -699,7 +699,7 @@ const struct options_table_entry options_table[] = {
|
||||
|
||||
{ .name = "remain-on-exit",
|
||||
.type = OPTIONS_TABLE_FLAG,
|
||||
.scope = OPTIONS_TABLE_WINDOW,
|
||||
.scope = OPTIONS_TABLE_WINDOW|OPTIONS_TABLE_PANE,
|
||||
.default_num = 0
|
||||
},
|
||||
|
||||
@ -711,7 +711,7 @@ const struct options_table_entry options_table[] = {
|
||||
|
||||
{ .name = "window-active-style",
|
||||
.type = OPTIONS_TABLE_STYLE,
|
||||
.scope = OPTIONS_TABLE_WINDOW,
|
||||
.scope = OPTIONS_TABLE_WINDOW|OPTIONS_TABLE_PANE,
|
||||
.default_str = "default"
|
||||
},
|
||||
|
||||
@ -724,7 +724,7 @@ const struct options_table_entry options_table[] = {
|
||||
|
||||
{ .name = "window-style",
|
||||
.type = OPTIONS_TABLE_STYLE,
|
||||
.scope = OPTIONS_TABLE_WINDOW,
|
||||
.scope = OPTIONS_TABLE_WINDOW|OPTIONS_TABLE_PANE,
|
||||
.default_str = "default"
|
||||
},
|
||||
|
||||
|
105
options.c
105
options.c
@ -100,7 +100,7 @@ options_parent_table_entry(struct options *oo, const char *s)
|
||||
|
||||
if (oo->parent == NULL)
|
||||
fatalx("no parent options for %s", s);
|
||||
o = options_get_only(oo->parent, s);
|
||||
o = options_get(oo->parent, s);
|
||||
if (o == NULL)
|
||||
fatalx("%s not in parent options", s);
|
||||
return (o->tableentry);
|
||||
@ -178,6 +178,12 @@ options_free(struct options *oo)
|
||||
free(oo);
|
||||
}
|
||||
|
||||
void
|
||||
options_set_parent(struct options *oo, struct options *parent)
|
||||
{
|
||||
oo->parent = parent;
|
||||
}
|
||||
|
||||
struct options_entry *
|
||||
options_first(struct options *oo)
|
||||
{
|
||||
@ -365,7 +371,8 @@ options_array_set(struct options_entry *o, u_int idx, const char *value,
|
||||
pr = cmd_parse_from_string(value, NULL);
|
||||
switch (pr->status) {
|
||||
case CMD_PARSE_EMPTY:
|
||||
*cause = xstrdup("empty command");
|
||||
if (cause != NULL)
|
||||
*cause = xstrdup("empty command");
|
||||
return (-1);
|
||||
case CMD_PARSE_ERROR:
|
||||
if (cause != NULL)
|
||||
@ -544,7 +551,7 @@ options_parse_get(struct options *oo, const char *s, int *idx, int only)
|
||||
}
|
||||
|
||||
char *
|
||||
options_match(const char *s, int *idx, int* ambiguous)
|
||||
options_match(const char *s, int *idx, int *ambiguous)
|
||||
{
|
||||
const struct options_table_entry *oe, *found;
|
||||
char *name;
|
||||
@ -724,20 +731,102 @@ options_set_style(struct options *oo, const char *name, int append,
|
||||
return (o);
|
||||
}
|
||||
|
||||
enum options_table_scope
|
||||
int
|
||||
options_scope_from_name(struct args *args, int window,
|
||||
const char *name, struct cmd_find_state *fs, struct options **oo,
|
||||
char **cause)
|
||||
{
|
||||
struct session *s = fs->s;
|
||||
struct winlink *wl = fs->wl;
|
||||
struct window_pane *wp = fs->wp;
|
||||
const char *target = args_get(args, 't');
|
||||
const struct options_table_entry *oe;
|
||||
int scope = OPTIONS_TABLE_NONE;
|
||||
|
||||
if (*name == '@')
|
||||
return (options_scope_from_flags(args, window, fs, oo, cause));
|
||||
|
||||
for (oe = options_table; oe->name != NULL; oe++) {
|
||||
if (strcmp(oe->name, name) == 0)
|
||||
break;
|
||||
}
|
||||
if (oe->name == NULL) {
|
||||
xasprintf(cause, "unknown option: %s", name);
|
||||
return (OPTIONS_TABLE_NONE);
|
||||
}
|
||||
switch (oe->scope) {
|
||||
case OPTIONS_TABLE_SERVER:
|
||||
*oo = global_options;
|
||||
scope = OPTIONS_TABLE_SERVER;
|
||||
break;
|
||||
case OPTIONS_TABLE_SESSION:
|
||||
if (args_has(args, 'g')) {
|
||||
*oo = global_s_options;
|
||||
scope = OPTIONS_TABLE_SESSION;
|
||||
} else if (s == NULL && target != NULL)
|
||||
xasprintf(cause, "no such session: %s", target);
|
||||
else if (s == NULL)
|
||||
xasprintf(cause, "no current session");
|
||||
else {
|
||||
*oo = s->options;
|
||||
scope = OPTIONS_TABLE_SESSION;
|
||||
}
|
||||
break;
|
||||
case OPTIONS_TABLE_WINDOW|OPTIONS_TABLE_PANE:
|
||||
if (args_has(args, 'p')) {
|
||||
if (wp == NULL && target != NULL)
|
||||
xasprintf(cause, "no such pane: %s", target);
|
||||
else if (wp == NULL)
|
||||
xasprintf(cause, "no current pane");
|
||||
else {
|
||||
*oo = wp->options;
|
||||
scope = OPTIONS_TABLE_PANE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
/* FALLTHROUGH */
|
||||
case OPTIONS_TABLE_WINDOW:
|
||||
if (args_has(args, 'g')) {
|
||||
*oo = global_w_options;
|
||||
scope = OPTIONS_TABLE_WINDOW;
|
||||
} else if (wl == NULL && target != NULL)
|
||||
xasprintf(cause, "no such window: %s", target);
|
||||
else if (wl == NULL)
|
||||
xasprintf(cause, "no current window");
|
||||
else {
|
||||
*oo = wl->window->options;
|
||||
scope = OPTIONS_TABLE_WINDOW;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return (scope);
|
||||
}
|
||||
|
||||
int
|
||||
options_scope_from_flags(struct args *args, int window,
|
||||
struct cmd_find_state *fs, struct options **oo, char **cause)
|
||||
{
|
||||
struct session *s = fs->s;
|
||||
struct winlink *wl = fs->wl;
|
||||
const char *target= args_get(args, 't');
|
||||
struct session *s = fs->s;
|
||||
struct winlink *wl = fs->wl;
|
||||
struct window_pane *wp = fs->wp;
|
||||
const char *target = args_get(args, 't');
|
||||
|
||||
if (args_has(args, 's')) {
|
||||
*oo = global_options;
|
||||
return (OPTIONS_TABLE_SERVER);
|
||||
}
|
||||
|
||||
if (window || args_has(args, 'w')) {
|
||||
if (args_has(args, 'p')) {
|
||||
if (wp == NULL) {
|
||||
if (target != NULL)
|
||||
xasprintf(cause, "no such pane: %s", target);
|
||||
else
|
||||
xasprintf(cause, "no current pane");
|
||||
return (OPTIONS_TABLE_NONE);
|
||||
}
|
||||
*oo = wp->options;
|
||||
return (OPTIONS_TABLE_PANE);
|
||||
} else if (window || args_has(args, 'w')) {
|
||||
if (args_has(args, 'g')) {
|
||||
*oo = global_w_options;
|
||||
return (OPTIONS_TABLE_WINDOW);
|
||||
|
@ -133,13 +133,27 @@ char *
|
||||
osdep_get_cwd(int fd)
|
||||
{
|
||||
static char target[PATH_MAX + 1];
|
||||
char *path;
|
||||
pid_t pgrp;
|
||||
#ifdef KERN_PROC_CWD
|
||||
int mib[4];
|
||||
size_t len;
|
||||
#else
|
||||
char *path;
|
||||
ssize_t n;
|
||||
#endif
|
||||
|
||||
if ((pgrp = tcgetpgrp(fd)) == -1)
|
||||
return (NULL);
|
||||
|
||||
#ifdef KERN_PROC_CWD
|
||||
mib[0] = CTL_KERN;
|
||||
mib[1] = KERN_PROC_ARGS;
|
||||
mib[2] = pgrp;
|
||||
mib[3] = KERN_PROC_CWD;
|
||||
len = sizeof(target);
|
||||
if (sysctl(mib, __arraycount(mib), target, &len, NULL, 0) == 0)
|
||||
return (target);
|
||||
#else
|
||||
xasprintf(&path, "/proc/%lld/cwd", (long long) pgrp);
|
||||
n = readlink(path, target, sizeof(target) - 1);
|
||||
free(path);
|
||||
@ -147,6 +161,7 @@ osdep_get_cwd(int fd)
|
||||
target[n] = '\0';
|
||||
return (target);
|
||||
}
|
||||
#endif
|
||||
|
||||
return (NULL);
|
||||
}
|
||||
|
@ -1,7 +1,5 @@
|
||||
#!/bin/sh
|
||||
|
||||
# new-session without clients should be the right size
|
||||
|
||||
PATH=/bin:/usr/bin
|
||||
TERM=screen
|
||||
|
||||
@ -19,6 +17,7 @@ EOF
|
||||
$TMUX -f$TMP start </dev/null || exit 1
|
||||
sleep 1
|
||||
$TMUX lsw -aF '#{session_name},#{window_name}'|sort >$TMP || exit 1
|
||||
$TMUX kill-server 2>/dev/null
|
||||
cat <<EOF|cmp -s $TMP - || exit 1
|
||||
bar,bar0
|
||||
bar,bar1
|
||||
@ -27,7 +26,6 @@ foo,foo0
|
||||
foo,foo1
|
||||
foo,foo2
|
||||
EOF
|
||||
$TMUX kill-server 2>/dev/null
|
||||
|
||||
cat <<EOF >$TMP
|
||||
new -sfoo -nfoo0
|
||||
@ -40,6 +38,7 @@ EOF
|
||||
$TMUX -f$TMP start </dev/null || exit 1
|
||||
sleep 1
|
||||
$TMUX lsw -aF '#{session_name},#{window_name}'|sort >$TMP || exit 1
|
||||
$TMUX kill-server 2>/dev/null
|
||||
cat <<EOF|cmp -s $TMP - || exit 1
|
||||
bar,bar0
|
||||
bar,bar1
|
||||
@ -48,6 +47,5 @@ foo,foo0
|
||||
foo,foo1
|
||||
foo,foo2
|
||||
EOF
|
||||
$TMUX kill-server 2>/dev/null
|
||||
|
||||
exit 0
|
||||
|
8
regress/conf/21867280ff7e99631046f9cc669b80d2.conf
Normal file
8
regress/conf/21867280ff7e99631046f9cc669b80d2.conf
Normal file
@ -0,0 +1,8 @@
|
||||
%if #{l:1}
|
||||
set -g status-style fg=cyan,bg='#001040'
|
||||
%elif #{l:1}
|
||||
set -g status-style fg=white,bg='#400040'
|
||||
%else
|
||||
set -g status-style fg=white,bg='#800000'
|
||||
%endif
|
||||
bind ^X last-window
|
93
regress/conf/99749670b62bcb99a9b2e3d59708e357.conf
Normal file
93
regress/conf/99749670b62bcb99a9b2e3d59708e357.conf
Normal file
@ -0,0 +1,93 @@
|
||||
# -----------------------------------------------------------------------------
|
||||
# This config is targeted for tmux 2.1+ and should be placed in $HOME.
|
||||
#
|
||||
# Read the "Plugin Manager" section (bottom) before trying to use this config!
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Global options
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
# Set a new prefix / leader key.
|
||||
set -g prefix `
|
||||
bind ` send-prefix
|
||||
|
||||
# Allow opening multiple terminals to view the same session at different sizes.
|
||||
setw -g aggressive-resize on
|
||||
|
||||
# Remove delay when switching between Vim modes.
|
||||
set -s escape-time 0
|
||||
|
||||
# Allow Vim's FocusGained to work when your terminal gains focus.
|
||||
# Requires Vim plugin: https://github.com/tmux-plugins/vim-tmux-focus-events
|
||||
set -g focus-events on
|
||||
|
||||
# Add a bit more scroll history in the buffer.
|
||||
set -g history-limit 50000
|
||||
|
||||
# Enable color support inside of tmux.
|
||||
set -g default-terminal "screen-256color"
|
||||
|
||||
# Ensure window titles get renamed automatically.
|
||||
setw -g automatic-rename
|
||||
|
||||
# Start windows and panes index at 1, not 0.
|
||||
set -g base-index 1
|
||||
setw -g pane-base-index 1
|
||||
|
||||
# Enable full mouse support.
|
||||
set -g mouse on
|
||||
|
||||
# Status bar optimized for Gruvbox.
|
||||
set -g status-fg colour244
|
||||
set -g status-bg default
|
||||
set -g status-left ''
|
||||
set -g status-right-length 0
|
||||
#set -g status-right-length 20
|
||||
#set -g status-right '%a %Y-%m-%d %H:%M'
|
||||
|
||||
set -g pane-border-fg default
|
||||
set -g pane-border-bg default
|
||||
set -g pane-active-border-fg colour250
|
||||
set -g pane-active-border-bg default
|
||||
|
||||
set-window-option -g window-status-current-attr bold
|
||||
set-window-option -g window-status-current-fg colour223
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Key bindings
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
# Unbind default keys
|
||||
unbind C-b
|
||||
unbind '"'
|
||||
unbind %
|
||||
|
||||
# Reload the tmux config.
|
||||
bind-key r source-file ~/.tmux.conf
|
||||
|
||||
# Split panes.
|
||||
bind-key h split-window -v
|
||||
bind-key v split-window -h
|
||||
|
||||
# Move around panes with ALT + arrow keys.
|
||||
bind-key -n M-Up select-pane -U
|
||||
bind-key -n M-Left select-pane -L
|
||||
bind-key -n M-Down select-pane -D
|
||||
bind-key -n M-Right select-pane -R
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Plugin Manager - https://github.com/tmux-plugins/tpm
|
||||
# In order to use the plugins below you need to install TPM and the plugins.
|
||||
# Step 1) git clone https://github.com/tmux-plugins/tpm ~/.tmux/plugins/tpm
|
||||
# Step 2) Reload tmux if it's already started with `r
|
||||
# Step 3) Launch tmux and hit `I (capital i) to fetch any plugins
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
# List of plugins.
|
||||
set -g @plugin 'tmux-plugins/tpm'
|
||||
set -g @plugin 'tmux-plugins/tmux-resurrect'
|
||||
set -g @plugin 'tmux-plugins/tmux-yank'
|
||||
|
||||
# Initialize TPM (keep this line at the very bottom of your tmux.conf).
|
||||
run -b '~/.tmux/plugins/tpm/tpm'
|
29
regress/xenl-terminal.sh
Normal file
29
regress/xenl-terminal.sh
Normal file
@ -0,0 +1,29 @@
|
||||
#!/bin/sh
|
||||
|
||||
PATH=/bin:/usr/bin
|
||||
TERM=screen
|
||||
|
||||
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
|
||||
TMUX="$TEST_TMUX -Ltest"
|
||||
$TMUX kill-server 2>/dev/null
|
||||
TMUX2="$TEST_TMUX -Ltest2"
|
||||
$TMUX2 kill-server 2>/dev/null
|
||||
|
||||
TMP=$(mktemp)
|
||||
trap "rm -f $TMP" 0 1 15
|
||||
|
||||
$TMUX2 -f/dev/null new -d || exit 1
|
||||
$TMUX2 set -as terminal-overrides ',*:xenl@' || exit 1
|
||||
$TMUX2 set -g status-right 'RRR' || exit 1
|
||||
$TMUX2 set -g status-left 'LLL' || exit 1
|
||||
$TMUX2 set -g window-status-current-format 'WWW' || exit 1
|
||||
$TMUX -f/dev/null new -x20 -y2 -d "$TMUX2 attach" || exit 1
|
||||
sleep 1
|
||||
$TMUX capturep -p|tail -1 >$TMP || exit 1
|
||||
$TMUX kill-server 2>/dev/null
|
||||
$TMUX2 kill-server 2>/dev/null
|
||||
cat <<EOF|cmp -s $TMP - || exit 1
|
||||
LLLWWW RR
|
||||
EOF
|
||||
|
||||
exit 0
|
115
regsub.c
Normal file
115
regsub.c
Normal file
@ -0,0 +1,115 @@
|
||||
/* $OpenBSD$ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2019 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||
*
|
||||
* 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 <regex.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "tmux.h"
|
||||
|
||||
static void
|
||||
regsub_copy(char **buf, size_t *len, const char *text, size_t start,
|
||||
size_t end)
|
||||
{
|
||||
size_t add = end - start;
|
||||
|
||||
*buf = xrealloc(*buf, (*len) + add + 1);
|
||||
memcpy((*buf) + *len, text + start, add);
|
||||
(*len) += add;
|
||||
}
|
||||
|
||||
static void
|
||||
regsub_expand(char **buf, size_t *len, const char *with, const char *text,
|
||||
regmatch_t *m, u_int n)
|
||||
{
|
||||
const char *cp;
|
||||
u_int i;
|
||||
|
||||
for (cp = with; *cp != '\0'; cp++) {
|
||||
if (*cp == '\\') {
|
||||
cp++;
|
||||
if (*cp >= '0' && *cp <= '9') {
|
||||
i = *cp - '0';
|
||||
if (i < n && m[i].rm_so != m[i].rm_eo) {
|
||||
regsub_copy(buf, len, text, m[i].rm_so,
|
||||
m[i].rm_eo);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
*buf = xrealloc(*buf, (*len) + 2);
|
||||
(*buf)[(*len)++] = *cp;
|
||||
}
|
||||
}
|
||||
|
||||
char *
|
||||
regsub(const char *pattern, const char *with, const char *text, int flags)
|
||||
{
|
||||
regex_t r;
|
||||
regmatch_t m[10];
|
||||
ssize_t start, end, last, len = 0;
|
||||
int empty = 0;
|
||||
char *buf = NULL;
|
||||
|
||||
if (*text == '\0')
|
||||
return (xstrdup(""));
|
||||
if (regcomp(&r, pattern, flags) != 0)
|
||||
return (NULL);
|
||||
|
||||
start = 0;
|
||||
last = 0;
|
||||
end = strlen(text);
|
||||
|
||||
while (start <= end) {
|
||||
m[0].rm_so = start;
|
||||
m[0].rm_eo = end;
|
||||
|
||||
if (regexec(&r, text, nitems(m), m, REG_STARTEND) != 0) {
|
||||
regsub_copy(&buf, &len, text, start, end);
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Append any text not part of this match (from the end of the
|
||||
* last match).
|
||||
*/
|
||||
regsub_copy(&buf, &len, text, last, m[0].rm_so);
|
||||
|
||||
/*
|
||||
* If the last match was empty and this one isn't (it is either
|
||||
* later or has matched text), expand this match. If it is
|
||||
* empty, move on one character and try again from there.
|
||||
*/
|
||||
if (empty || m[0].rm_so != last || m[0].rm_so != m[0].rm_eo) {
|
||||
regsub_expand(&buf, &len, with, text, m, nitems(m));
|
||||
|
||||
last = m[0].rm_eo;
|
||||
start = m[0].rm_eo;
|
||||
empty = 0;
|
||||
} else {
|
||||
last = m[0].rm_eo;
|
||||
start = m[0].rm_eo + 1;
|
||||
empty = 1;
|
||||
}
|
||||
}
|
||||
buf[len] = '\0';
|
||||
|
||||
regfree(&r);
|
||||
return (buf);
|
||||
}
|
@ -45,10 +45,6 @@ static void screen_redraw_draw_pane(struct screen_redraw_ctx *,
|
||||
|
||||
#define CELL_BORDERS " xqlkmjwvtun~"
|
||||
|
||||
#define CELL_STATUS_OFF 0
|
||||
#define CELL_STATUS_TOP 1
|
||||
#define CELL_STATUS_BOTTOM 2
|
||||
|
||||
/* Check if cell is on the border of a particular pane. */
|
||||
static int
|
||||
screen_redraw_cell_border1(struct window_pane *wp, u_int px, u_int py)
|
||||
@ -112,12 +108,12 @@ screen_redraw_check_cell(struct client *c, u_int px, u_int py, int pane_status,
|
||||
if (px > w->sx || py > w->sy)
|
||||
return (CELL_OUTSIDE);
|
||||
|
||||
if (pane_status != CELL_STATUS_OFF) {
|
||||
if (pane_status != PANE_STATUS_OFF) {
|
||||
TAILQ_FOREACH(wp, &w->panes, entry) {
|
||||
if (!window_pane_visible(wp))
|
||||
continue;
|
||||
|
||||
if (pane_status == CELL_STATUS_TOP)
|
||||
if (pane_status == PANE_STATUS_TOP)
|
||||
line = wp->yoff - 1;
|
||||
else
|
||||
line = wp->yoff + wp->sy;
|
||||
@ -153,7 +149,7 @@ screen_redraw_check_cell(struct client *c, u_int px, u_int py, int pane_status,
|
||||
borders |= 8;
|
||||
if (px <= w->sx && screen_redraw_cell_border(c, px + 1, py))
|
||||
borders |= 4;
|
||||
if (pane_status == CELL_STATUS_TOP) {
|
||||
if (pane_status == PANE_STATUS_TOP) {
|
||||
if (py != 0 && screen_redraw_cell_border(c, px, py - 1))
|
||||
borders |= 2;
|
||||
} else {
|
||||
@ -208,9 +204,9 @@ screen_redraw_check_is(u_int px, u_int py, int type, int pane_status,
|
||||
border = screen_redraw_cell_border1(wantwp, px, py);
|
||||
if (border == 0 || border == -1)
|
||||
return (0);
|
||||
if (pane_status == CELL_STATUS_TOP && border == 4)
|
||||
if (pane_status == PANE_STATUS_TOP && border == 4)
|
||||
return (0);
|
||||
if (pane_status == CELL_STATUS_BOTTOM && border == 3)
|
||||
if (pane_status == PANE_STATUS_BOTTOM && border == 3)
|
||||
return (0);
|
||||
|
||||
/* If there are more than two panes, that's enough. */
|
||||
@ -222,7 +218,7 @@ screen_redraw_check_is(u_int px, u_int py, int type, int pane_status,
|
||||
return (1);
|
||||
|
||||
/* With status lines mark the entire line. */
|
||||
if (pane_status != CELL_STATUS_OFF)
|
||||
if (pane_status != PANE_STATUS_OFF)
|
||||
return (1);
|
||||
|
||||
/* Check if the pane covers the whole width. */
|
||||
@ -270,7 +266,7 @@ screen_redraw_make_pane_status(struct client *c, struct window *w,
|
||||
|
||||
fmt = options_get_string(w->options, "pane-border-format");
|
||||
|
||||
ft = format_create(c, NULL, FORMAT_PANE|wp->id, 0);
|
||||
ft = format_create(c, NULL, FORMAT_PANE|wp->id, FORMAT_STATUS);
|
||||
format_defaults(ft, c, NULL, NULL, wp);
|
||||
|
||||
expanded = format_expand_time(ft, fmt);
|
||||
@ -324,7 +320,7 @@ screen_redraw_draw_pane_status(struct screen_redraw_ctx *ctx)
|
||||
s = &wp->status_screen;
|
||||
|
||||
size = wp->status_size;
|
||||
if (ctx->pane_status == CELL_STATUS_TOP)
|
||||
if (ctx->pane_status == PANE_STATUS_TOP)
|
||||
yoff = wp->yoff - 1;
|
||||
else
|
||||
yoff = wp->yoff + wp->sy;
|
||||
@ -386,7 +382,7 @@ screen_redraw_update(struct client *c, int flags)
|
||||
if (c->overlay_draw != NULL)
|
||||
flags |= CLIENT_REDRAWOVERLAY;
|
||||
|
||||
if (options_get_number(wo, "pane-border-status") != CELL_STATUS_OFF) {
|
||||
if (options_get_number(wo, "pane-border-status") != PANE_STATUS_OFF) {
|
||||
redraw = 0;
|
||||
TAILQ_FOREACH(wp, &w->panes, entry) {
|
||||
if (screen_redraw_make_pane_status(c, w, wp))
|
||||
@ -441,7 +437,7 @@ screen_redraw_screen(struct client *c)
|
||||
screen_redraw_set_context(c, &ctx);
|
||||
|
||||
if (flags & (CLIENT_REDRAWWINDOW|CLIENT_REDRAWBORDERS)) {
|
||||
if (ctx.pane_status != CELL_STATUS_OFF)
|
||||
if (ctx.pane_status != PANE_STATUS_OFF)
|
||||
screen_redraw_draw_pane_status(&ctx);
|
||||
screen_redraw_draw_borders(&ctx);
|
||||
}
|
||||
|
@ -36,7 +36,7 @@ static const struct grid_cell *screen_write_combine(struct screen_write_ctx *,
|
||||
const struct utf8_data *, u_int *);
|
||||
|
||||
static const struct grid_cell screen_write_pad_cell = {
|
||||
GRID_FLAG_PADDING, 0, 8, 8, { { 0 }, 0, 0, 0 }
|
||||
{ { 0 }, 0, 0, 0 }, 0, GRID_FLAG_PADDING, 0, 8, 8
|
||||
};
|
||||
|
||||
struct screen_write_collect_item {
|
||||
@ -1169,11 +1169,7 @@ screen_write_clearscreen(struct screen_write_ctx *ctx, u_int bg)
|
||||
void
|
||||
screen_write_clearhistory(struct screen_write_ctx *ctx)
|
||||
{
|
||||
struct screen *s = ctx->s;
|
||||
struct grid *gd = s->grid;
|
||||
|
||||
grid_move_lines(gd, 0, gd->hsize, gd->sy, 8);
|
||||
gd->hscrolled = gd->hsize = 0;
|
||||
grid_clear_history(ctx->s->grid);
|
||||
}
|
||||
|
||||
/* Clear a collected line. */
|
||||
|
@ -522,9 +522,10 @@ have_event:
|
||||
|
||||
/* Is this on the status line? */
|
||||
m->statusat = status_at_line(c);
|
||||
m->statuslines = status_line_size(c);
|
||||
if (m->statusat != -1 &&
|
||||
y >= (u_int)m->statusat &&
|
||||
y < m->statusat + status_line_size(c)) {
|
||||
y < m->statusat + m->statuslines) {
|
||||
sr = status_get_range(c, x, y - m->statusat);
|
||||
if (sr == NULL) {
|
||||
where = STATUS_DEFAULT;
|
||||
@ -553,8 +554,8 @@ have_event:
|
||||
/* Not on status line. Adjust position and check for border or pane. */
|
||||
if (where == NOWHERE) {
|
||||
px = x;
|
||||
if (m->statusat == 0 && y > 0)
|
||||
py = y - 1;
|
||||
if (m->statusat == 0 && y >= m->statuslines)
|
||||
py = y - m->statuslines;
|
||||
else if (m->statusat > 0 && y >= (u_int)m->statusat)
|
||||
py = m->statusat - 1;
|
||||
else
|
||||
@ -1024,16 +1025,6 @@ server_client_key_callback(struct cmdq_item *item, void *data)
|
||||
fatal("gettimeofday failed");
|
||||
session_update_activity(s, &c->activity_time);
|
||||
|
||||
/* Handle status line. */
|
||||
if (~c->flags & CLIENT_READONLY)
|
||||
status_message_clear(c);
|
||||
if (c->prompt_string != NULL) {
|
||||
if (c->flags & CLIENT_READONLY)
|
||||
goto out;
|
||||
if (status_prompt_key(c, key) == 0)
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Check for mouse keys. */
|
||||
m->valid = 0;
|
||||
if (key == KEYC_MOUSE) {
|
||||
@ -1214,17 +1205,26 @@ server_client_handle_key(struct client *c, struct key_event *event)
|
||||
return (0);
|
||||
|
||||
/*
|
||||
* Key presses in overlay mode are a special case. The queue might be
|
||||
* blocked so they need to be processed immediately rather than queued.
|
||||
* Key presses in overlay mode and the command prompt are a special
|
||||
* case. The queue might be blocked so they need to be processed
|
||||
* immediately rather than queued.
|
||||
*/
|
||||
if ((~c->flags & CLIENT_READONLY) && c->overlay_key != NULL) {
|
||||
switch (c->overlay_key(c, event)) {
|
||||
case 0:
|
||||
return (0);
|
||||
case 1:
|
||||
server_client_clear_overlay(c);
|
||||
return (0);
|
||||
if (~c->flags & CLIENT_READONLY) {
|
||||
status_message_clear(c);
|
||||
if (c->prompt_string != NULL) {
|
||||
if (status_prompt_key(c, event->key) == 0)
|
||||
return (0);
|
||||
}
|
||||
if (c->overlay_key != NULL) {
|
||||
switch (c->overlay_key(c, event)) {
|
||||
case 0:
|
||||
return (0);
|
||||
case 1:
|
||||
server_client_clear_overlay(c);
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
server_client_clear_overlay(c);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1243,6 +1243,8 @@ server_client_loop(void)
|
||||
struct client *c;
|
||||
struct window *w;
|
||||
struct window_pane *wp;
|
||||
struct winlink *wl;
|
||||
struct session *s;
|
||||
int focus;
|
||||
|
||||
TAILQ_FOREACH(c, &clients, entry) {
|
||||
@ -1259,11 +1261,17 @@ server_client_loop(void)
|
||||
*/
|
||||
focus = options_get_number(global_options, "focus-events");
|
||||
RB_FOREACH(w, windows, &windows) {
|
||||
TAILQ_FOREACH(wl, &w->winlinks, wentry) {
|
||||
s = wl->session;
|
||||
if (s->attached != 0 && s->curw == wl)
|
||||
break;
|
||||
}
|
||||
TAILQ_FOREACH(wp, &w->panes, entry) {
|
||||
if (wp->fd != -1) {
|
||||
if (focus)
|
||||
server_client_check_focus(wp);
|
||||
server_client_check_resize(wp);
|
||||
if (wl != NULL)
|
||||
server_client_check_resize(wp);
|
||||
}
|
||||
wp->flags &= ~PANE_REDRAW;
|
||||
}
|
||||
@ -1525,7 +1533,9 @@ server_client_click_timer(__unused int fd, __unused short events, void *data)
|
||||
static void
|
||||
server_client_check_exit(struct client *c)
|
||||
{
|
||||
if (!(c->flags & CLIENT_EXIT))
|
||||
if (~c->flags & CLIENT_EXIT)
|
||||
return;
|
||||
if (c->flags & CLIENT_EXITED)
|
||||
return;
|
||||
|
||||
if (EVBUFFER_LENGTH(c->stdin_data) != 0)
|
||||
@ -1538,7 +1548,7 @@ server_client_check_exit(struct client *c)
|
||||
if (c->flags & CLIENT_ATTACHED)
|
||||
notify_client("client-detached", c);
|
||||
proc_send(c->peer, MSG_EXIT, -1, &c->retval, sizeof c->retval);
|
||||
c->flags &= ~CLIENT_EXIT;
|
||||
c->flags |= CLIENT_EXITED;
|
||||
}
|
||||
|
||||
/* Redraw timer callback. */
|
||||
@ -1943,26 +1953,29 @@ server_client_dispatch_identify(struct client *c, struct imsg *imsg)
|
||||
|
||||
close(c->fd);
|
||||
c->fd = -1;
|
||||
|
||||
return;
|
||||
} else if (c->fd != -1) {
|
||||
if (tty_init(&c->tty, c, c->fd, c->term) != 0) {
|
||||
close(c->fd);
|
||||
c->fd = -1;
|
||||
} else {
|
||||
if (c->flags & CLIENT_UTF8)
|
||||
c->tty.flags |= TTY_UTF8;
|
||||
if (c->flags & CLIENT_256COLOURS)
|
||||
c->tty.term_flags |= TERM_256COLOURS;
|
||||
tty_resize(&c->tty);
|
||||
c->flags |= CLIENT_TERMINAL;
|
||||
}
|
||||
}
|
||||
|
||||
if (c->fd == -1)
|
||||
return;
|
||||
if (tty_init(&c->tty, c, c->fd, c->term) != 0) {
|
||||
close(c->fd);
|
||||
c->fd = -1;
|
||||
return;
|
||||
}
|
||||
if (c->flags & CLIENT_UTF8)
|
||||
c->tty.flags |= TTY_UTF8;
|
||||
if (c->flags & CLIENT_256COLOURS)
|
||||
c->tty.term_flags |= TERM_256COLOURS;
|
||||
|
||||
tty_resize(&c->tty);
|
||||
|
||||
if (!(c->flags & CLIENT_CONTROL))
|
||||
c->flags |= CLIENT_TERMINAL;
|
||||
/*
|
||||
* If this is the first client that has finished identifying, load
|
||||
* configuration files.
|
||||
*/
|
||||
if ((~c->flags & CLIENT_EXIT) &&
|
||||
!cfg_finished &&
|
||||
c == TAILQ_FIRST(&clients) &&
|
||||
TAILQ_NEXT(c, entry) == NULL)
|
||||
start_cfg();
|
||||
}
|
||||
|
||||
/* Handle shell message. */
|
||||
|
@ -308,7 +308,7 @@ server_destroy_pane(struct window_pane *wp, int notify)
|
||||
wp->fd = -1;
|
||||
}
|
||||
|
||||
if (options_get_number(w->options, "remain-on-exit")) {
|
||||
if (options_get_number(wp->options, "remain-on-exit")) {
|
||||
if (~wp->flags & PANE_STATUSREADY)
|
||||
return;
|
||||
|
||||
|
7
server.c
7
server.c
@ -43,7 +43,7 @@
|
||||
struct clients clients;
|
||||
|
||||
struct tmuxproc *server_proc;
|
||||
static int server_fd;
|
||||
static int server_fd = -1;
|
||||
static int server_exit;
|
||||
static struct event server_ev_accept;
|
||||
|
||||
@ -209,9 +209,7 @@ server_start(struct tmuxproc *client, struct event_base *base, int lockfd,
|
||||
c->flags |= CLIENT_EXIT;
|
||||
}
|
||||
|
||||
start_cfg();
|
||||
server_add_accept(0);
|
||||
|
||||
proc_loop(server_proc, server_loop);
|
||||
|
||||
job_kill_all();
|
||||
@ -363,6 +361,9 @@ server_add_accept(int timeout)
|
||||
{
|
||||
struct timeval tv = { timeout, 0 };
|
||||
|
||||
if (server_fd == -1)
|
||||
return;
|
||||
|
||||
if (event_initialized(&server_ev_accept))
|
||||
event_del(&server_ev_accept);
|
||||
|
||||
|
4
spawn.c
4
spawn.c
@ -170,10 +170,8 @@ spawn_window(struct spawn_context *sc, char **cause)
|
||||
/* Spawn the pane. */
|
||||
wp = spawn_pane(sc, cause);
|
||||
if (wp == NULL) {
|
||||
if (~sc->flags & SPAWN_RESPAWN) {
|
||||
window_destroy(w);
|
||||
if (~sc->flags & SPAWN_RESPAWN)
|
||||
winlink_remove(&s->windows, sc->wl);
|
||||
}
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
|
14
style.c
14
style.c
@ -30,8 +30,9 @@
|
||||
|
||||
/* Default style. */
|
||||
static struct style style_default = {
|
||||
{ 0, 0, 8, 8, { { ' ' }, 0, 1, 1 } },
|
||||
{ { { ' ' }, 0, 1, 1 }, 0, 0, 8, 8, 0 },
|
||||
|
||||
8,
|
||||
STYLE_ALIGN_DEFAULT,
|
||||
STYLE_LIST_OFF,
|
||||
|
||||
@ -127,6 +128,10 @@ style_parse(struct style *sy, const struct grid_cell *base, const char *in)
|
||||
sy->align = STYLE_ALIGN_RIGHT;
|
||||
else
|
||||
goto error;
|
||||
} else if (end > 5 && strncasecmp(tmp, "fill=", 5) == 0) {
|
||||
if ((value = colour_fromstring(tmp + 5)) == -1)
|
||||
goto error;
|
||||
sy->fill = value;
|
||||
} else if (end > 3 && strncasecmp(tmp + 1, "g=", 2) == 0) {
|
||||
if ((value = colour_fromstring(tmp + 3)) == -1)
|
||||
goto error;
|
||||
@ -213,6 +218,11 @@ style_tostring(struct style *sy)
|
||||
tmp);
|
||||
comma = ",";
|
||||
}
|
||||
if (sy->fill != 8) {
|
||||
off += xsnprintf(s + off, sizeof s - off, "%sfill=%s", comma,
|
||||
colour_tostring(sy->fill));
|
||||
comma = ",";
|
||||
}
|
||||
if (gc->fg != 8) {
|
||||
off += xsnprintf(s + off, sizeof s - off, "%sfg=%s", comma,
|
||||
colour_tostring(gc->fg));
|
||||
@ -290,6 +300,8 @@ style_equal(struct style *sy1, struct style *sy2)
|
||||
return (0);
|
||||
if ((gc1->attr & STYLE_ATTR_MASK) != (gc2->attr & STYLE_ATTR_MASK))
|
||||
return (0);
|
||||
if (sy1->fill != sy2->fill)
|
||||
return (0);
|
||||
if (sy1->align != sy2->align)
|
||||
return (0);
|
||||
return (1);
|
||||
|
511
tmux.1
511
tmux.1
@ -461,7 +461,7 @@ Will execute
|
||||
.Ic if-shell ,
|
||||
the shell command
|
||||
.Xr true 1 ,
|
||||
.Ic new-window
|
||||
.Ic split-window
|
||||
and
|
||||
.Ic kill-session
|
||||
in that order.
|
||||
@ -475,7 +475,7 @@ commands and their arguments.
|
||||
This section describes the syntax of commands parsed by
|
||||
.Nm ,
|
||||
for example in a configuration file or at the command prompt.
|
||||
Note the when commands are entered into the shell, they are parsed by the shell
|
||||
Note that when commands are entered into the shell, they are parsed by the shell
|
||||
- see for example
|
||||
.Xr ksh 1
|
||||
or
|
||||
@ -520,7 +520,11 @@ the given four or eight digit hexadecimal number.
|
||||
When preceded (escaped) by a \e, the following characters are replaced: \ee by
|
||||
the escape character; \er by a carriage return; \en by a newline; and \et by a
|
||||
tab.
|
||||
.Pp
|
||||
.It
|
||||
\eooo is replaced by a character of the octal value ooo.
|
||||
Three octal digits are required, for example \e001.
|
||||
The largest valid character is \e377.
|
||||
.It
|
||||
Any other characters preceded by \e are replaced by themselves (that is, the \e
|
||||
is removed) and are not treated as having any special meaning - so for example
|
||||
\e; will not mark a command sequence and \e$ will not expand an environment
|
||||
@ -610,7 +614,7 @@ Most commands accept the optional
|
||||
.Fl s )
|
||||
argument with one of
|
||||
.Ar target-client ,
|
||||
.Ar target-session
|
||||
.Ar target-session ,
|
||||
.Ar target-window ,
|
||||
or
|
||||
.Ar target-pane .
|
||||
@ -777,7 +781,7 @@ may consist entirely of the token
|
||||
.Ql {mouse}
|
||||
(alternative form
|
||||
.Ql = )
|
||||
to specify the most recent mouse event
|
||||
to specify the session, window or pane where the most recent mouse event occurred
|
||||
(see the
|
||||
.Sx MOUSE SUPPORT
|
||||
section)
|
||||
@ -877,7 +881,7 @@ refresh-client -t/dev/ttyp2
|
||||
|
||||
rename-session -tfirst newname
|
||||
|
||||
set-window-option -t:0 monitor-activity on
|
||||
set-option -wt:0 monitor-activity on
|
||||
|
||||
new-window ; split-window -d
|
||||
|
||||
@ -919,7 +923,7 @@ section.
|
||||
The following commands are available to manage clients and sessions:
|
||||
.Bl -tag -width Ds
|
||||
.It Xo Ic attach-session
|
||||
.Op Fl dEr
|
||||
.Op Fl dErx
|
||||
.Op Fl c Ar working-directory
|
||||
.Op Fl t Ar target-session
|
||||
.Xc
|
||||
@ -932,6 +936,10 @@ If used from inside, switch the current client.
|
||||
If
|
||||
.Fl d
|
||||
is specified, any other clients attached to the session are detached.
|
||||
If
|
||||
.Fl x
|
||||
is given, send SIGHUP to the parent process of the client as well as
|
||||
detaching the client, typically causing it to exit.
|
||||
.Fl r
|
||||
signifies the client is read-only (only keys bound to the
|
||||
.Ic detach-client
|
||||
@ -1049,7 +1057,7 @@ command.
|
||||
Lock all clients attached to
|
||||
.Ar target-session .
|
||||
.It Xo Ic new-session
|
||||
.Op Fl AdDEP
|
||||
.Op Fl AdDEPX
|
||||
.Op Fl c Ar start-directory
|
||||
.Op Fl F Ar format
|
||||
.Op Fl n Ar window-name
|
||||
@ -1106,6 +1114,12 @@ already exists; in this case,
|
||||
behaves like
|
||||
.Fl d
|
||||
to
|
||||
.Ic attach-session ,
|
||||
and
|
||||
.Fl X
|
||||
behaves like
|
||||
.Fl x
|
||||
to
|
||||
.Ic attach-session .
|
||||
.Pp
|
||||
If
|
||||
@ -1153,7 +1167,8 @@ is used, the
|
||||
option will not be applied.
|
||||
.It Xo Ic refresh-client
|
||||
.Op Fl cDlLRSU
|
||||
.Op Fl C Ar width,height
|
||||
.Op Fl C Ar XxY
|
||||
.Op Fl F Ar flags
|
||||
.Op Fl t Ar target-client
|
||||
.Op Ar adjustment
|
||||
.Xc
|
||||
@ -1196,7 +1211,13 @@ window, changing the current window in the attached session will reset
|
||||
it.
|
||||
.Pp
|
||||
.Fl C
|
||||
sets the width and height of a control client.
|
||||
sets the width and height of a control client and
|
||||
.Fl F
|
||||
sets a comma-separated list of flags.
|
||||
Currently the only flag available is
|
||||
.Ql no-output
|
||||
to disable receiving pane output.
|
||||
.Pp
|
||||
.Fl l
|
||||
requests the clipboard from the client using the
|
||||
.Xr xterm 1
|
||||
@ -1242,7 +1263,7 @@ and
|
||||
.Fl T
|
||||
show debugging information about jobs and terminals.
|
||||
.It Xo Ic source-file
|
||||
.Op Fl nq
|
||||
.Op Fl nqv
|
||||
.Ar path
|
||||
.Ar ...
|
||||
.Xc
|
||||
@ -1260,6 +1281,8 @@ does not exist.
|
||||
With
|
||||
.Fl n ,
|
||||
the file is parsed but no commands are executed.
|
||||
.Fl v
|
||||
shows the parsed commands and line numbers if possible.
|
||||
.It Ic start-server
|
||||
.D1 (alias: Ic start )
|
||||
Start the
|
||||
@ -1343,6 +1366,9 @@ It is also entered when a command that produces output, such as
|
||||
.Ic list-keys ,
|
||||
is executed from a key binding.
|
||||
.Pp
|
||||
In copy mode an indicator is displayed in the top-right corner of the pane with
|
||||
the current position and the number of lines in the history.
|
||||
.Pp
|
||||
Commands are sent to copy mode using the
|
||||
.Fl X
|
||||
flag to the
|
||||
@ -1396,6 +1422,7 @@ The following commands are supported in copy mode:
|
||||
.It Li "jump-to-backward <to>" Ta "T" Ta ""
|
||||
.It Li "jump-to-forward <to>" Ta "t" Ta ""
|
||||
.It Li "middle-line" Ta "M" Ta "M-r"
|
||||
.It Li "next-matching-bracket" Ta "%" Ta "M-C-f"
|
||||
.It Li "next-paragraph" Ta "}" Ta "M-}"
|
||||
.It Li "next-space" Ta "W" Ta ""
|
||||
.It Li "next-space-end" Ta "E" Ta ""
|
||||
@ -1405,6 +1432,7 @@ The following commands are supported in copy mode:
|
||||
.It Li "page-down" Ta "C-f" Ta "PageDown"
|
||||
.It Li "page-down-and-cancel" Ta "" Ta ""
|
||||
.It Li "page-up" Ta "C-b" Ta "PageUp"
|
||||
.It Li "previous-matching-bracket" Ta "" Ta "M-C-b"
|
||||
.It Li "previous-paragraph" Ta "{" Ta "M-{"
|
||||
.It Li "previous-space" Ta "B" Ta ""
|
||||
.It Li "previous-word" Ta "b" Ta "M-b"
|
||||
@ -1817,14 +1845,16 @@ With
|
||||
.Fl b ,
|
||||
other commands are not blocked from running until the indicator is closed.
|
||||
.It Xo Ic find-window
|
||||
.Op Fl CNTZ
|
||||
.Op Fl rCNTZ
|
||||
.Op Fl t Ar target-pane
|
||||
.Ar match-string
|
||||
.Xc
|
||||
.D1 (alias: Ic findw )
|
||||
Search for the
|
||||
Search for a
|
||||
.Xr fnmatch 3
|
||||
pattern
|
||||
pattern or, with
|
||||
.Fl r ,
|
||||
regular expression
|
||||
.Ar match-string
|
||||
in window names, titles, and visible content (but not history).
|
||||
The flags control matching behavior:
|
||||
@ -2312,8 +2342,7 @@ applies the last set layout if possible (undoes the most recent layout change).
|
||||
.Fl E
|
||||
spreads the current pane and any panes next to it out evenly.
|
||||
.It Xo Ic select-pane
|
||||
.Op Fl DdegLlMmRU
|
||||
.Op Fl P Ar style
|
||||
.Op Fl DdeLlMmRU
|
||||
.Op Fl T Ar title
|
||||
.Op Fl t Ar target-pane
|
||||
.Xc
|
||||
@ -2321,9 +2350,7 @@ spreads the current pane and any panes next to it out evenly.
|
||||
Make pane
|
||||
.Ar target-pane
|
||||
the active pane in window
|
||||
.Ar target-window ,
|
||||
or set its style (with
|
||||
.Fl P ) .
|
||||
.Ar target-window .
|
||||
If one of
|
||||
.Fl D ,
|
||||
.Fl L ,
|
||||
@ -2340,6 +2367,8 @@ command.
|
||||
enables or
|
||||
.Fl d
|
||||
disables input to the pane.
|
||||
.Fl T
|
||||
sets the pane title.
|
||||
.Pp
|
||||
.Fl m
|
||||
and
|
||||
@ -2354,25 +2383,6 @@ to
|
||||
.Ic swap-pane
|
||||
and
|
||||
.Ic swap-window .
|
||||
.Pp
|
||||
Each pane has a style: by default the
|
||||
.Ic window-style
|
||||
and
|
||||
.Ic window-active-style
|
||||
options are used,
|
||||
.Ic select-pane
|
||||
.Fl P
|
||||
sets the style for a single pane.
|
||||
For example, to set the pane 1 background to red:
|
||||
.Bd -literal -offset indent
|
||||
select-pane -t:.1 -P 'bg=red'
|
||||
.Ed
|
||||
.Pp
|
||||
.Fl g
|
||||
shows the current pane style.
|
||||
.Pp
|
||||
.Fl T
|
||||
sets the pane title.
|
||||
.It Xo Ic select-window
|
||||
.Op Fl lnpT
|
||||
.Op Fl t Ar target-window
|
||||
@ -2629,7 +2639,7 @@ With
|
||||
only
|
||||
.Ar key-table .
|
||||
.It Xo Ic send-keys
|
||||
.Op Fl lMRX
|
||||
.Op Fl HlMRX
|
||||
.Op Fl N Ar repeat-count
|
||||
.Op Fl t Ar target-pane
|
||||
.Ar key Ar ...
|
||||
@ -2644,10 +2654,16 @@ or
|
||||
.Ql NPage )
|
||||
to send; if the string is not recognised as a key, it is sent as a series of
|
||||
characters.
|
||||
All arguments are sent sequentially from first to last.
|
||||
.Pp
|
||||
The
|
||||
.Fl l
|
||||
flag disables key name lookup and sends the keys literally.
|
||||
All arguments are sent sequentially from first to last.
|
||||
flag disables key name lookup and processes the keys as literal UTF-8
|
||||
characters.
|
||||
The
|
||||
.Fl H
|
||||
flag expects each key to be a hexadecimal number for an ASCII character.
|
||||
.Pp
|
||||
The
|
||||
.Fl R
|
||||
flag causes the terminal state to be reset.
|
||||
@ -2691,16 +2707,17 @@ is present, all key bindings are removed.
|
||||
The appearance and behaviour of
|
||||
.Nm
|
||||
may be modified by changing the value of various options.
|
||||
There are three types of option:
|
||||
There are four types of option:
|
||||
.Em server options ,
|
||||
.Em session options
|
||||
.Em window options
|
||||
and
|
||||
.Em window options .
|
||||
.Em pane options .
|
||||
.Pp
|
||||
The
|
||||
.Nm
|
||||
server has a set of global options which do not apply to any particular
|
||||
window or session.
|
||||
window or session or pane.
|
||||
These are altered with the
|
||||
.Ic set-option
|
||||
.Fl s
|
||||
@ -2722,16 +2739,29 @@ The available server and session options are listed under the
|
||||
.Ic set-option
|
||||
command.
|
||||
.Pp
|
||||
Similarly, a set of window options is attached to each window, and there is
|
||||
a set of global window options from which any unset options are inherited.
|
||||
Window options are altered with the
|
||||
.Ic set-window-option
|
||||
command and can be listed with the
|
||||
.Ic show-window-options
|
||||
command.
|
||||
All window options are documented with the
|
||||
.Ic set-window-option
|
||||
command.
|
||||
Similarly, a set of window options is attached to each window and a set of pane
|
||||
options to each pane.
|
||||
Pane options inherit from window options.
|
||||
This means any pane option may be set as a window option to apply the option to
|
||||
all panes in the window without the option set, for example these commands will
|
||||
set the background colour to red for all panes except pane 0:
|
||||
.Bd -literal -offset indent
|
||||
set -w window-style bg=red
|
||||
set -pt:.0 window-style bg=blue
|
||||
.Ed
|
||||
.Pp
|
||||
There is also a set of global window options from which any unset window or
|
||||
pane options are inherited.
|
||||
Window and pane options are altered with
|
||||
.Ic set-option
|
||||
.Fl w
|
||||
and
|
||||
.Fl p
|
||||
commands and displayed with
|
||||
.Ic show-option
|
||||
.Fl w
|
||||
and
|
||||
.Fl p .
|
||||
.Pp
|
||||
.Nm
|
||||
also supports user options which are prefixed with a
|
||||
@ -2749,26 +2779,27 @@ abc123
|
||||
Commands which set options are as follows:
|
||||
.Bl -tag -width Ds
|
||||
.It Xo Ic set-option
|
||||
.Op Fl aFgoqsuw
|
||||
.Op Fl t Ar target-session | Ar target-window
|
||||
.Op Fl aFgopqsuw
|
||||
.Op Fl t Ar target-pane
|
||||
.Ar option Ar value
|
||||
.Xc
|
||||
.D1 (alias: Ic set )
|
||||
Set a window option with
|
||||
.Fl w
|
||||
(equivalent to the
|
||||
.Ic set-window-option
|
||||
command),
|
||||
Set a pane option with
|
||||
.Fl p ,
|
||||
a window option with
|
||||
.Fl w ,
|
||||
a server option with
|
||||
.Fl s ,
|
||||
otherwise a session option.
|
||||
If the option is not a user option,
|
||||
.Fl w
|
||||
and
|
||||
or
|
||||
.Fl s
|
||||
are unnecessary -
|
||||
may be unnecessary -
|
||||
.Nm
|
||||
will infer the type from the option name.
|
||||
will infer the type from the option name, assuming
|
||||
.Fl w
|
||||
for pane options.
|
||||
If
|
||||
.Fl g
|
||||
is given, the global session or window option is set.
|
||||
@ -2813,13 +2844,49 @@ blue foreground.
|
||||
Without
|
||||
.Fl a ,
|
||||
the result would be the default background and a blue foreground.
|
||||
.Pp
|
||||
Available window options are listed under
|
||||
.Ic set-window-option .
|
||||
.Pp
|
||||
.It Xo Ic show-options
|
||||
.Op Fl AgHpqsvw
|
||||
.Op Fl t Ar target-pane
|
||||
.Op Ar option
|
||||
.Xc
|
||||
.D1 (alias: Ic show )
|
||||
Show the pane options (or a single option if
|
||||
.Ar option
|
||||
is provided) with
|
||||
.Fl p ,
|
||||
the window options with
|
||||
.Fl w ,
|
||||
the server options with
|
||||
.Fl s ,
|
||||
otherwise the session options.
|
||||
If the option is not a user option,
|
||||
.Fl w
|
||||
or
|
||||
.Fl s
|
||||
may be unnecessary -
|
||||
.Nm
|
||||
will infer the type from the option name, assuming
|
||||
.Fl w
|
||||
for pane options.
|
||||
Global session or window options are listed if
|
||||
.Fl g
|
||||
is used.
|
||||
.Fl v
|
||||
shows only the option value, not the name.
|
||||
If
|
||||
.Fl q
|
||||
is set, no error will be returned if
|
||||
.Ar option
|
||||
is unset.
|
||||
.Fl H
|
||||
includes hooks (omitted by default).
|
||||
.Fl A
|
||||
includes options inherited from a parent set of options, such options are
|
||||
marked with an asterisk.
|
||||
.Ar value
|
||||
depends on the option and may be a number, a string, or a flag (on, off, or
|
||||
omitted to toggle).
|
||||
.El
|
||||
.Pp
|
||||
Available server options are:
|
||||
.Bl -tag -width Ds
|
||||
@ -2960,6 +3027,18 @@ for all terminal types matching
|
||||
The terminal entry value is passed through
|
||||
.Xr strunvis 3
|
||||
before interpretation.
|
||||
.It Ic user-keys[] Ar key
|
||||
Set list of user-defined key escape sequences.
|
||||
Each item is associated with a key named
|
||||
.Ql User0 ,
|
||||
.Ql User1 ,
|
||||
and so on.
|
||||
.Pp
|
||||
For example:
|
||||
.Bd -literal -offset indent
|
||||
set -s user-keys[0] "\ee[5;30012~"
|
||||
bind User0 resize-pane -L 3
|
||||
.Ed
|
||||
.El
|
||||
.Pp
|
||||
Available session options are:
|
||||
@ -3166,7 +3245,7 @@ the terminal appears to be
|
||||
.Xr xterm 1 .
|
||||
This option is off by default.
|
||||
.It Ic set-titles-string Ar string
|
||||
String used to set the window title if
|
||||
String used to set the client terminal title if
|
||||
.Ic set-titles
|
||||
is on.
|
||||
Formats are expanded, see the
|
||||
@ -3300,18 +3379,6 @@ removed from the session environment (as if
|
||||
was given to the
|
||||
.Ic set-environment
|
||||
command).
|
||||
.It Ic user-keys[] Ar key
|
||||
Set list of user-defined key escape sequences.
|
||||
Each item is associated with a key named
|
||||
.Ql User0 ,
|
||||
.Ql User1 ,
|
||||
and so on.
|
||||
.Pp
|
||||
For example:
|
||||
.Bd -literal -offset indent
|
||||
set -s user-keys[0] "\ee[5;30012~"
|
||||
bind User0 resize-pane -L 3
|
||||
.Ed
|
||||
.It Xo Ic visual-activity
|
||||
.Op Ic on | off | both
|
||||
.Xc
|
||||
@ -3346,26 +3413,8 @@ copy mode.
|
||||
The default is
|
||||
.Ql \ -_@ .
|
||||
.El
|
||||
.It Xo Ic set-window-option
|
||||
.Op Fl aFgoqu
|
||||
.Op Fl t Ar target-window
|
||||
.Ar option Ar value
|
||||
.Xc
|
||||
.D1 (alias: Ic setw )
|
||||
Set a window option.
|
||||
The
|
||||
.Fl a ,
|
||||
.Fl F ,
|
||||
.Fl g ,
|
||||
.Fl o ,
|
||||
.Fl q
|
||||
and
|
||||
.Fl u
|
||||
flags work similarly to the
|
||||
.Ic set-option
|
||||
command.
|
||||
.Pp
|
||||
Supported window options are:
|
||||
Available window options are:
|
||||
.Pp
|
||||
.Bl -tag -width Ds -compact
|
||||
.It Xo Ic aggressive-resize
|
||||
@ -3384,29 +3433,6 @@ session; this option is good for full-screen programs which support
|
||||
.Dv SIGWINCH
|
||||
and poor for interactive programs such as shells.
|
||||
.Pp
|
||||
.It Xo Ic allow-rename
|
||||
.Op Ic on | off
|
||||
.Xc
|
||||
Allow programs to change the window name using a terminal escape
|
||||
sequence (\eek...\ee\e\e).
|
||||
The default is off.
|
||||
.Pp
|
||||
.It Xo Ic alternate-screen
|
||||
.Op Ic on | off
|
||||
.Xc
|
||||
This option configures whether programs running inside
|
||||
.Nm
|
||||
may use the terminal alternate screen feature, which allows the
|
||||
.Em smcup
|
||||
and
|
||||
.Em rmcup
|
||||
.Xr terminfo 5
|
||||
capabilities.
|
||||
The alternate screen feature preserves the contents of the window when an
|
||||
interactive application starts and restores it on exit, so that any output
|
||||
visible before the application starts reappears unchanged after it exits.
|
||||
The default is on.
|
||||
.Pp
|
||||
.It Xo Ic automatic-rename
|
||||
.Op Ic on | off
|
||||
.Xc
|
||||
@ -3425,7 +3451,7 @@ or later with
|
||||
or with a terminal escape sequence.
|
||||
It may be switched off globally with:
|
||||
.Bd -literal -offset indent
|
||||
set-window-option -g automatic-rename off
|
||||
set-option -wg automatic-rename off
|
||||
.Ed
|
||||
.Pp
|
||||
.It Ic automatic-rename-format Ar format
|
||||
@ -3542,29 +3568,12 @@ see the
|
||||
section.
|
||||
Attributes are ignored.
|
||||
.Pp
|
||||
.It Xo Ic remain-on-exit
|
||||
.Op Ic on | off
|
||||
.Xc
|
||||
A window with this flag set is not destroyed when the program running in it
|
||||
exits.
|
||||
The window may be reactivated with the
|
||||
.Ic respawn-window
|
||||
command.
|
||||
.Pp
|
||||
.It Xo Ic synchronize-panes
|
||||
.Op Ic on | off
|
||||
.Xc
|
||||
Duplicate input to any pane to all other panes in the same window (only
|
||||
for panes that are not in any special mode).
|
||||
.Pp
|
||||
.It Ic window-active-style Ar style
|
||||
Set the style for the window's active pane.
|
||||
For how to specify
|
||||
.Ar style ,
|
||||
see the
|
||||
.Sx STYLES
|
||||
section.
|
||||
.Pp
|
||||
.It Ic window-status-activity-style Ar style
|
||||
Set status line style for windows with an activity alert.
|
||||
For how to specify
|
||||
@ -3644,14 +3653,6 @@ command and the
|
||||
.Ic aggressive-resize
|
||||
option.
|
||||
.Pp
|
||||
.It Ic window-style Ar style
|
||||
Set the default window style.
|
||||
For how to specify
|
||||
.Ar style ,
|
||||
see the
|
||||
.Sx STYLES
|
||||
section.
|
||||
.Pp
|
||||
.It Xo Ic wrap-search
|
||||
.Op Ic on | off
|
||||
.Xc
|
||||
@ -3668,54 +3669,54 @@ will generate
|
||||
function key sequences; these have a number included to indicate modifiers such
|
||||
as Shift, Alt or Ctrl.
|
||||
.El
|
||||
.It Xo Ic show-options
|
||||
.Op Fl gHqsvw
|
||||
.Op Fl t Ar target-session | Ar target-window
|
||||
.Op Ar option
|
||||
.Pp
|
||||
Available pane options are:
|
||||
.Pp
|
||||
.Bl -tag -width Ds -compact
|
||||
.It Xo Ic allow-rename
|
||||
.Op Ic on | off
|
||||
.Xc
|
||||
.D1 (alias: Ic show )
|
||||
Show the window options (or a single window option if given) with
|
||||
.Fl w
|
||||
(equivalent to
|
||||
.Ic show-window-options ) ,
|
||||
the server options with
|
||||
.Fl s ,
|
||||
otherwise the session options for
|
||||
.Ar target session .
|
||||
If
|
||||
.Ar option
|
||||
is given and is not a user option,
|
||||
.Fl w
|
||||
Allow programs in the pane to change the window name using a terminal escape
|
||||
sequence (\eek...\ee\e\e).
|
||||
.Pp
|
||||
.It Xo Ic alternate-screen
|
||||
.Op Ic on | off
|
||||
.Xc
|
||||
This option configures whether programs running inside the pane may use the
|
||||
terminal alternate screen feature, which allows the
|
||||
.Em smcup
|
||||
and
|
||||
.Fl s
|
||||
are unnecessary -
|
||||
.Nm
|
||||
will infer the type from the option name.
|
||||
Global session or window options are listed if
|
||||
.Fl g
|
||||
is used.
|
||||
.Fl v
|
||||
shows only the option value, not the name.
|
||||
If
|
||||
.Fl q
|
||||
is set, no error will be returned if
|
||||
.Ar option
|
||||
is unset.
|
||||
.Fl H
|
||||
includes hooks (omitted by default).
|
||||
.It Xo Ic show-window-options
|
||||
.Op Fl gv
|
||||
.Op Fl t Ar target-window
|
||||
.Op Ar option
|
||||
.Em rmcup
|
||||
.Xr terminfo 5
|
||||
capabilities.
|
||||
The alternate screen feature preserves the contents of the window when an
|
||||
interactive application starts and restores it on exit, so that any output
|
||||
visible before the application starts reappears unchanged after it exits.
|
||||
.Pp
|
||||
.It Xo Ic remain-on-exit
|
||||
.Op Ic on | off
|
||||
.Xc
|
||||
.D1 (alias: Ic showw )
|
||||
List the window options or a single option for
|
||||
.Ar target-window ,
|
||||
or the global window options if
|
||||
.Fl g
|
||||
is used.
|
||||
.Fl v
|
||||
shows only the option value, not the name.
|
||||
A pane with this flag set is not destroyed when the program running in it
|
||||
exits.
|
||||
The pane may be reactivated with the
|
||||
.Ic respawn-pane
|
||||
command.
|
||||
.Pp
|
||||
.It Ic window-active-style Ar style
|
||||
Set the pane style when it is the active pane.
|
||||
For how to specify
|
||||
.Ar style ,
|
||||
see the
|
||||
.Sx STYLES
|
||||
section.
|
||||
.Pp
|
||||
.It Ic window-style Ar style
|
||||
Set the pane style.
|
||||
For how to specify
|
||||
.Ar style ,
|
||||
see the
|
||||
.Sx STYLES
|
||||
section.
|
||||
.El
|
||||
.Sh HOOKS
|
||||
.Nm
|
||||
@ -3924,7 +3925,7 @@ flag with a
|
||||
.Ar format
|
||||
argument.
|
||||
This is a string which controls the output format of the command.
|
||||
Replacement variables are enclosed in
|
||||
Format variables are enclosed in
|
||||
.Ql #{
|
||||
and
|
||||
.Ql } ,
|
||||
@ -3983,7 +3984,7 @@ For example:
|
||||
#{?pane_in_mode,#[fg=white#,bg=red],#[fg=red#,bg=white]}#W .
|
||||
.Ed
|
||||
.Pp
|
||||
Comparisons may be expressed by prefixing two comma-separated
|
||||
String comparisons may be expressed by prefixing two comma-separated
|
||||
alternatives by
|
||||
.Ql == ,
|
||||
.Ql != ,
|
||||
@ -4001,25 +4002,45 @@ if running on
|
||||
.Ql myhost ,
|
||||
otherwise by
|
||||
.Ql 0 .
|
||||
An
|
||||
.Ql m
|
||||
specifies an
|
||||
.Xr fnmatch 3
|
||||
comparison where the first argument is the pattern and the second the string to
|
||||
compare, for example
|
||||
.Ql #{m:*foo*,#{host}} .
|
||||
.Ql ||
|
||||
and
|
||||
.Ql &&
|
||||
evaluate to true if either or both of two comma-separated alternatives are
|
||||
true, for example
|
||||
.Ql #{||:#{pane_in_mode},#{alternate_on}} .
|
||||
.Pp
|
||||
An
|
||||
.Ql m
|
||||
specifies an
|
||||
.Xr fnmatch 3
|
||||
or regular expression comparison.
|
||||
The first argument is the pattern and the second the string to compare.
|
||||
An optional third argument specifies flags:
|
||||
.Ql r
|
||||
means the pattern is a regular expression instead of the default
|
||||
.Xr fnmatch 3
|
||||
pattern, and
|
||||
.Ql i
|
||||
means to ignore case.
|
||||
For example:
|
||||
.Ql #{m:*foo*,#{host}}
|
||||
or
|
||||
.Ql #{m/ri:^A,MYVAR} .
|
||||
A
|
||||
.Ql C
|
||||
performs a search for an
|
||||
.Xr fnmatch 3
|
||||
pattern in the pane content and evaluates to zero if not found, or a line
|
||||
number if found.
|
||||
pattern or regular expression in the pane content and evaluates to zero if not
|
||||
found, or a line number if found.
|
||||
Like
|
||||
.Ql m ,
|
||||
an
|
||||
.Ql r
|
||||
flag means search for a regular expression and
|
||||
.Ql i
|
||||
ignores case.
|
||||
For example:
|
||||
.Ql #{C/r:^Start}
|
||||
.Pp
|
||||
A limit may be placed on the length of the resultant string by prefixing it
|
||||
by an
|
||||
@ -4065,7 +4086,7 @@ will expand the format twice, for example
|
||||
.Ql #{E:status-left}
|
||||
is the result of expanding the content of the
|
||||
.Ic status-left
|
||||
option rather than the content itself.
|
||||
option rather than the option itself.
|
||||
.Ql T:
|
||||
is like
|
||||
.Ql E:
|
||||
@ -4092,8 +4113,16 @@ will substitute
|
||||
with
|
||||
.Ql bar
|
||||
throughout.
|
||||
The first argument may be an extended regular expression and a final argument may be
|
||||
.Ql i
|
||||
to ignore case, for example
|
||||
.Ql s/a(.)/\e1x/i:
|
||||
would change
|
||||
.Ql abABab
|
||||
into
|
||||
.Ql bxBxbx .
|
||||
.Pp
|
||||
In addition, the first line of a shell command's output may be inserted using
|
||||
In addition, the last line of a shell command's output may be inserted using
|
||||
.Ql #() .
|
||||
For example,
|
||||
.Ql #(uptime)
|
||||
@ -4112,10 +4141,18 @@ global environment set (see the
|
||||
.Sx GLOBAL AND SESSION ENVIRONMENT
|
||||
section).
|
||||
.Pp
|
||||
An
|
||||
.Ql l
|
||||
specifies that a string should be interpreted literally and not expanded.
|
||||
For example
|
||||
.Ql #{l:#{?pane_in_mode,yes,no}}
|
||||
will be replaced by
|
||||
.Ql #{?pane_in_mode,yes,no} .
|
||||
.Pp
|
||||
The following variables are available, where appropriate:
|
||||
.Bl -column "XXXXXXXXXXXXXXXXXXX" "XXXXX"
|
||||
.It Sy "Variable name" Ta Sy "Alias" Ta Sy "Replaced with"
|
||||
.It Li "alternate_on" Ta "" Ta "If pane is in alternate screen"
|
||||
.It Li "alternate_on" Ta "" Ta "1 if pane is in alternate screen"
|
||||
.It Li "alternate_saved_x" Ta "" Ta "Saved cursor X in alternate screen"
|
||||
.It Li "alternate_saved_y" Ta "" Ta "Saved cursor Y in alternate screen"
|
||||
.It Li "buffer_created" Ta "" Ta "Time buffer created"
|
||||
@ -4166,11 +4203,14 @@ The following variables are available, where appropriate:
|
||||
.It Li "mouse_all_flag" Ta "" Ta "Pane mouse all flag"
|
||||
.It Li "mouse_any_flag" Ta "" Ta "Pane mouse any flag"
|
||||
.It Li "mouse_button_flag" Ta "" Ta "Pane mouse button flag"
|
||||
.It Li "mouse_line" Ta "" Ta "Line under mouse, if any"
|
||||
.It Li "mouse_sgr_flag" Ta "" Ta "Pane mouse SGR flag"
|
||||
.It Li "mouse_standard_flag" Ta "" Ta "Pane mouse standard flag"
|
||||
.It Li "mouse_utf8_flag" Ta "" Ta "Pane mouse UTF-8 flag"
|
||||
.It Li "mouse_word" Ta "" Ta "Word under mouse, if any"
|
||||
.It Li "mouse_x" Ta "" Ta "Mouse X position, if any"
|
||||
.It Li "mouse_y" Ta "" Ta "Mouse Y position, if any"
|
||||
.It Li "mouse_word" Ta "" Ta "Word under mouse, if any"
|
||||
.It Li "mouse_line" Ta "" Ta "Line under mouse, if any"
|
||||
.It Li "origin_flag" Ta "" Ta "Pane origin flag"
|
||||
.It Li "pane_active" Ta "" Ta "1 if active pane"
|
||||
.It Li "pane_at_bottom" Ta "" Ta "1 if pane is at the bottom of window"
|
||||
.It Li "pane_at_left" Ta "" Ta "1 if pane is at the left of window"
|
||||
@ -4184,19 +4224,19 @@ The following variables are available, where appropriate:
|
||||
.It Li "pane_format" Ta "" Ta "1 if format is for a pane (not assuming the current)"
|
||||
.It Li "pane_height" Ta "" Ta "Height of pane"
|
||||
.It Li "pane_id" Ta "#D" Ta "Unique pane ID"
|
||||
.It Li "pane_in_mode" Ta "" Ta "If pane is in a mode"
|
||||
.It Li "pane_in_mode" Ta "" Ta "1 if pane is in a mode"
|
||||
.It Li "pane_index" Ta "#P" Ta "Index of pane"
|
||||
.It Li "pane_input_off" Ta "" Ta "If input to pane is disabled"
|
||||
.It Li "pane_input_off" Ta "" Ta "1 if input to pane is disabled"
|
||||
.It Li "pane_left" Ta "" Ta "Left of pane"
|
||||
.It Li "pane_marked" Ta "" Ta "1 if this is the marked pane"
|
||||
.It Li "pane_marked_set" Ta "" Ta "1 if a marked pane is set"
|
||||
.It Li "pane_mode" Ta "" Ta "Name of pane mode, if any."
|
||||
.It Li "pane_mode" Ta "" Ta "Name of pane mode, if any"
|
||||
.It Li "pane_pid" Ta "" Ta "PID of first process in pane"
|
||||
.It Li "pane_pipe" Ta "" Ta "1 if pane is being piped"
|
||||
.It Li "pane_right" Ta "" Ta "Right of pane"
|
||||
.It Li "pane_search_string" Ta "" Ta "Last search string in copy mode"
|
||||
.It Li "pane_start_command" Ta "" Ta "Command pane started with"
|
||||
.It Li "pane_synchronized" Ta "" Ta "If pane is synchronized"
|
||||
.It Li "pane_synchronized" Ta "" Ta "1 if pane is synchronized"
|
||||
.It Li "pane_tabs" Ta "" Ta "Pane tab positions"
|
||||
.It Li "pane_title" Ta "#T" Ta "Title of pane"
|
||||
.It Li "pane_top" Ta "" Ta "Top of pane"
|
||||
@ -4325,10 +4365,12 @@ to unset.
|
||||
.Ic align=right
|
||||
.Xc
|
||||
Align text to the left, centre or right of the available space if appropriate.
|
||||
.It Ic fill=colour
|
||||
Fill the available space with a background colour if appropriate.
|
||||
.It Xo Ic list=on ,
|
||||
.Ic list=focus ,
|
||||
.Ic list=left-marker ,
|
||||
.Ic list=right=marker ,
|
||||
.Ic list=right-marker ,
|
||||
.Ic nolist
|
||||
.Xc
|
||||
Mark the position of the various window list components in the
|
||||
@ -4560,7 +4602,7 @@ session option.
|
||||
Commands related to the status line are as follows:
|
||||
.Bl -tag -width Ds
|
||||
.It Xo Ic command-prompt
|
||||
.Op Fl 1i
|
||||
.Op Fl 1Ni
|
||||
.Op Fl I Ar inputs
|
||||
.Op Fl p Ar prompts
|
||||
.Op Fl t Ar target-client
|
||||
@ -4610,6 +4652,8 @@ but any quotation marks are escaped.
|
||||
.Fl 1
|
||||
makes the prompt only accept one key press, in this case the resulting input
|
||||
is a single character.
|
||||
.Fl N
|
||||
makes the prompt only accept numeric key presses.
|
||||
.Fl i
|
||||
executes the command every time the prompt input changes instead of when the
|
||||
user exits the command prompt.
|
||||
@ -4621,7 +4665,7 @@ option:
|
||||
.Bl -column "FunctionXXXXXXXXXXXXXXXXXXXXXXXXX" "viXXXX" "emacsX" -offset indent
|
||||
.It Sy "Function" Ta Sy "vi" Ta Sy "emacs"
|
||||
.It Li "Cancel command prompt" Ta "Escape" Ta "Escape"
|
||||
.It Li "Delete current word" Ta "" Ta "C-w"
|
||||
.It Li "Delete from cursor to start of word" Ta "" Ta "C-w"
|
||||
.It Li "Delete entire command" Ta "d" Ta "C-u"
|
||||
.It Li "Delete from cursor to end" Ta "D" Ta "C-k"
|
||||
.It Li "Execute command" Ta "Enter" Ta "Enter"
|
||||
@ -4739,8 +4783,7 @@ section; information is taken from
|
||||
.Ar target-pane
|
||||
if
|
||||
.Fl t
|
||||
is given, otherwise the active pane for the session attached to
|
||||
.Ar target-client .
|
||||
is given, otherwise the active pane.
|
||||
.Pp
|
||||
.Fl v
|
||||
prints verbose logging as the format is parsed and
|
||||
@ -5032,11 +5075,33 @@ $ printf '\e033]12;red\e033\e\e'
|
||||
.Ed
|
||||
.It Em \&Smol
|
||||
Enable the overline attribute.
|
||||
The capability is usually SGR 53 and can be added to
|
||||
.Ic terminal-overrides
|
||||
as:
|
||||
.Bd -literal -offset indent
|
||||
Smol=\eE[53m
|
||||
.Ed
|
||||
.It Em \&Smulx
|
||||
Set a styled underline.
|
||||
The single parameter is one of: 0 for no underline, 1 for normal
|
||||
underline, 2 for double underline, 3 for curly underline, 4 for dotted
|
||||
underline and 5 for dashed underline.
|
||||
Set a styled underscore.
|
||||
The single parameter is one of: 0 for no underscore, 1 for normal
|
||||
underscore, 2 for double underscore, 3 for curly underscore, 4 for dotted
|
||||
underscore and 5 for dashed underscore.
|
||||
The capability can typically be added to
|
||||
.Ic terminal-overrides
|
||||
as:
|
||||
.Bd -literal -offset indent
|
||||
Smulx=\eE[4::%p1%dm
|
||||
.Ed
|
||||
.It Em \&Setulc
|
||||
Set the underscore colour.
|
||||
The argument is (red * 65536) + (green * 256) + blue where each is between 0
|
||||
and 255.
|
||||
The capability can typically be added to
|
||||
.Ic terminal-overrides
|
||||
as:
|
||||
.Bd -literal -offset indent
|
||||
Setulc=\eE[58::2::%p1%{65536}%/%d::%p1%{256}%/%{255}%&%d::%p1%{255}%&%d%;m
|
||||
.Ed
|
||||
.It Em \&Ss , Se
|
||||
Set or reset the cursor style.
|
||||
If set, a sequence such as this may be used
|
||||
|
6
tmux.c
6
tmux.c
@ -321,11 +321,11 @@ main(int argc, char **argv)
|
||||
global_s_options = options_create(NULL);
|
||||
global_w_options = options_create(NULL);
|
||||
for (oe = options_table; oe->name != NULL; oe++) {
|
||||
if (oe->scope == OPTIONS_TABLE_SERVER)
|
||||
if (oe->scope & OPTIONS_TABLE_SERVER)
|
||||
options_default(global_options, oe);
|
||||
if (oe->scope == OPTIONS_TABLE_SESSION)
|
||||
if (oe->scope & OPTIONS_TABLE_SESSION)
|
||||
options_default(global_s_options, oe);
|
||||
if (oe->scope == OPTIONS_TABLE_WINDOW)
|
||||
if (oe->scope & OPTIONS_TABLE_WINDOW)
|
||||
options_default(global_w_options, oe);
|
||||
}
|
||||
|
||||
|
64
tmux.h
64
tmux.h
@ -113,9 +113,10 @@ struct winlink;
|
||||
#define KEYC_CTRL 0x400000000000ULL
|
||||
#define KEYC_SHIFT 0x800000000000ULL
|
||||
#define KEYC_XTERM 0x1000000000000ULL
|
||||
#define KEYC_LITERAL 0x2000000000000ULL
|
||||
|
||||
/* Mask to obtain key w/o modifiers. */
|
||||
#define KEYC_MASK_MOD (KEYC_ESCAPE|KEYC_CTRL|KEYC_SHIFT|KEYC_XTERM)
|
||||
#define KEYC_MASK_MOD (KEYC_ESCAPE|KEYC_CTRL|KEYC_SHIFT|KEYC_XTERM|KEYC_LITERAL)
|
||||
#define KEYC_MASK_KEY (~KEYC_MASK_MOD)
|
||||
|
||||
/* Is this a mouse key? */
|
||||
@ -429,6 +430,7 @@ enum tty_code_code {
|
||||
TTYC_SETAF,
|
||||
TTYC_SETRGBB,
|
||||
TTYC_SETRGBF,
|
||||
TTYC_SETULC,
|
||||
TTYC_SGR0,
|
||||
TTYC_SITM,
|
||||
TTYC_SMACS,
|
||||
@ -597,12 +599,13 @@ enum utf8_state {
|
||||
|
||||
/* Grid cell data. */
|
||||
struct grid_cell {
|
||||
u_char flags;
|
||||
struct utf8_data data; /* 21 bytes */
|
||||
u_short attr;
|
||||
u_char flags;
|
||||
int fg;
|
||||
int bg;
|
||||
struct utf8_data data;
|
||||
};
|
||||
int us;
|
||||
} __packed;
|
||||
struct grid_cell_entry {
|
||||
u_char flags;
|
||||
union {
|
||||
@ -682,6 +685,7 @@ TAILQ_HEAD(style_ranges, style_range);
|
||||
struct style {
|
||||
struct grid_cell gc;
|
||||
|
||||
int fill;
|
||||
enum style_align align;
|
||||
enum style_list list;
|
||||
|
||||
@ -812,6 +816,7 @@ struct window_pane {
|
||||
u_int active_point;
|
||||
|
||||
struct window *window;
|
||||
struct options *options;
|
||||
|
||||
struct layout_cell *layout_cell;
|
||||
struct layout_cell *saved_layout_cell;
|
||||
@ -838,6 +843,7 @@ struct window_pane {
|
||||
#define PANE_STATUSREADY 0x200
|
||||
#define PANE_STATUSDRAWN 0x400
|
||||
#define PANE_EMPTY 0x800
|
||||
#define PANE_STYLECHANGED 0x1000
|
||||
|
||||
int argc;
|
||||
char **argv;
|
||||
@ -856,7 +862,8 @@ struct window_pane {
|
||||
|
||||
struct input_ctx *ictx;
|
||||
|
||||
struct style style;
|
||||
struct style cached_style;
|
||||
struct style cached_active_style;
|
||||
int *palette;
|
||||
|
||||
int pipe_fd;
|
||||
@ -916,7 +923,6 @@ struct window {
|
||||
#define WINDOW_ACTIVITY 0x2
|
||||
#define WINDOW_SILENCE 0x4
|
||||
#define WINDOW_ZOOMED 0x8
|
||||
#define WINDOW_STYLECHANGED 0x10
|
||||
#define WINDOW_ALERTFLAGS (WINDOW_BELL|WINDOW_ACTIVITY|WINDOW_SILENCE)
|
||||
|
||||
int alerts_queued;
|
||||
@ -924,9 +930,6 @@ struct window {
|
||||
|
||||
struct options *options;
|
||||
|
||||
struct style style;
|
||||
struct style active_style;
|
||||
|
||||
u_int references;
|
||||
TAILQ_HEAD(, winlink) winlinks;
|
||||
|
||||
@ -958,6 +961,11 @@ TAILQ_HEAD(winlink_stack, winlink);
|
||||
#define WINDOW_SIZE_SMALLEST 1
|
||||
#define WINDOW_SIZE_MANUAL 2
|
||||
|
||||
/* Pane border status option. */
|
||||
#define PANE_STATUS_OFF 0
|
||||
#define PANE_STATUS_TOP 1
|
||||
#define PANE_STATUS_BOTTOM 2
|
||||
|
||||
/* Layout direction. */
|
||||
enum layout_type {
|
||||
LAYOUT_LEFTRIGHT,
|
||||
@ -1326,6 +1334,7 @@ struct cmd_parse_input {
|
||||
#define CMD_PARSE_QUIET 0x1
|
||||
#define CMD_PARSE_PARSEONLY 0x2
|
||||
#define CMD_PARSE_NOALIAS 0x4
|
||||
#define CMD_PARSE_VERBOSE 0x8
|
||||
|
||||
const char *file;
|
||||
u_int line;
|
||||
@ -1491,7 +1500,7 @@ struct client {
|
||||
#define CLIENT_REPEAT 0x20
|
||||
#define CLIENT_SUSPENDED 0x40
|
||||
#define CLIENT_ATTACHED 0x80
|
||||
/* 0x100 unused */
|
||||
#define CLIENT_EXITED 0x100
|
||||
#define CLIENT_DEAD 0x200
|
||||
#define CLIENT_REDRAWBORDERS 0x400
|
||||
#define CLIENT_READONLY 0x800
|
||||
@ -1509,6 +1518,7 @@ struct client {
|
||||
#define CLIENT_STATUSOFF 0x800000
|
||||
#define CLIENT_REDRAWSTATUSALWAYS 0x1000000
|
||||
#define CLIENT_REDRAWOVERLAY 0x2000000
|
||||
#define CLIENT_CONTROL_NOOUTPUT 0x4000000
|
||||
#define CLIENT_ALLREDRAWFLAGS \
|
||||
(CLIENT_REDRAWWINDOW| \
|
||||
CLIENT_REDRAWSTATUS| \
|
||||
@ -1606,12 +1616,11 @@ enum options_table_type {
|
||||
OPTIONS_TABLE_COMMAND
|
||||
};
|
||||
|
||||
enum options_table_scope {
|
||||
OPTIONS_TABLE_NONE,
|
||||
OPTIONS_TABLE_SERVER,
|
||||
OPTIONS_TABLE_SESSION,
|
||||
OPTIONS_TABLE_WINDOW
|
||||
};
|
||||
#define OPTIONS_TABLE_NONE 0
|
||||
#define OPTIONS_TABLE_SERVER 0x1
|
||||
#define OPTIONS_TABLE_SESSION 0x2
|
||||
#define OPTIONS_TABLE_WINDOW 0x4
|
||||
#define OPTIONS_TABLE_PANE 0x8
|
||||
|
||||
#define OPTIONS_TABLE_IS_ARRAY 0x1
|
||||
#define OPTIONS_TABLE_IS_HOOK 0x2
|
||||
@ -1619,7 +1628,7 @@ enum options_table_scope {
|
||||
struct options_table_entry {
|
||||
const char *name;
|
||||
enum options_table_type type;
|
||||
enum options_table_scope scope;
|
||||
int scope;
|
||||
int flags;
|
||||
|
||||
u_int minimum;
|
||||
@ -1781,6 +1790,7 @@ void notify_pane(const char *, struct window_pane *);
|
||||
/* options.c */
|
||||
struct options *options_create(struct options *);
|
||||
void options_free(struct options *);
|
||||
void options_set_parent(struct options *, struct options *);
|
||||
struct options_entry *options_first(struct options *);
|
||||
struct options_entry *options_next(struct options_entry *);
|
||||
struct options_entry *options_empty(struct options *,
|
||||
@ -1820,7 +1830,10 @@ struct options_entry *options_set_number(struct options *, const char *,
|
||||
long long);
|
||||
struct options_entry *options_set_style(struct options *, const char *, int,
|
||||
const char *);
|
||||
enum options_table_scope options_scope_from_flags(struct args *, int,
|
||||
int options_scope_from_name(struct args *, int,
|
||||
const char *, struct cmd_find_state *, struct options **,
|
||||
char **);
|
||||
int options_scope_from_flags(struct args *, int,
|
||||
struct cmd_find_state *, struct options **, char **);
|
||||
|
||||
/* options-table.c */
|
||||
@ -2011,7 +2024,7 @@ extern const struct cmd_entry *cmd_table[];
|
||||
|
||||
/* cmd-attach-session.c */
|
||||
enum cmd_retval cmd_attach_session(struct cmdq_item *, const char *, int, int,
|
||||
const char *, int);
|
||||
int, const char *, int);
|
||||
|
||||
/* cmd-parse.c */
|
||||
void cmd_parse_empty(struct cmd_parse_input *);
|
||||
@ -2038,6 +2051,7 @@ void cmdq_insert_after(struct cmdq_item *, struct cmdq_item *);
|
||||
void cmdq_append(struct client *, struct cmdq_item *);
|
||||
void cmdq_insert_hook(struct session *, struct cmdq_item *,
|
||||
struct cmd_find_state *, const char *, ...);
|
||||
void cmdq_continue(struct cmdq_item *);
|
||||
void printflike(3, 4) cmdq_format(struct cmdq_item *, const char *,
|
||||
const char *, ...);
|
||||
u_int cmdq_next(struct client *);
|
||||
@ -2187,7 +2201,8 @@ int colour_join_rgb(u_char, u_char, u_char);
|
||||
void colour_split_rgb(int, u_char *, u_char *, u_char *);
|
||||
const char *colour_tostring(int);
|
||||
int colour_fromstring(const char *s);
|
||||
u_char colour_256to16(u_char);
|
||||
int colour_256toRGB(int);
|
||||
int colour_256to16(int);
|
||||
|
||||
/* attributes.c */
|
||||
const char *attributes_tostring(int);
|
||||
@ -2352,7 +2367,6 @@ struct window *window_find_by_id_str(const char *);
|
||||
struct window *window_find_by_id(u_int);
|
||||
void window_update_activity(struct window *);
|
||||
struct window *window_create(u_int, u_int);
|
||||
void window_destroy(struct window *);
|
||||
void window_pane_set_event(struct window_pane *);
|
||||
struct window_pane *window_get_active_at(struct window *, u_int, u_int);
|
||||
struct window_pane *window_find_string(struct window *, const char *);
|
||||
@ -2397,7 +2411,8 @@ void window_pane_key(struct window_pane *, struct client *,
|
||||
struct session *, struct winlink *, key_code,
|
||||
struct mouse_event *);
|
||||
int window_pane_visible(struct window_pane *);
|
||||
u_int window_pane_search(struct window_pane *, const char *);
|
||||
u_int window_pane_search(struct window_pane *, const char *, int,
|
||||
int);
|
||||
const char *window_printable_flags(struct winlink *);
|
||||
struct window_pane *window_pane_find_up(struct window_pane *);
|
||||
struct window_pane *window_pane_find_down(struct window_pane *);
|
||||
@ -2425,7 +2440,7 @@ void layout_set_size(struct layout_cell *, u_int, u_int, u_int,
|
||||
u_int);
|
||||
void layout_make_leaf(struct layout_cell *, struct window_pane *);
|
||||
void layout_make_node(struct layout_cell *, enum layout_type);
|
||||
void layout_fix_offsets(struct layout_cell *);
|
||||
void layout_fix_offsets(struct window *);
|
||||
void layout_fix_panes(struct window *);
|
||||
void layout_resize_adjust(struct window *, struct layout_cell *,
|
||||
enum layout_type, int);
|
||||
@ -2634,4 +2649,7 @@ int style_is_default(struct style *);
|
||||
struct winlink *spawn_window(struct spawn_context *, char **);
|
||||
struct window_pane *spawn_pane(struct spawn_context *, char **);
|
||||
|
||||
/* regsub.c */
|
||||
char *regsub(const char *, const char *, const char *, int);
|
||||
|
||||
#endif /* TMUX_H */
|
||||
|
@ -249,6 +249,7 @@ static const struct tty_term_code_entry tty_term_codes[] = {
|
||||
[TTYC_SETAF] = { TTYCODE_STRING, "setaf" },
|
||||
[TTYC_SETRGBB] = { TTYCODE_STRING, "setrgbb" },
|
||||
[TTYC_SETRGBF] = { TTYCODE_STRING, "setrgbf" },
|
||||
[TTYC_SETULC] = { TTYCODE_STRING, "Setulc" },
|
||||
[TTYC_SE] = { TTYCODE_STRING, "Se" },
|
||||
[TTYC_SGR0] = { TTYCODE_STRING, "sgr0" },
|
||||
[TTYC_SITM] = { TTYCODE_STRING, "sitm" },
|
||||
@ -691,7 +692,7 @@ tty_term_describe(struct tty_term *term, enum tty_code_code code)
|
||||
break;
|
||||
case TTYCODE_STRING:
|
||||
strnvis(out, term->codes[code].value.string, sizeof out,
|
||||
VIS_OCTAL|VIS_TAB|VIS_NL);
|
||||
VIS_OCTAL|VIS_CSTYLE|VIS_TAB|VIS_NL);
|
||||
xsnprintf(s, sizeof s, "%4u: %s: (string) %s",
|
||||
code, tty_term_codes[code].name,
|
||||
out);
|
||||
|
138
tty.c
138
tty.c
@ -49,8 +49,11 @@ static void tty_check_fg(struct tty *, struct window_pane *,
|
||||
struct grid_cell *);
|
||||
static void tty_check_bg(struct tty *, struct window_pane *,
|
||||
struct grid_cell *);
|
||||
static void tty_check_us(struct tty *, struct window_pane *,
|
||||
struct grid_cell *);
|
||||
static void tty_colours_fg(struct tty *, const struct grid_cell *);
|
||||
static void tty_colours_bg(struct tty *, const struct grid_cell *);
|
||||
static void tty_colours_us(struct tty *, const struct grid_cell *);
|
||||
|
||||
static void tty_region_pane(struct tty *, const struct tty_ctx *, u_int,
|
||||
u_int);
|
||||
@ -527,6 +530,12 @@ tty_putc(struct tty *tty, u_char ch)
|
||||
{
|
||||
const char *acs;
|
||||
|
||||
if ((tty->term->flags & TERM_EARLYWRAP) &&
|
||||
ch >= 0x20 && ch != 0x7f &&
|
||||
tty->cy == tty->sy - 1 &&
|
||||
tty->cx + 1 >= tty->sx)
|
||||
return;
|
||||
|
||||
if (tty->cell.attr & GRID_ATTR_CHARSET) {
|
||||
acs = tty_acs_get(tty, ch);
|
||||
if (acs != NULL)
|
||||
@ -557,6 +566,11 @@ tty_putc(struct tty *tty, u_char ch)
|
||||
void
|
||||
tty_putn(struct tty *tty, const void *buf, size_t len, u_int width)
|
||||
{
|
||||
if ((tty->term->flags & TERM_EARLYWRAP) &&
|
||||
tty->cy == tty->sy - 1 &&
|
||||
tty->cx + len >= tty->sx)
|
||||
len = tty->sx - tty->cx - 1;
|
||||
|
||||
tty_add(tty, buf, len);
|
||||
if (tty->cx + width > tty->sx) {
|
||||
tty->cx = (tty->cx + width) - tty->sx;
|
||||
@ -1049,17 +1063,17 @@ tty_clamp_area(struct tty *tty, const struct tty_ctx *ctx, u_int px, u_int py,
|
||||
*y = ctx->yoff + py - ctx->oy;
|
||||
*ry = ny;
|
||||
} else if (yoff < ctx->oy && yoff + ny > ctx->oy + ctx->sy) {
|
||||
/* Both left and right not visible. */
|
||||
/* Both top and bottom not visible. */
|
||||
*j = ctx->oy;
|
||||
*y = 0;
|
||||
*ry = ctx->sy;
|
||||
} else if (yoff < ctx->oy) {
|
||||
/* Left not visible. */
|
||||
/* Top not visible. */
|
||||
*j = ctx->oy - (ctx->yoff + py);
|
||||
*y = 0;
|
||||
*ry = ny - *j;
|
||||
} else {
|
||||
/* Right not visible. */
|
||||
/* Bottom not visible. */
|
||||
*j = 0;
|
||||
*y = (ctx->yoff + py) - ctx->oy;
|
||||
*ry = ctx->sy - *y;
|
||||
@ -1203,7 +1217,7 @@ tty_draw_line(struct tty *tty, struct window_pane *wp, struct screen *s,
|
||||
const struct grid_cell *gcp;
|
||||
struct grid_line *gl;
|
||||
u_int i, j, ux, sx, width;
|
||||
int flags, cleared = 0;
|
||||
int flags, cleared = 0, wrapped = 0;
|
||||
char buf[512];
|
||||
size_t len;
|
||||
u_int cellsize;
|
||||
@ -1260,8 +1274,10 @@ tty_draw_line(struct tty *tty, struct window_pane *wp, struct screen *s,
|
||||
tty_putcode(tty, TTYC_EL1);
|
||||
cleared = 1;
|
||||
}
|
||||
} else
|
||||
} else {
|
||||
log_debug("%s: wrapped line %u", __func__, aty);
|
||||
wrapped = 1;
|
||||
}
|
||||
|
||||
memcpy(&last, &grid_default_cell, sizeof last);
|
||||
len = 0;
|
||||
@ -1276,6 +1292,7 @@ tty_draw_line(struct tty *tty, struct window_pane *wp, struct screen *s,
|
||||
gcp->attr != last.attr ||
|
||||
gcp->fg != last.fg ||
|
||||
gcp->bg != last.bg ||
|
||||
gcp->us != last.us ||
|
||||
ux + width + gcp->data.width > nx ||
|
||||
(sizeof buf) - len < gcp->data.size)) {
|
||||
tty_attributes(tty, &last, wp);
|
||||
@ -1284,13 +1301,15 @@ tty_draw_line(struct tty *tty, struct window_pane *wp, struct screen *s,
|
||||
tty_clear_line(tty, wp, aty, atx + ux, width,
|
||||
last.bg);
|
||||
} else {
|
||||
tty_cursor(tty, atx + ux, aty);
|
||||
if (!wrapped || atx != 0 || ux != 0)
|
||||
tty_cursor(tty, atx + ux, aty);
|
||||
tty_putn(tty, buf, len, width);
|
||||
}
|
||||
ux += width;
|
||||
|
||||
len = 0;
|
||||
width = 0;
|
||||
wrapped = 0;
|
||||
}
|
||||
|
||||
if (gcp->flags & GRID_FLAG_SELECTED)
|
||||
@ -1324,7 +1343,8 @@ tty_draw_line(struct tty *tty, struct window_pane *wp, struct screen *s,
|
||||
log_debug("%s: %zu cleared (end)", __func__, len);
|
||||
tty_clear_line(tty, wp, aty, atx + ux, width, last.bg);
|
||||
} else {
|
||||
tty_cursor(tty, atx + ux, aty);
|
||||
if (!wrapped || atx != 0 || ux != 0)
|
||||
tty_cursor(tty, atx + ux, aty);
|
||||
tty_putn(tty, buf, len, width);
|
||||
}
|
||||
ux += width;
|
||||
@ -2121,10 +2141,11 @@ tty_attributes(struct tty *tty, const struct grid_cell *gc,
|
||||
/* Ignore cell if it is the same as the last one. */
|
||||
if (wp != NULL &&
|
||||
(int)wp->id == tty->last_wp &&
|
||||
~(wp->window->flags & WINDOW_STYLECHANGED) &&
|
||||
~(wp->flags & PANE_STYLECHANGED) &&
|
||||
gc->attr == tty->last_cell.attr &&
|
||||
gc->fg == tty->last_cell.fg &&
|
||||
gc->bg == tty->last_cell.bg)
|
||||
gc->bg == tty->last_cell.bg &&
|
||||
gc->us == tty->last_cell.us)
|
||||
return;
|
||||
tty->last_wp = (wp != NULL ? (int)wp->id : -1);
|
||||
memcpy(&tty->last_cell, gc, sizeof tty->last_cell);
|
||||
@ -2152,14 +2173,18 @@ tty_attributes(struct tty *tty, const struct grid_cell *gc,
|
||||
/* Fix up the colours if necessary. */
|
||||
tty_check_fg(tty, wp, &gc2);
|
||||
tty_check_bg(tty, wp, &gc2);
|
||||
tty_check_us(tty, wp, &gc2);
|
||||
|
||||
/* If any bits are being cleared, reset everything. */
|
||||
if (tc->attr & ~gc2.attr)
|
||||
/*
|
||||
* If any bits are being cleared or the underline colour is now default,
|
||||
* reset everything.
|
||||
*/
|
||||
if ((tc->attr & ~gc2.attr) || (tc->us != gc2.us && gc2.us == 0))
|
||||
tty_reset(tty);
|
||||
|
||||
/*
|
||||
* Set the colours. This may call tty_reset() (so it comes next) and
|
||||
* may add to (NOT remove) the desired attributes by changing new_attr.
|
||||
* may add to (NOT remove) the desired attributes.
|
||||
*/
|
||||
tty_colours(tty, &gc2);
|
||||
|
||||
@ -2212,7 +2237,7 @@ tty_colours(struct tty *tty, const struct grid_cell *gc)
|
||||
int have_ax;
|
||||
|
||||
/* No changes? Nothing is necessary. */
|
||||
if (gc->fg == tc->fg && gc->bg == tc->bg)
|
||||
if (gc->fg == tc->fg && gc->bg == tc->bg && gc->us == tc->us)
|
||||
return;
|
||||
|
||||
/*
|
||||
@ -2260,6 +2285,10 @@ tty_colours(struct tty *tty, const struct grid_cell *gc)
|
||||
*/
|
||||
if (!COLOUR_DEFAULT(gc->bg) && gc->bg != tc->bg)
|
||||
tty_colours_bg(tty, gc);
|
||||
|
||||
/* Set the underscore color. */
|
||||
if (gc->us != tc->us)
|
||||
tty_colours_us(tty, gc);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -2374,6 +2403,22 @@ tty_check_bg(struct tty *tty, struct window_pane *wp, struct grid_cell *gc)
|
||||
gc->bg -= 90;
|
||||
}
|
||||
|
||||
static void
|
||||
tty_check_us(__unused struct tty *tty, struct window_pane *wp, struct grid_cell *gc)
|
||||
{
|
||||
int c;
|
||||
|
||||
/* Perform substitution if this pane has a palette. */
|
||||
if (~gc->flags & GRID_FLAG_NOPALETTE) {
|
||||
if ((c = window_pane_get_palette(wp, gc->us)) != -1)
|
||||
gc->us = c;
|
||||
}
|
||||
|
||||
/* Underscore colour is set as RGB so convert a 256 colour to RGB. */
|
||||
if (gc->us & COLOUR_FLAG_256)
|
||||
gc->us = colour_256toRGB (gc->us);
|
||||
}
|
||||
|
||||
static void
|
||||
tty_colours_fg(struct tty *tty, const struct grid_cell *gc)
|
||||
{
|
||||
@ -2438,6 +2483,31 @@ save_bg:
|
||||
tc->bg = gc->bg;
|
||||
}
|
||||
|
||||
static void
|
||||
tty_colours_us(struct tty *tty, const struct grid_cell *gc)
|
||||
{
|
||||
struct grid_cell *tc = &tty->cell;
|
||||
u_int c;
|
||||
u_char r, g, b;
|
||||
|
||||
/* Must be an RGB colour - this should never happen. */
|
||||
if (~gc->us & COLOUR_FLAG_RGB)
|
||||
return;
|
||||
|
||||
/*
|
||||
* Setulc follows the ncurses(3) one argument "direct colour"
|
||||
* capability format. Calculate the colour value.
|
||||
*/
|
||||
colour_split_rgb(gc->us, &r, &g, &b);
|
||||
c = (65536 * r) + (256 * g) + b;
|
||||
|
||||
/* Write the colour. */
|
||||
tty_putcode1(tty, TTYC_SETULC, c);
|
||||
|
||||
/* Save the new values in the terminal current cell. */
|
||||
tc->us = gc->us;
|
||||
}
|
||||
|
||||
static int
|
||||
tty_try_colour(struct tty *tty, int colour, const char *type)
|
||||
{
|
||||
@ -2503,30 +2573,28 @@ fallback_256:
|
||||
static void
|
||||
tty_default_colours(struct grid_cell *gc, struct window_pane *wp)
|
||||
{
|
||||
struct window *w = wp->window;
|
||||
struct options *oo = w->options;
|
||||
struct style *active, *pane, *window;
|
||||
int c;
|
||||
struct options *oo = wp->options;
|
||||
struct style *style, *active_style;
|
||||
int c;
|
||||
|
||||
if (w->flags & WINDOW_STYLECHANGED) {
|
||||
w->flags &= ~WINDOW_STYLECHANGED;
|
||||
active = options_get_style(oo, "window-active-style");
|
||||
style_copy(&w->active_style, active);
|
||||
window = options_get_style(oo, "window-style");
|
||||
style_copy(&w->style, window);
|
||||
if (wp->flags & PANE_STYLECHANGED) {
|
||||
wp->flags &= ~PANE_STYLECHANGED;
|
||||
|
||||
active_style = options_get_style(oo, "window-active-style");
|
||||
style = options_get_style(oo, "window-style");
|
||||
|
||||
style_copy(&wp->cached_active_style, active_style);
|
||||
style_copy(&wp->cached_style, style);
|
||||
} else {
|
||||
active = &w->active_style;
|
||||
window = &w->style;
|
||||
active_style = &wp->cached_active_style;
|
||||
style = &wp->cached_style;
|
||||
}
|
||||
pane = &wp->style;
|
||||
|
||||
if (gc->fg == 8) {
|
||||
if (pane->gc.fg != 8)
|
||||
gc->fg = pane->gc.fg;
|
||||
else if (wp == w->active && active->gc.fg != 8)
|
||||
gc->fg = active->gc.fg;
|
||||
if (wp == wp->window->active && active_style->gc.fg != 8)
|
||||
gc->fg = active_style->gc.fg;
|
||||
else
|
||||
gc->fg = window->gc.fg;
|
||||
gc->fg = style->gc.fg;
|
||||
|
||||
if (gc->fg != 8) {
|
||||
c = window_pane_get_palette(wp, gc->fg);
|
||||
@ -2536,12 +2604,10 @@ tty_default_colours(struct grid_cell *gc, struct window_pane *wp)
|
||||
}
|
||||
|
||||
if (gc->bg == 8) {
|
||||
if (pane->gc.bg != 8)
|
||||
gc->bg = pane->gc.bg;
|
||||
else if (wp == w->active && active->gc.bg != 8)
|
||||
gc->bg = active->gc.bg;
|
||||
if (wp == wp->window->active && active_style->gc.bg != 8)
|
||||
gc->bg = active_style->gc.bg;
|
||||
else
|
||||
gc->bg = window->gc.bg;
|
||||
gc->bg = style->gc.bg;
|
||||
|
||||
if (gc->bg != 8) {
|
||||
c = window_pane_get_palette(wp, gc->bg);
|
||||
|
@ -245,7 +245,7 @@ window_buffer_draw(__unused void *modedata, void *itemdata,
|
||||
at = 0;
|
||||
while (end != pdata + psize && *end != '\n') {
|
||||
if ((sizeof line) - at > 5) {
|
||||
cp = vis(line + at, *end, VIS_TAB|VIS_OCTAL, 0);
|
||||
cp = vis(line + at, *end, VIS_OCTAL|VIS_TAB, 0);
|
||||
at = cp - line;
|
||||
}
|
||||
end++;
|
||||
|
@ -577,6 +577,7 @@ window_copy_resize(struct window_mode_entry *wme, u_int sx, u_int sy)
|
||||
struct window_copy_mode_data *data = wme->data;
|
||||
struct screen *s = &data->screen;
|
||||
struct screen_write_ctx ctx;
|
||||
int search;
|
||||
|
||||
screen_resize(s, sx, sy, 1);
|
||||
if (data->backing != &wp->base)
|
||||
@ -589,13 +590,15 @@ window_copy_resize(struct window_mode_entry *wme, u_int sx, u_int sy)
|
||||
if (data->oy > screen_hsize(data->backing))
|
||||
data->oy = screen_hsize(data->backing);
|
||||
|
||||
search = (data->searchmark != NULL);
|
||||
window_copy_clear_selection(wme);
|
||||
window_copy_clear_marks(wme);
|
||||
|
||||
screen_write_start(&ctx, NULL, s);
|
||||
window_copy_write_lines(wme, &ctx, 0, screen_size_y(s) - 1);
|
||||
screen_write_stop(&ctx);
|
||||
|
||||
if (data->searchmark != NULL)
|
||||
if (search)
|
||||
window_copy_search_marks(wme, NULL);
|
||||
data->searchx = data->cx;
|
||||
data->searchy = data->cy;
|
||||
@ -2700,7 +2703,7 @@ window_copy_append_selection(struct window_mode_entry *wme)
|
||||
struct window_pane *wp = wme->wp;
|
||||
char *buf;
|
||||
struct paste_buffer *pb;
|
||||
const char *bufdata, *bufname;
|
||||
const char *bufdata, *bufname = NULL;
|
||||
size_t len, bufsize;
|
||||
struct screen_write_ctx ctx;
|
||||
|
||||
@ -3027,8 +3030,8 @@ window_copy_cursor_up(struct window_mode_entry *wme, int scroll_only)
|
||||
if (data->lineflag == LINE_SEL_LEFT_RIGHT && oy == data->sely)
|
||||
window_copy_other_end(wme);
|
||||
|
||||
data->cx = data->lastcx;
|
||||
if (scroll_only || data->cy == 0) {
|
||||
data->cx = data->lastcx;
|
||||
window_copy_scroll_down(wme, 1);
|
||||
if (scroll_only) {
|
||||
if (data->cy == screen_size_y(s) - 1)
|
||||
@ -3037,7 +3040,7 @@ window_copy_cursor_up(struct window_mode_entry *wme, int scroll_only)
|
||||
window_copy_redraw_lines(wme, data->cy, 2);
|
||||
}
|
||||
} else {
|
||||
window_copy_update_cursor(wme, data->cx, data->cy - 1);
|
||||
window_copy_update_cursor(wme, data->lastcx, data->cy - 1);
|
||||
if (window_copy_update_selection(wme, 1)) {
|
||||
if (data->cy == screen_size_y(s) - 1)
|
||||
window_copy_redraw_lines(wme, data->cy, 1);
|
||||
@ -3077,13 +3080,13 @@ window_copy_cursor_down(struct window_mode_entry *wme, int scroll_only)
|
||||
if (data->lineflag == LINE_SEL_RIGHT_LEFT && oy == data->endsely)
|
||||
window_copy_other_end(wme);
|
||||
|
||||
data->cx = data->lastcx;
|
||||
if (scroll_only || data->cy == screen_size_y(s) - 1) {
|
||||
data->cx = data->lastcx;
|
||||
window_copy_scroll_up(wme, 1);
|
||||
if (scroll_only && data->cy > 0)
|
||||
window_copy_redraw_lines(wme, data->cy - 1, 2);
|
||||
} else {
|
||||
window_copy_update_cursor(wme, data->cx, data->cy + 1);
|
||||
window_copy_update_cursor(wme, data->lastcx, data->cy + 1);
|
||||
if (window_copy_update_selection(wme, 1))
|
||||
window_copy_redraw_lines(wme, data->cy - 1, 2);
|
||||
}
|
||||
|
185
window.c
185
window.c
@ -19,9 +19,11 @@
|
||||
#include <sys/types.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <fnmatch.h>
|
||||
#include <regex.h>
|
||||
#include <signal.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
@ -310,7 +312,7 @@ window_create(u_int sx, u_int sy)
|
||||
|
||||
w = xcalloc(1, sizeof *w);
|
||||
w->name = NULL;
|
||||
w->flags = WINDOW_STYLECHANGED;
|
||||
w->flags = 0;
|
||||
|
||||
TAILQ_INIT(&w->panes);
|
||||
w->active = NULL;
|
||||
@ -334,7 +336,7 @@ window_create(u_int sx, u_int sy)
|
||||
return (w);
|
||||
}
|
||||
|
||||
void
|
||||
static void
|
||||
window_destroy(struct window *w)
|
||||
{
|
||||
log_debug("window @%u destroyed (%d references)", w->id, w->references);
|
||||
@ -408,6 +410,7 @@ window_set_name(struct window *w, const char *new_name)
|
||||
void
|
||||
window_resize(struct window *w, u_int sx, u_int sy)
|
||||
{
|
||||
log_debug("%s: @%u resize %ux%u", __func__, w->id, sx, sy);
|
||||
w->sx = sx;
|
||||
w->sy = sy;
|
||||
}
|
||||
@ -447,31 +450,37 @@ window_set_active_pane(struct window *w, struct window_pane *wp, int notify)
|
||||
void
|
||||
window_redraw_active_switch(struct window *w, struct window_pane *wp)
|
||||
{
|
||||
struct style *sy;
|
||||
struct style *sy1, *sy2;
|
||||
int c1, c2;
|
||||
|
||||
if (wp == w->active)
|
||||
return;
|
||||
|
||||
/*
|
||||
* If window-style and window-active-style are the same, we don't need
|
||||
* to redraw panes when switching active panes.
|
||||
*/
|
||||
sy = options_get_style(w->options, "window-active-style");
|
||||
if (style_equal(sy, options_get_style(w->options, "window-style")))
|
||||
return;
|
||||
|
||||
/*
|
||||
* If the now active or inactive pane do not have a custom style or if
|
||||
* the palette is different, they need to be redrawn.
|
||||
*/
|
||||
if (window_pane_get_palette(w->active, w->active->style.gc.fg) != -1 ||
|
||||
window_pane_get_palette(w->active, w->active->style.gc.bg) != -1 ||
|
||||
style_is_default(&w->active->style))
|
||||
w->active->flags |= PANE_REDRAW;
|
||||
if (window_pane_get_palette(wp, wp->style.gc.fg) != -1 ||
|
||||
window_pane_get_palette(wp, wp->style.gc.bg) != -1 ||
|
||||
style_is_default(&wp->style))
|
||||
wp->flags |= PANE_REDRAW;
|
||||
for (;;) {
|
||||
/*
|
||||
* If the active and inactive styles or palettes are different,
|
||||
* need to redraw the panes.
|
||||
*/
|
||||
sy1 = &wp->cached_style;
|
||||
sy2 = &wp->cached_active_style;
|
||||
if (!style_equal(sy1, sy2))
|
||||
wp->flags |= PANE_REDRAW;
|
||||
else {
|
||||
c1 = window_pane_get_palette(wp, sy1->gc.fg);
|
||||
c2 = window_pane_get_palette(wp, sy2->gc.fg);
|
||||
if (c1 != c2)
|
||||
wp->flags |= PANE_REDRAW;
|
||||
else {
|
||||
c1 = window_pane_get_palette(wp, sy1->gc.bg);
|
||||
c2 = window_pane_get_palette(wp, sy2->gc.bg);
|
||||
if (c1 != c2)
|
||||
wp->flags |= PANE_REDRAW;
|
||||
}
|
||||
}
|
||||
if (wp == w->active)
|
||||
break;
|
||||
wp = w->active;
|
||||
}
|
||||
}
|
||||
|
||||
struct window_pane *
|
||||
@ -775,6 +784,8 @@ window_pane_create(struct window *w, u_int sx, u_int sy, u_int hlimit)
|
||||
|
||||
wp = xcalloc(1, sizeof *wp);
|
||||
wp->window = w;
|
||||
wp->options = options_create(w->options);
|
||||
wp->flags = PANE_STYLECHANGED;
|
||||
|
||||
wp->id = next_window_pane_id++;
|
||||
RB_INSERT(window_pane_tree, &all_window_panes, wp);
|
||||
@ -802,8 +813,8 @@ window_pane_create(struct window *w, u_int sx, u_int sy, u_int hlimit)
|
||||
wp->pipe_event = NULL;
|
||||
|
||||
wp->saved_grid = NULL;
|
||||
|
||||
style_set(&wp->style, &grid_default_cell);
|
||||
wp->saved_cx = UINT_MAX;
|
||||
wp->saved_cy = UINT_MAX;
|
||||
|
||||
screen_init(&wp->base, sx, sy, hlimit);
|
||||
wp->screen = &wp->base;
|
||||
@ -850,6 +861,7 @@ window_pane_destroy(struct window_pane *wp)
|
||||
|
||||
RB_REMOVE(window_pane_tree, &all_window_panes, wp);
|
||||
|
||||
options_free(wp->options);
|
||||
free((void *)wp->cwd);
|
||||
free(wp->shell);
|
||||
cmd_free_argv(wp->argc, wp->argv);
|
||||
@ -913,6 +925,7 @@ window_pane_resize(struct window_pane *wp, u_int sx, u_int sy)
|
||||
wp->sx = sx;
|
||||
wp->sy = sy;
|
||||
|
||||
log_debug("%s: %%%u resize %ux%u", __func__, wp->id, sx, sy);
|
||||
screen_resize(&wp->base, sx, sy, wp->saved_grid == NULL);
|
||||
|
||||
wme = TAILQ_FIRST(&wp->modes);
|
||||
@ -935,7 +948,7 @@ window_pane_alternate_on(struct window_pane *wp, struct grid_cell *gc,
|
||||
|
||||
if (wp->saved_grid != NULL)
|
||||
return;
|
||||
if (!options_get_number(wp->window->options, "alternate-screen"))
|
||||
if (!options_get_number(wp->options, "alternate-screen"))
|
||||
return;
|
||||
sx = screen_size_x(s);
|
||||
sy = screen_size_y(s);
|
||||
@ -963,9 +976,24 @@ window_pane_alternate_off(struct window_pane *wp, struct grid_cell *gc,
|
||||
struct screen *s = &wp->base;
|
||||
u_int sx, sy;
|
||||
|
||||
if (wp->saved_grid == NULL)
|
||||
if (!options_get_number(wp->options, "alternate-screen"))
|
||||
return;
|
||||
if (!options_get_number(wp->window->options, "alternate-screen"))
|
||||
|
||||
/*
|
||||
* Restore the cursor position and cell. This happens even if not
|
||||
* currently in the alternate screen.
|
||||
*/
|
||||
if (cursor && wp->saved_cx != UINT_MAX && wp->saved_cy != UINT_MAX) {
|
||||
s->cx = wp->saved_cx;
|
||||
if (s->cx > screen_size_x(s) - 1)
|
||||
s->cx = screen_size_x(s) - 1;
|
||||
s->cy = wp->saved_cy;
|
||||
if (s->cy > screen_size_y(s) - 1)
|
||||
s->cy = screen_size_y(s) - 1;
|
||||
memcpy(gc, &wp->saved_cell, sizeof *gc);
|
||||
}
|
||||
|
||||
if (wp->saved_grid == NULL)
|
||||
return;
|
||||
sx = screen_size_x(s);
|
||||
sy = screen_size_y(s);
|
||||
@ -977,17 +1005,8 @@ window_pane_alternate_off(struct window_pane *wp, struct grid_cell *gc,
|
||||
if (sy > wp->saved_grid->sy)
|
||||
screen_resize(s, sx, wp->saved_grid->sy, 1);
|
||||
|
||||
/* Restore the grid, cursor position and cell. */
|
||||
/* Restore the saved grid. */
|
||||
grid_duplicate_lines(s->grid, screen_hsize(s), wp->saved_grid, 0, sy);
|
||||
if (cursor)
|
||||
s->cx = wp->saved_cx;
|
||||
if (s->cx > screen_size_x(s) - 1)
|
||||
s->cx = screen_size_x(s) - 1;
|
||||
if (cursor)
|
||||
s->cy = wp->saved_cy;
|
||||
if (s->cy > screen_size_y(s) - 1)
|
||||
s->cy = screen_size_y(s) - 1;
|
||||
memcpy(gc, &wp->saved_cell, sizeof *gc);
|
||||
|
||||
/*
|
||||
* Turn history back on (so resize can use it) and then resize back to
|
||||
@ -1137,7 +1156,7 @@ window_pane_reset_mode(struct window_pane *wp)
|
||||
} else {
|
||||
log_debug("%s: next mode is %s", __func__, next->mode->name);
|
||||
wp->screen = next->screen;
|
||||
if (next != NULL && next->mode->resize != NULL)
|
||||
if (next->mode->resize != NULL)
|
||||
next->mode->resize(next, wp->sx, wp->sy);
|
||||
}
|
||||
wp->flags |= (PANE_REDRAW|PANE_CHANGED);
|
||||
@ -1199,24 +1218,48 @@ window_pane_visible(struct window_pane *wp)
|
||||
}
|
||||
|
||||
u_int
|
||||
window_pane_search(struct window_pane *wp, const char *searchstr)
|
||||
window_pane_search(struct window_pane *wp, const char *term, int regex,
|
||||
int ignore)
|
||||
{
|
||||
struct screen *s = &wp->base;
|
||||
char *newsearchstr, *line;
|
||||
regex_t r;
|
||||
char *new = NULL, *line;
|
||||
u_int i;
|
||||
int flags = 0, found;
|
||||
size_t n;
|
||||
|
||||
xasprintf(&newsearchstr, "*%s*", searchstr);
|
||||
if (!regex) {
|
||||
if (ignore)
|
||||
flags |= FNM_CASEFOLD;
|
||||
xasprintf(&new, "*%s*", term);
|
||||
} else {
|
||||
if (ignore)
|
||||
flags |= REG_ICASE;
|
||||
if (regcomp(&r, term, flags|REG_EXTENDED) != 0)
|
||||
return (0);
|
||||
}
|
||||
|
||||
for (i = 0; i < screen_size_y(s); i++) {
|
||||
line = grid_view_string_cells(s->grid, 0, i, screen_size_x(s));
|
||||
if (fnmatch(newsearchstr, line, 0) == 0) {
|
||||
free(line);
|
||||
break;
|
||||
for (n = strlen(line); n > 0; n--) {
|
||||
if (!isspace((u_char)line[n - 1]))
|
||||
break;
|
||||
line[n - 1] = '\0';
|
||||
}
|
||||
log_debug("%s: %s", __func__, line);
|
||||
if (!regex)
|
||||
found = (fnmatch(new, line, 0) == 0);
|
||||
else
|
||||
found = (regexec(&r, line, 0, NULL, 0) == 0);
|
||||
free(line);
|
||||
if (found)
|
||||
break;
|
||||
}
|
||||
if (!regex)
|
||||
free(new);
|
||||
else
|
||||
regfree(&r);
|
||||
|
||||
free(newsearchstr);
|
||||
if (i == screen_size_y(s))
|
||||
return (0);
|
||||
return (i + 1);
|
||||
@ -1248,25 +1291,35 @@ window_pane_choose_best(struct window_pane **list, u_int size)
|
||||
struct window_pane *
|
||||
window_pane_find_up(struct window_pane *wp)
|
||||
{
|
||||
struct window *w;
|
||||
struct window_pane *next, *best, **list;
|
||||
u_int edge, left, right, end, size;
|
||||
int status, found;
|
||||
|
||||
if (wp == NULL)
|
||||
return (NULL);
|
||||
status = options_get_number(wp->window->options, "pane-border-status");
|
||||
w = wp->window;
|
||||
status = options_get_number(w->options, "pane-border-status");
|
||||
|
||||
list = NULL;
|
||||
size = 0;
|
||||
|
||||
edge = wp->yoff;
|
||||
if (edge == (status == 1 ? 1 : 0))
|
||||
edge = wp->window->sy + 1 - (status == 2 ? 1 : 0);
|
||||
if (status == PANE_STATUS_TOP) {
|
||||
if (edge == 1)
|
||||
edge = w->sy + 1;
|
||||
} else if (status == PANE_STATUS_BOTTOM) {
|
||||
if (edge == 0)
|
||||
edge = w->sy;
|
||||
} else {
|
||||
if (edge == 0)
|
||||
edge = w->sy + 1;
|
||||
}
|
||||
|
||||
left = wp->xoff;
|
||||
right = wp->xoff + wp->sx;
|
||||
|
||||
TAILQ_FOREACH(next, &wp->window->panes, entry) {
|
||||
TAILQ_FOREACH(next, &w->panes, entry) {
|
||||
if (next == wp)
|
||||
continue;
|
||||
if (next->yoff + next->sy + 1 != edge)
|
||||
@ -1295,25 +1348,35 @@ window_pane_find_up(struct window_pane *wp)
|
||||
struct window_pane *
|
||||
window_pane_find_down(struct window_pane *wp)
|
||||
{
|
||||
struct window *w;
|
||||
struct window_pane *next, *best, **list;
|
||||
u_int edge, left, right, end, size;
|
||||
int status, found;
|
||||
|
||||
if (wp == NULL)
|
||||
return (NULL);
|
||||
status = options_get_number(wp->window->options, "pane-border-status");
|
||||
w = wp->window;
|
||||
status = options_get_number(w->options, "pane-border-status");
|
||||
|
||||
list = NULL;
|
||||
size = 0;
|
||||
|
||||
edge = wp->yoff + wp->sy + 1;
|
||||
if (edge >= wp->window->sy - (status == 2 ? 1 : 0))
|
||||
edge = (status == 1 ? 1 : 0);
|
||||
if (status == PANE_STATUS_TOP) {
|
||||
if (edge >= w->sy)
|
||||
edge = 1;
|
||||
} else if (status == PANE_STATUS_BOTTOM) {
|
||||
if (edge >= w->sy - 1)
|
||||
edge = 0;
|
||||
} else {
|
||||
if (edge >= w->sy)
|
||||
edge = 0;
|
||||
}
|
||||
|
||||
left = wp->xoff;
|
||||
right = wp->xoff + wp->sx;
|
||||
|
||||
TAILQ_FOREACH(next, &wp->window->panes, entry) {
|
||||
TAILQ_FOREACH(next, &w->panes, entry) {
|
||||
if (next == wp)
|
||||
continue;
|
||||
if (next->yoff != edge)
|
||||
@ -1342,24 +1405,26 @@ window_pane_find_down(struct window_pane *wp)
|
||||
struct window_pane *
|
||||
window_pane_find_left(struct window_pane *wp)
|
||||
{
|
||||
struct window *w;
|
||||
struct window_pane *next, *best, **list;
|
||||
u_int edge, top, bottom, end, size;
|
||||
int found;
|
||||
|
||||
if (wp == NULL)
|
||||
return (NULL);
|
||||
w = wp->window;
|
||||
|
||||
list = NULL;
|
||||
size = 0;
|
||||
|
||||
edge = wp->xoff;
|
||||
if (edge == 0)
|
||||
edge = wp->window->sx + 1;
|
||||
edge = w->sx + 1;
|
||||
|
||||
top = wp->yoff;
|
||||
bottom = wp->yoff + wp->sy;
|
||||
|
||||
TAILQ_FOREACH(next, &wp->window->panes, entry) {
|
||||
TAILQ_FOREACH(next, &w->panes, entry) {
|
||||
if (next == wp)
|
||||
continue;
|
||||
if (next->xoff + next->sx + 1 != edge)
|
||||
@ -1388,24 +1453,26 @@ window_pane_find_left(struct window_pane *wp)
|
||||
struct window_pane *
|
||||
window_pane_find_right(struct window_pane *wp)
|
||||
{
|
||||
struct window *w;
|
||||
struct window_pane *next, *best, **list;
|
||||
u_int edge, top, bottom, end, size;
|
||||
int found;
|
||||
|
||||
if (wp == NULL)
|
||||
return (NULL);
|
||||
w = wp->window;
|
||||
|
||||
list = NULL;
|
||||
size = 0;
|
||||
|
||||
edge = wp->xoff + wp->sx + 1;
|
||||
if (edge >= wp->window->sx)
|
||||
if (edge >= w->sx)
|
||||
edge = 0;
|
||||
|
||||
top = wp->yoff;
|
||||
bottom = wp->yoff + wp->sy;
|
||||
|
||||
TAILQ_FOREACH(next, &wp->window->panes, entry) {
|
||||
TAILQ_FOREACH(next, &w->panes, entry) {
|
||||
if (next == wp)
|
||||
continue;
|
||||
if (next->xoff != edge)
|
||||
@ -1487,7 +1554,7 @@ window_pane_input_callback(struct client *c, int closed, void *data)
|
||||
c->stdin_callback = NULL;
|
||||
server_client_unref(c);
|
||||
|
||||
cdata->item->flags &= ~CMDQ_WAITING;
|
||||
cmdq_continue(cdata->item);
|
||||
free(cdata);
|
||||
|
||||
return;
|
||||
|
Loading…
Reference in New Issue
Block a user