Merge branch 'master' into floating_panes

This commit is contained in:
Dane Jensen
2026-06-14 19:54:43 -07:00
23 changed files with 749 additions and 120 deletions

View File

@@ -47,8 +47,8 @@ const struct cmd_entry cmd_choose_client_entry = {
.name = "choose-client",
.alias = NULL,
.args = { "F:f:hK:kNO:rt:yZ", 0, 1, cmd_choose_tree_args_parse },
.usage = "[-hkNrZ] [-F format] [-f filter] [-K key-format] "
.args = { "F:f:hiK:kNO:rt:yZ", 0, 1, cmd_choose_tree_args_parse },
.usage = "[-hikNrZ] [-F format] [-f filter] [-K key-format] "
"[-O sort-order] " CMD_TARGET_PANE_USAGE " [template]",
.target = { 't', CMD_FIND_PANE, 0 },

View File

@@ -49,8 +49,10 @@ const struct cmd_entry cmd_move_pane_entry = {
.name = "move-pane",
.alias = "movep",
.args = { "bdfhvp:l:s:t:", 0, 0, NULL },
.usage = "[-bdfhv] [-l size] " CMD_SRCDST_PANE_USAGE,
.args = { "bdfhvl:L::P:R::s:t:U::X:Y:z:", 0, 0, NULL },
.usage = "[-bdfhv] [-D lines] [-l size] [-L columns] [-P position] "
"[-R columns] " CMD_SRCDST_PANE_USAGE " [-U lines] "
"[-X x-position] [-Y y-position] [-z z-index]",
.source = { 's', CMD_FIND_PANE, CMD_FIND_DEFAULT_MARKED },
.target = { 't', CMD_FIND_PANE, 0 },
@@ -59,6 +61,231 @@ const struct cmd_entry cmd_move_pane_entry = {
.exec = cmd_join_pane_exec
};
static enum cmd_retval
cmd_join_pane_place(struct cmdq_item *item, struct winlink *wl,
struct window_pane *wp, const char *position)
{
struct window *w = wl->window;
struct layout_cell *lc = wp->layout_cell;
struct window_pane *owp;
int wx = w->sx, wy = w->sy, px = lc->sx;
int py = lc->sy, xoff = lc->xoff, yoff = lc->yoff;
if (strcmp(position, "top-left") == 0) {
xoff = 1;
yoff = 1;
} else if (strcmp(position, "top-centre") == 0 ||
strcmp(position, "top-center") == 0) {
xoff = (wx - px) / 2;
yoff = 1;
} else if (strcmp(position, "top-right") == 0) {
xoff = wx - px - 1;
yoff = 1;
} else if (strcmp(position, "centre-left") == 0 ||
strcmp(position, "center-left") == 0) {
xoff = 1;
yoff = (wy - py) / 2;
} else if (strcmp(position, "centre") == 0 ||
strcmp(position, "center") == 0) {
xoff = (wx - px) / 2;
yoff = (wy - py) / 2;
} else if (strcmp(position, "centre-right") == 0 ||
strcmp(position, "center-right") == 0) {
xoff = wx - px - 1;
yoff = (wy - py) / 2;
} else if (strcmp(position, "bottom-left") == 0) {
xoff = 1;
yoff = wy - py - 1;
} else if (strcmp(position, "bottom-centre") == 0 ||
strcmp(position, "bottom-center") == 0) {
xoff = (wx - px) / 2;
yoff = wy - py - 1;
} else if (strcmp(position, "bottom-right") == 0) {
xoff = wx - px - 1;
yoff = wy - py - 1;
} else if (strcmp(position, "top-left-centre") == 0 ||
strcmp(position, "top-left-center") == 0) {
xoff = wx / 4 - px / 2;
yoff = wy / 4 - py / 2;
} else if (strcmp(position, "top-right-centre") == 0 ||
strcmp(position, "top-right-center") == 0) {
xoff = (3 * wx) / 4 - px / 2;
yoff = wy / 4 - py / 2;
} else if (strcmp(position, "bottom-left-centre") == 0 ||
strcmp(position, "bottom-left-center") == 0) {
xoff = wx / 4 - px / 2;
yoff = (3 * wy) / 4 - py / 2;
} else if (strcmp(position, "bottom-right-centre") == 0 ||
strcmp(position, "bottom-right-center") == 0) {
xoff = (3 * wx) / 4 - px / 2;
yoff = (3 * wy) / 4 - py / 2;
} else if (strcmp(position, "front") == 0) {
TAILQ_REMOVE(&w->z_index, wp, zentry);
TAILQ_INSERT_HEAD(&w->z_index, wp, zentry);
} else if (strcmp(position, "back") == 0) {
TAILQ_REMOVE(&w->z_index, wp, zentry);
TAILQ_FOREACH(owp, &w->z_index, zentry) {
if (!window_pane_is_floating(owp))
break;
}
if (owp != NULL)
TAILQ_INSERT_BEFORE(owp, wp, zentry);
else
TAILQ_INSERT_TAIL(&w->z_index, wp, zentry);
} else if (strcmp(position, "forward") == 0) {
owp = TAILQ_PREV(wp, window_panes_zindex, zentry);
if (owp != NULL) {
TAILQ_REMOVE(&w->z_index, wp, zentry);
TAILQ_INSERT_BEFORE(owp, wp, zentry);
}
} else if (strcmp(position, "backward") == 0) {
owp = TAILQ_NEXT(wp, zentry);
if (owp != NULL && window_pane_is_floating(owp)) {
TAILQ_REMOVE(&w->z_index, wp, zentry);
TAILQ_INSERT_AFTER(&w->z_index, owp, wp, zentry);
}
} else if (strcmp(position, "forward-loop") == 0) {
owp = TAILQ_PREV(wp, window_panes_zindex, zentry);
TAILQ_REMOVE(&w->z_index, wp, zentry);
if (owp != NULL)
TAILQ_INSERT_BEFORE(owp, wp, zentry);
else {
TAILQ_FOREACH(owp, &w->z_index, zentry) {
if (!window_pane_is_floating(owp))
break;
}
if (owp != NULL)
TAILQ_INSERT_BEFORE(owp, wp, zentry);
else
TAILQ_INSERT_TAIL(&w->z_index, wp, zentry);
}
} else if (strcmp(position, "backward-loop") == 0) {
owp = TAILQ_NEXT(wp, zentry);
if (owp != NULL && window_pane_is_floating(owp)) {
TAILQ_REMOVE(&w->z_index, wp, zentry);
TAILQ_INSERT_AFTER(&w->z_index, owp, wp, zentry);
} else {
TAILQ_REMOVE(&w->z_index, wp, zentry);
TAILQ_INSERT_HEAD(&w->z_index, wp, zentry);
}
} else {
cmdq_error(item, "unknown position: %s", position);
return (CMD_RETURN_ERROR);
}
if (xoff != lc->xoff || yoff != lc->yoff) {
lc->xoff = xoff;
lc->yoff = yoff;
layout_fix_panes(w, NULL);
}
notify_window("window-layout-changed", w);
server_redraw_window(w);
return (CMD_RETURN_NORMAL);
}
static enum cmd_retval
cmd_join_pane_move(struct cmdq_item *item, struct args *args,
struct winlink *wl, struct window_pane *wp)
{
struct window *w = wl->window;
struct layout_cell *lc = wp->layout_cell;
const char *errstr, *argval;
const char flags[] = { 'U', 'D', 'L', 'R' };
char *cause = NULL, flag;
int xoff = lc->xoff, yoff = lc->yoff, adjust;
u_int i;
if (args_has(args, 'X')) {
xoff = args_percentage_and_expand(args, 'X', -(int)lc->sx,
w->sx, w->sx, item, &cause);
if (cause != NULL) {
cmdq_error(item, "position %s", cause);
free(cause);
return (CMD_RETURN_ERROR);
}
}
if (args_has(args, 'Y')) {
yoff = args_percentage_and_expand(args, 'Y', -(int)lc->sy,
w->sy, w->sy, item, &cause);
if (cause != NULL) {
cmdq_error(item, "position %s", cause);
free(cause);
return (CMD_RETURN_ERROR);
}
}
for (i = 0; i < nitems(flags); i++) {
flag = flags[i];
if (!args_has(args, flag))
continue;
argval = args_get(args, flag);
if (argval == NULL)
argval = "1";
adjust = strtonum(argval, INT_MIN, INT_MAX, &errstr);
if (errstr != NULL) {
cmdq_error(item, "offset %s", errstr);
return (CMD_RETURN_ERROR);
}
if (flag == 'U')
yoff -= adjust;
else if (flag == 'D')
yoff += adjust;
else if (flag == 'L')
xoff -= adjust;
else
xoff += adjust;
}
if (xoff != lc->xoff || yoff != lc->yoff) {
lc->xoff = xoff;
lc->yoff = yoff;
layout_fix_panes(w, NULL);
notify_window("window-layout-changed", w);
server_redraw_window(w);
}
return (CMD_RETURN_NORMAL);
}
static enum cmd_retval
cmd_join_pane_zindex(struct cmdq_item *item, struct winlink *wl,
struct window_pane *wp, const char *s)
{
struct window *w = wl->window;
struct window_pane *owp;
const char *errstr;
u_int n, z;
z = strtonum(s, 0, UINT_MAX, &errstr);
if (errstr != NULL) {
cmdq_error(item, "z-index %s", errstr);
return (CMD_RETURN_ERROR);
}
TAILQ_REMOVE(&w->z_index, wp, zentry);
n = 0;
TAILQ_FOREACH(owp, &w->z_index, zentry) {
if (!window_pane_is_floating(owp))
break;
if (n >= z)
break;
n++;
}
if (owp != NULL)
TAILQ_INSERT_BEFORE(owp, wp, zentry);
else
TAILQ_INSERT_TAIL(&w->z_index, wp, zentry);
notify_window("window-layout-changed", w);
server_redraw_window(w);
return (CMD_RETURN_NORMAL);
}
static enum cmd_retval
cmd_join_pane_exec(struct cmd *self, struct cmdq_item *item)
{
@@ -70,6 +297,7 @@ cmd_join_pane_exec(struct cmd *self, struct cmdq_item *item)
struct winlink *src_wl, *dst_wl;
struct window *src_w, *dst_w;
struct window_pane *src_wp, *dst_wp;
const char *s;
char *cause = NULL;
int flags = 0, dst_idx;
struct layout_cell *lc;
@@ -81,6 +309,24 @@ cmd_join_pane_exec(struct cmd *self, struct cmdq_item *item)
dst_idx = dst_wl->idx;
server_unzoom_window(dst_w);
if (cmd_get_entry(self) == &cmd_move_pane_entry) {
if (!window_pane_is_floating(dst_wp)) {
cmdq_error(item, "pane is not floating");
return (CMD_RETURN_ERROR);
}
if ((s = args_get(args, 'P')) != NULL)
return (cmd_join_pane_place(item, dst_wl, dst_wp, s));
if ((s = args_get(args, 'z')) != NULL)
return (cmd_join_pane_zindex(item, dst_wl, dst_wp, s));
if (args_has(args, 'X') ||
args_has(args, 'Y') ||
args_has(args, 'U') ||
args_has(args, 'D') ||
args_has(args, 'L') ||
args_has(args, 'R'))
return (cmd_join_pane_move(item, args, dst_wl, dst_wp));
}
src_wl = source->wl;
src_wp = source->wp;
src_w = src_wl->window;

View File

@@ -41,7 +41,7 @@ const struct cmd_entry cmd_resize_pane_entry = {
.alias = "resizep",
.args = { "D::L::MR::Tt:U::x:y:Z", 0, 1, NULL },
.usage = "[-MTZ] [-U lines] [-D lines] [-L columns] [-R columns] "
.usage = "[-MTZ] [-D lines] [-L columns] [-R columns] [-U lines] "
"[-x width] [-y height] " CMD_TARGET_PANE_USAGE,
.target = { 't', CMD_FIND_PANE, 0 },
@@ -118,7 +118,7 @@ cmd_resize_pane_exec(struct cmd *self, struct cmdq_item *item)
free(cause);
return (CMD_RETURN_ERROR);
}
status = options_get_number(w->options, "pane-border-status");
status = window_get_pane_status(w);
switch (status) {
case PANE_STATUS_TOP:
if (y != INT_MAX && wp->yoff == 1)

View File

@@ -119,7 +119,7 @@ cmd_split_window_exec(struct cmd *self, struct cmdq_item *item)
else
lc = layout_get_tiled_cell(item, args, w, wp, flags, &cause);
if (cause != NULL) {
cmdq_error(item, "size or position %s", cause);
cmdq_error(item, "%s", cause);
free(cause);
return (CMD_RETURN_ERROR);
}
@@ -189,10 +189,11 @@ cmd_split_window_exec(struct cmd *self, struct cmdq_item *item)
}
if (args_has(args, 'k') || args_has(args, 'm')) {
options_set_number(new_wp->options, "remain-on-exit", 3);
if (args_has(args, 'm'))
if (args_has(args, 'm')) {
options_set_string(new_wp->options,
"remain-on-exit-format",
0, "%s", args_get(args, 'm'));
"remain-on-exit-format", 0, "%s",
args_get(args, 'm'));
}
}
if (args_has(args, 'T')) {
title = format_single_from_target(item, args_get(args, 'T'));

View File

@@ -339,7 +339,7 @@ static int
getopt_internal(int nargc, char * const *nargv, const char *options,
const struct option *long_options, int *idx, int flags)
{
char *oli; /* option letter list index */
const char *oli; /* option letter list index */
int optchar, short_too;
static int posixly_correct = -1;

View File

@@ -152,7 +152,8 @@ environ_clear(struct environ *env, const char *name)
void
environ_put(struct environ *env, const char *var, int flags)
{
char *name, *value;
char *name;
const char *value;
value = strchr(var, '=');
if (value == NULL)

View File

@@ -118,6 +118,9 @@ format_job_cmp(struct format_job *fj1, struct format_job *fj2)
#define FORMAT_REPEAT 0x200000
#define FORMAT_QUOTE_ARGUMENTS 0x400000
#define FORMAT_RELATIVE 0x800000
#define FORMAT_CLIENT_TERMCAP 0x1000000
#define FORMAT_CLIENT_TERMFEAT 0x2000000
#define FORMAT_CLIENT_ENVIRON 0x4000000
/* Limit on recursion. */
#define FORMAT_LOOP_LIMIT 100
@@ -1162,7 +1165,7 @@ format_cb_pane_at_top(struct format_tree *ft)
return (NULL);
w = wp->window;
status = options_get_number(w->options, "pane-border-status");
status = window_get_pane_status(w);
if (status == PANE_STATUS_TOP)
flag = (wp->yoff == 1);
else
@@ -3792,7 +3795,7 @@ format_table_compare(const void *key0, const void *entry0)
}
/* Get a format callback. */
static struct format_table_entry *
static const struct format_table_entry *
format_table_get(const char *key)
{
return (bsearch(key, format_table, nitems(format_table),
@@ -4087,18 +4090,14 @@ format_relative_time(time_t t)
{
time_t now, age;
u_int d, h, m, s;
char out[32], sign;
char out[32];
time(&now);
if (t > now)
return (NULL);
if (t == now)
return (xstrdup("0s"));
if (t > now) {
sign = '+';
age = t - now;
} else {
sign = '-';
age = now - t;
}
age = now - t;
d = age / 86400;
h = (age % 86400) / 3600;
@@ -4107,21 +4106,21 @@ format_relative_time(time_t t)
if (d != 0) {
if (h != 0)
xsnprintf(out, sizeof out, "%c%ud%uh", sign, d, h);
xsnprintf(out, sizeof out, "%ud%uh", d, h);
else
xsnprintf(out, sizeof out, "%c%ud", sign, d);
xsnprintf(out, sizeof out, "%ud", d);
} else if (h != 0) {
if (m != 0)
xsnprintf(out, sizeof out, "%c%uh%um", sign, h, m);
xsnprintf(out, sizeof out, "%uh%um", h, m);
else
xsnprintf(out, sizeof out, "%c%uh", sign, h);
xsnprintf(out, sizeof out, "%uh", h);
} else if (m != 0) {
if (s != 0)
xsnprintf(out, sizeof out, "%c%um%us", sign, m, s);
xsnprintf(out, sizeof out, "%um%us", m, s);
else
xsnprintf(out, sizeof out, "%c%um", sign, m);
xsnprintf(out, sizeof out, "%um", m);
} else
xsnprintf(out, sizeof out, "%c%us", sign, s);
xsnprintf(out, sizeof out, "%us", s);
return (xstrdup(out));
}
@@ -4130,7 +4129,7 @@ static char *
format_find(struct format_tree *ft, const char *key, int modifiers,
const char *time_format)
{
struct format_table_entry *fte;
const struct format_table_entry *fte;
void *value;
struct format_entry *fe, fe_find;
struct environ_entry *envent;
@@ -4443,7 +4442,7 @@ format_build_modifiers(struct format_expand_state *es, const char **s,
/*
* Modifiers are a ; separated list of the forms:
* l,m,C,a,b,c,d,n,t,w,q,E,T,S,W,P,R,<,>
* l,m,C,a,b,c,d,I,n,t,w,q,E,T,S,W,P,R,<,>
* =a
* =/a
* =/a/
@@ -4484,7 +4483,7 @@ format_build_modifiers(struct format_expand_state *es, const char **s,
}
/* Now try single character with arguments. */
if (strchr("mCLNPSst=pReqW", cp[0]) == NULL)
if (strchr("ImCLNPSst=pReqW", cp[0]) == NULL)
break;
c = cp[0];
@@ -5125,6 +5124,7 @@ format_replace(struct format_expand_state *es, const char *key, size_t keylen,
struct format_modifier *bool_op_n = NULL;
u_int i, count, nsub = 0, nrep;
struct format_expand_state next;
struct environ_entry *envent;
/* Set sorting defaults. */
sc->order = SORT_ORDER;
@@ -5207,6 +5207,16 @@ format_replace(struct format_expand_state *es, const char *key, size_t keylen,
case 'n':
modifiers |= FORMAT_LENGTH;
break;
case 'I':
if (fm->argc < 1)
break;
if (strchr(fm->argv[0], 'f') != NULL)
modifiers |= FORMAT_CLIENT_TERMFEAT;
if (strchr(fm->argv[0], 'c') != NULL)
modifiers |= FORMAT_CLIENT_TERMCAP;
if (strchr(fm->argv[0], 'e') != NULL)
modifiers |= FORMAT_CLIENT_ENVIRON;
break;
case 't':
modifiers |= FORMAT_TIMESTRING;
if (fm->argc < 1)
@@ -5218,7 +5228,8 @@ format_replace(struct format_expand_state *es, const char *key, size_t keylen,
else if (fm->argc >= 2 &&
strchr(fm->argv[0], 'f') != NULL) {
free(time_format);
time_format = format_strip(es, fm->argv[1]);
time_format = format_strip(es,
fm->argv[1]);
}
break;
case 'q':
@@ -5333,6 +5344,38 @@ format_replace(struct format_expand_state *es, const char *key, size_t keylen,
}
}
/* Look up client capability, feature or environment. */
if ((modifiers & FORMAT_CLIENT_TERMCAP) ||
(modifiers & FORMAT_CLIENT_TERMFEAT) ||
(modifiers & FORMAT_CLIENT_ENVIRON)) {
if (ft->c == NULL ||
ft->c->tty.term == NULL ||
ft->c->flags & CLIENT_UNATTACHEDFLAGS) {
value = xstrdup("");
goto done;
}
if (modifiers & FORMAT_CLIENT_TERMCAP) {
if (tty_term_has_name(ft->c->tty.term, copy))
value = xstrdup("1");
else
value = xstrdup("0");
}
if (modifiers & FORMAT_CLIENT_TERMFEAT) {
if (tty_feature_present(ft->c->tty.term, copy))
value = xstrdup("1");
else
value = xstrdup("0");
}
if (modifiers & FORMAT_CLIENT_ENVIRON) {
envent = environ_find(ft->c->environ, copy);
if (envent != NULL && envent->value != NULL)
value = xstrdup(envent->value);
else
value = xstrdup("");
}
goto done;
}
/* Is this a literal string? */
if (modifiers & FORMAT_LITERAL) {
format_log(es, "literal string is '%s'", copy);

View File

@@ -483,7 +483,7 @@ input_key_vt10x(struct bufferevent *bev, key_code key)
{
struct utf8_data ud;
key_code onlykey;
char *p;
const char *p;
static const char *standard_map[2] = {
"1!9(0)=+;:'\",<.>/-8? 2",
"119900=+;;'',,..\x1f\x1f\x7f\x7f\0\0",

16
input.c
View File

@@ -1365,7 +1365,7 @@ input_esc_dispatch(struct input_ctx *ictx)
{
struct screen_write_ctx *sctx = &ictx->ctx;
struct screen *s = sctx->s;
struct input_table_entry *entry;
const struct input_table_entry *entry;
if (ictx->flags & INPUT_DISCARD)
return (0);
@@ -1439,12 +1439,12 @@ input_esc_dispatch(struct input_ctx *ictx)
static int
input_csi_dispatch(struct input_ctx *ictx)
{
struct screen_write_ctx *sctx = &ictx->ctx;
struct screen *s = sctx->s;
struct input_table_entry *entry;
struct options *oo;
int i, n, m, ek, set, p;
u_int cx, bg = ictx->cell.cell.bg;
struct screen_write_ctx *sctx = &ictx->ctx;
struct screen *s = sctx->s;
const struct input_table_entry *entry;
struct options *oo;
int i, n, m, ek, set, p;
u_int cx, bg = ictx->cell.cell.bg;
if (ictx->flags & INPUT_DISCARD)
return (0);
@@ -3225,7 +3225,7 @@ static int
input_osc_52_parse(struct input_ctx *ictx, const char *p, u_char **out,
int *outlen, char *clip)
{
char *end;
const char *end;
size_t len;
const char *allow = "cpqs01234567";
u_int i, j = 0;

View File

@@ -409,8 +409,10 @@ key_bindings_init(void)
"bind -N 'Choose a window from a list' w { choose-tree -Zw }",
"bind -N 'Kill the active pane' x { confirm-before -p\"kill-pane #P? (y/n)\" kill-pane }",
"bind -N 'Zoom the active pane' z { resize-pane -Z }",
"bind -N 'Swap the active pane with the pane above' '{' { swap-pane -U }",
"bind -N 'Swap the active pane with the pane below' '}' { swap-pane -D }",
"bind -N 'Move pane to top-left corner' '{' { resize-pane -x50% -y50%; move-pane -P top-left }",
"bind -N 'Move pane to top-right corner' '}' { resize-pane -x50% -y50%; move-pane -P top-right }",
"bind -N 'Move pane to bottom-left corner' 'M-{' { resize-pane -x50% -y50%; move-pane -P bottom-left }",
"bind -N 'Move pane to bottom-right corner' 'M-}' { resize-pane -x50% -y50%; move-pane -P bottom-right }",
"bind -N 'Show messages' '~' { show-messages }",
"bind -N 'Enter copy mode and scroll up' PPage { copy-mode -u }",
"bind -N 'Select the pane above the active pane' -r Up { select-pane -U }",
@@ -432,13 +434,13 @@ key_bindings_init(void)
"bind -N 'Move the visible part of the window left' -r S-Left { refresh-client -L 10 }",
"bind -N 'Move the visible part of the window right' -r S-Right { refresh-client -R 10 }",
"bind -N 'Reset so the visible part of the window follows the cursor' -r DC { refresh-client -c }",
"bind -N 'Resize the pane up by 5' -r M-Up { resize-pane -U 5 }",
"bind -N 'Resize the pane up by 5' -r M-Up if -F '#{?floating_pane_flag}' { resizep -D-5 } { resize-pane -U 5 }",
"bind -N 'Resize the pane down by 5' -r M-Down { resize-pane -D 5 }",
"bind -N 'Resize the pane left by 5' -r M-Left { resize-pane -L 5 }",
"bind -N 'Resize the pane right by 5' -r M-Right { resize-pane -R 5 }",
"bind -N 'Resize the pane up' -r C-Up { resize-pane -U }",
"bind -N 'Resize the pane left by 5' -r M-Left if -F '#{?floating_pane_flag}' { resizep -R-5 } { resize-pane -L 5 }",
"bind -N 'Resize the pane right by 5' -r M-Right resize-pane -R 5",
"bind -N 'Resize the pane up' -r C-Up if -F '#{?floating_pane_flag}' { resizep -D-1 } { resize-pane -U }",
"bind -N 'Resize the pane down' -r C-Down { resize-pane -D }",
"bind -N 'Resize the pane left' -r C-Left { resize-pane -L }",
"bind -N 'Resize the pane left' -r C-Left if -F '#{?floating_pane_flag}' { resizep -R-1 } { resize-pane -L }",
"bind -N 'Resize the pane right' -r C-Right { resize-pane -R }",
/* Menu keys */

View File

@@ -379,6 +379,8 @@ layout_construct(struct layout_cell *lcparent, const char **layout,
struct layout_cell *lcchild;
*lc = layout_construct_cell(lcparent, layout);
if (*lc == NULL)
return (-1);
switch (**layout) {
case ',':

View File

@@ -319,7 +319,7 @@ layout_cell_is_first_tiled(struct layout_cell *lc)
static int
layout_cell_is_top(struct window *w, struct layout_cell *lc)
{
struct layout_cell *next;
struct layout_cell *next, *edge;
while (lc != w->layout_root) {
next = lc->parent;
@@ -337,15 +337,22 @@ layout_cell_is_top(struct window *w, struct layout_cell *lc)
static int
layout_cell_is_bottom(struct window *w, struct layout_cell *lc)
{
struct layout_cell *next;
struct layout_cell *next, *edge;
while (lc != w->layout_root) {
next = lc->parent;
if (next == NULL)
return (0);
if (next->type == LAYOUT_TOPBOTTOM &&
lc != TAILQ_LAST(&next->cells, layout_cells))
return (0);
if (next->type == LAYOUT_TOPBOTTOM) {
edge = TAILQ_LAST(&next->cells, layout_cells);
while (edge != NULL) {
if (~edge->flags & LAYOUT_CELL_FLOATING)
break;
edge = TAILQ_PREV(edge, layout_cells, entry);
}
if (lc != edge)
return (0);
}
lc = next;
}
return (1);
@@ -375,7 +382,7 @@ layout_fix_panes(struct window *w, struct window_pane *skip)
int status, scrollbars, sb_pos, sb_w, sb_pad;
u_int sx, sy;
status = options_get_number(w->options, "pane-border-status");
status = window_get_pane_status(w);
scrollbars = options_get_number(w->options, "pane-scrollbars");
sb_pos = options_get_number(w->options, "pane-scrollbars-position");
@@ -453,7 +460,7 @@ layout_resize_check(struct window *w, struct layout_cell *lc,
u_int available, minimum;
int status, scrollbars;
status = options_get_number(w->options, "pane-border-status");
status = window_get_pane_status(w);
scrollbars = options_get_number(w->options, "pane-scrollbars");
if (lc->type == LAYOUT_WINDOWPANE) {
@@ -892,6 +899,8 @@ layout_resize_floating_pane_to(struct window_pane *wp, enum layout_type type,
return;
}
if (size >= PANE_MINIMUM + 2)
size -= 2;
if (size < PANE_MINIMUM || size > PANE_MAXIMUM) {
*cause = xstrdup("size is too big or too small");
return;
@@ -937,6 +946,7 @@ layout_resize_floating_pane(struct window_pane *wp, enum layout_type type,
}
}
/* Resize a layout cell. */
void
layout_resize_layout(struct window *w, struct layout_cell *lc,
enum layout_type type, int change, int opposite)
@@ -982,8 +992,11 @@ layout_resize_pane(struct window_pane *wp, enum layout_type type, int change,
return;
/* If this is the last cell, move back one. */
if (lc == TAILQ_LAST(&lcparent->cells, layout_cells))
lc = TAILQ_PREV(lc, layout_cells, entry);
if (lc == TAILQ_LAST(&lcparent->cells, layout_cells)) {
do
lc = TAILQ_PREV(lc, layout_cells, entry);
while (lc->flags & LAYOUT_CELL_FLOATING);
}
layout_resize_layout(wp->window, lc, type, change, opposite);
}
@@ -1248,7 +1261,7 @@ layout_split_pane(struct window_pane *wp, enum layout_type type, int size,
lc = wp->window->layout_root;
else
lc = wp->layout_cell;
status = options_get_number(wp->window->options, "pane-border-status");
status = window_get_pane_status(wp->window);
scrollbars = options_get_number(wp->window->options, "pane-scrollbars");
/* Copy the old cell size. */
@@ -1475,7 +1488,7 @@ layout_spread_cell(struct window *w, struct layout_cell *parent)
number++;
if (number <= 1)
return (0);
status = options_get_number(w->options, "pane-border-status");
status = window_get_pane_status(w);
if (parent->type == LAYOUT_LEFTRIGHT)
size = parent->sx;
@@ -1614,30 +1627,43 @@ layout_get_floating_cell(struct cmdq_item *item, struct args *args,
struct layout_cell *lcnew;
u_int sx = w->sx / 2, sy = w->sy / 4;
int ox = INT_MAX, oy = INT_MAX;
char *error;
if (args_has(args, 'x')) {
sx = args_percentage_and_expand(args, 'x', 0, w->sx - 1, w->sx,
item, cause);
if (*cause != NULL)
item, &error);
if (error != NULL) {
xasprintf(cause, "position %s", error);
free(error);
return (NULL);
}
}
if (args_has(args, 'y')) {
sy = args_percentage_and_expand(args, 'y', 0, w->sy - 1, w->sy,
item, cause);
if (*cause != NULL)
item, &error);
if (error != NULL) {
xasprintf(cause, "position %s", error);
free(error);
return (NULL);
}
}
if (args_has(args, 'X')) {
ox = args_percentage_and_expand(args, 'X', -sx, w->sx,
w->sx, item, cause);
if (*cause != NULL)
w->sx, item, &error);
if (error != NULL) {
xasprintf(cause, "size %s", error);
free(error);
return (NULL);
}
}
if (args_has(args, 'Y')) {
oy = args_percentage_and_expand(args, 'Y', -sy, w->sy,
w->sy, item, cause);
if (*cause != NULL)
w->sy, item, &error);
if (error != NULL) {
xasprintf(cause, "size %s", error);
free(error);
return (NULL);
}
}
if (ox == INT_MAX) {

View File

@@ -49,6 +49,7 @@ struct mode_tree_data {
const struct menu_item *menu;
struct sort_criteria sort_crit;
const char *view_name;
mode_tree_build_cb buildcb;
mode_tree_draw_cb drawcb;
@@ -700,6 +701,12 @@ mode_tree_add(struct mode_tree_data *mtd, struct mode_tree_item *parent,
return (mti);
}
void
mode_tree_view_name(struct mode_tree_data *mtd, const char *name)
{
mtd->view_name = name;
}
void
mode_tree_draw_as_parent(struct mode_tree_item *mti)
{
@@ -884,9 +891,12 @@ mode_tree_draw(struct mode_tree_data *mtd)
screen_write_box(&ctx, w, sy - h, BOX_LINES_DEFAULT, NULL, NULL);
if (mtd->sort_crit.order_seq != NULL) {
xasprintf(&text, " %s (sort: %s%s)", mti->name,
xasprintf(&text, " %s (sort: %s%s)%s%s%s", mti->name,
sort_order_to_string(mtd->sort_crit.order),
mtd->sort_crit.reversed ? ", reversed" : "");
mtd->sort_crit.reversed ? ", reversed" : "",
mtd->view_name == NULL ? "" : " (view: ",
mtd->view_name == NULL ? "" : mtd->view_name,
mtd->view_name == NULL ? "" : ")");
} else
xasprintf(&text, " %s", mti->name);
if (w - 2 >= strlen(text)) {

View File

@@ -211,7 +211,7 @@ screen_redraw_pane_border(struct screen_redraw_ctx *ctx, struct window_pane *wp,
}
/* Top/bottom borders. */
if (vsplit && pane_status == PANE_STATUS_OFF && sb_w == 0) {
if (vsplit && pane_status == PANE_STATUS_OFF) {
if (wp->yoff == 0 && py == sy && px <= sx / 2)
return (SCREEN_REDRAW_BORDER_BOTTOM);
if (wp->yoff != 0 && py == wp->yoff - 1 && px > sx / 2)
@@ -220,9 +220,10 @@ screen_redraw_pane_border(struct screen_redraw_ctx *ctx, struct window_pane *wp,
if (sb_pos == PANE_SCROLLBARS_LEFT) {
if ((wp->xoff - sb_w == 0 || px >= wp->xoff - sb_w) &&
(px <= ex || (sb_w != 0 && px < ex + sb_w))) {
if (wp->yoff != 0 && py == wp->yoff - 1)
if (pane_status != PANE_STATUS_BOTTOM &&
wp->yoff != 0 && py == wp->yoff - 1)
return (SCREEN_REDRAW_BORDER_TOP);
if (py == ey)
if (pane_status != PANE_STATUS_TOP && py == ey)
return (SCREEN_REDRAW_BORDER_BOTTOM);
}
} else { /* sb_pos == PANE_SCROLLBARS_RIGHT */
@@ -619,7 +620,7 @@ screen_redraw_make_pane_status(struct client *c, struct window_pane *wp,
width = 0;
else
width = wp->sx + sb_w - 2;
max_width = (int)w->sx - (wp->xoff + 2) - sb_w;
max_width = (int)w->sx - (wp->xoff + 2);
if (max_width < 0)
max_width = 0;
if (width > (u_int)max_width)
@@ -703,7 +704,7 @@ screen_redraw_draw_pane_status(struct screen_redraw_ctx *ctx)
width = size;
} else if (xoff < ctx->ox && xoff + size > ctx->ox + ctx->sx) {
/* Both left and right not visible. */
l = ctx->ox;
l = ctx->ox - xoff;
x = 0;
width = ctx->sx;
} else if (xoff < ctx->ox) {
@@ -776,7 +777,6 @@ screen_redraw_set_context(struct client *c, struct screen_redraw_ctx *ctx)
struct session *s = c->session;
struct options *oo = s->options;
struct window *w = s->curw->window;
struct options *wo = w->options;
u_int lines;
memset(ctx, 0, sizeof *ctx);
@@ -789,11 +789,12 @@ screen_redraw_set_context(struct client *c, struct screen_redraw_ctx *ctx)
ctx->statustop = 1;
ctx->statuslines = lines;
ctx->pane_status = options_get_number(wo, "pane-border-status");
ctx->pane_lines = options_get_number(wo, "pane-border-lines");
ctx->pane_status = window_get_pane_status(w);
ctx->pane_lines = options_get_number(w->options, "pane-border-lines");
ctx->pane_scrollbars = options_get_number(wo, "pane-scrollbars");
ctx->pane_scrollbars_pos = options_get_number(wo,
ctx->pane_scrollbars = options_get_number(w->options,
"pane-scrollbars");
ctx->pane_scrollbars_pos = options_get_number(w->options,
"pane-scrollbars-position");
tty_window_offset(&c->tty, &ctx->ox, &ctx->oy, &ctx->sx, &ctx->sy);
@@ -1123,7 +1124,7 @@ screen_redraw_is_visible(struct visible_ranges *r, u_int px)
return (1);
for (i = 0; i < r->used; i++) {
ri = &r->ranges[i];
if (ri->nx != 0 && px >= ri->px && px <= ri->px + ri->nx)
if (ri->nx != 0 && px >= ri->px && px < ri->px + ri->nx)
return (1);
}
return (0);
@@ -1145,11 +1146,13 @@ screen_redraw_get_visible_ranges(struct window_pane *base_wp, int px,
u_int lb, rb, tb, bb;
u_int i, s;
if (px + width <= 0 || py < 0)
if (py < 0 || width == 0)
goto empty;
if (px < 0) {
if ((u_int)-px >= width)
goto empty;
width -= (u_int)-px;
px = 0;
width += px;
}
if (base_wp == NULL) {
@@ -1196,7 +1199,8 @@ screen_redraw_get_visible_ranges(struct window_pane *base_wp, int px,
(u_int)py < tb ||
(u_int)py > bb)
continue;
if (!window_pane_is_floating(wp) && (u_int)py == bb)
if (!window_pane_is_floating(wp) &&
((u_int)py == tb || (u_int)py == bb))
continue;
sb_w = wp->scrollbar_style.width + wp->scrollbar_style.pad;

View File

@@ -603,15 +603,14 @@ server_client_check_mouse_in_pane(struct window_pane *wp, int px, int py,
u_int *sl_mpos)
{
struct window *w = wp->window;
struct options *wo = w->options;
struct window_pane *fwp;
int pane_status, sb, sb_pos, sb_w, sb_pad;
int pane_status_line, sl_top, sl_bottom;
int bdr_bottom, bdr_top, bdr_left, bdr_right;
sb = options_get_number(wo, "pane-scrollbars");
sb_pos = options_get_number(wo, "pane-scrollbars-position");
pane_status = options_get_number(wo, "pane-border-status");
sb = options_get_number(w->options, "pane-scrollbars");
sb_pos = options_get_number(w->options, "pane-scrollbars-position");
pane_status = window_get_pane_status(w);
if (window_pane_show_scrollbar(wp, sb)) {
sb_w = wp->scrollbar_style.width;
@@ -915,8 +914,7 @@ have_event:
log_debug("mouse %u,%u on pane %%%u", x, y,
wp->id);
} else if (loc == KEYC_MOUSE_LOCATION_BORDER) {
sr = window_pane_border_status_get_range(wp, px,
py);
sr = window_pane_status_get_range(wp, px, py);
if (sr != NULL) {
n = sr->argument;
loc = KEYC_MOUSE_LOCATION_CONTROL0 + n;

113
tmux.1
View File

@@ -2324,6 +2324,11 @@ that line.
(emacs: C\-Down)
.Xc
Scroll down.
If
.Ic mode\-keys
is
.Ic vi ,
the cursor is fixed relative to the text.
.It Xo
.Ic scroll\-down\-and\-cancel
.Xc
@@ -2365,6 +2370,11 @@ that line.
(emacs: C\-Up)
.Xc
Scroll up.
If
.Ic mode\-keys
is
.Ic vi ,
the cursor is fixed relative to the text.
.It Xo
.Ic search\-again
(vi: n)
@@ -2868,7 +2878,7 @@ The
command works only if at least one client is attached.
.It Xo
.Ic choose\-tree
.Op Fl GhkNrswyZ
.Op Fl GhikNrswyZ
.Op Fl F Ar format
.Op Fl f Ar filter
.Op Fl K Ar key\-format
@@ -2920,6 +2930,7 @@ The following keys may be used in tree mode:
.It Li "O" Ta "Change sort order"
.It Li "r" Ta "Reverse sort order"
.It Li "v" Ta "Toggle preview"
.It Li "i" Ta "Change view (preview and client information)"
.It Li "F1 or C\-h" Ta "Display help"
.It Li "q" Ta "Exit mode"
.El
@@ -2959,6 +2970,8 @@ first.
.Pp
.Fl N
starts without the preview or if given twice with the larger preview.
.Fl i
starts showing client information instead of the preview.
.Fl h
hides the pane containing the mode.
.Fl k
@@ -3357,13 +3370,77 @@ The pane must not already be hidden.
.Tg movep
.It Xo Ic move\-pane
.Op Fl bdfhv
.Op Fl D Op Ar lines
.Op Fl l Ar size
.Op Fl L Op Ar columns
.Op Fl P Ar position
.Op Fl R Op Ar columns
.Op Fl s Ar src\-pane
.Op Fl t Ar dst\-pane
.Op Fl U Op Ar lines
.Op Fl X Ar x\-position
.Op Fl Y Ar y\-position
.Op Fl z Ar z\-index
.Xc
.D1 Pq alias: Ic movep
Does the same as
.Ic join\-pane .
.Ic join\-pane ,
except if given
.Fl D ,
.Fl L ,
.Fl P ,
.Fl R ,
.Fl U ,
.Fl X ,
.Fl Y
or
.Fl z
in which case move the target floating pane.
.Fl D ,
.Fl L ,
.Fl R
and
.Fl U
move it down, left, right or up by
.Ar lines
or
.Ar columns
(one if omitted).
.Fl P
moves it to
.Ar position ,
which may be one of:
.Bl -column "XXXXXXXXXXXXXXXXXX" "X"
.It Sy "Position" Ta Sy "Meaning"
.It Li "top-left" Ta "Top left"
.It Li "top-centre" Ta "Top and horizontal centre"
.It Li "top-right" Ta "Top right"
.It Li "centre-left" Ta "Vertical centre and left"
.It Li "centre" Ta "Centre"
.It Li "centre-right" Ta "Vertical centre and right"
.It Li "bottom-left" Ta "Bottom left"
.It Li "bottom-centre" Ta "Bottom and horizontal centre"
.It Li "bottom-right" Ta "Bottom right"
.It Li "top-left-centre" Ta "Centre of top-left quadrant"
.It Li "top-right-centre" Ta "Centre of top-right quadrant"
.It Li "bottom-left-centre" Ta "Centre of bottom-left quadrant"
.It Li "bottom-right-centre" Ta "Centre of botton-right quadrant"
.It Li "front" Ta "Front of floating panes"
.It Li "back" Ta "Back of floating panes"
.It Li "forward" Ta "Forward one floating pane"
.It Li "backward" Ta "Backward one floating pane"
.It Li "forward-loop" Ta "Forward but back if already at front"
.It Li "backward-loop" Ta "Backward but front if already at back"
.El
.Pp
.Fl X
and
.Fl Y
move it to an absolute position.
.Fl z
moves the pane to the given
.Ar z-index ,
where zero is the front.
.Tg movew
.It Xo Ic move\-window
.Op Fl abrdk
@@ -3665,13 +3742,13 @@ if specified, to
.Tg resizep
.It Xo Ic resize\-pane
.Op Fl MTZ
.Op Fl t Ar target\-pane
.Op Fl U Ar lines
.Op Fl D Ar lines
.Op Fl L Ar columns
.Op Fl R Ar columns
.Op Fl U Ar lines
.Op Fl x Ar width
.Op Fl y Ar height
.Op Fl t Ar target\-pane
.Xc
.D1 Pq alias: Ic resizep
Resize a pane, up, down, left or right by a specified adjustment with
@@ -3679,10 +3756,8 @@ Resize a pane, up, down, left or right by a specified adjustment with
.Fl D ,
.Fl L
or
.Fl R ,
or
to an absolute size
with
.Fl R ;
or to an absolute size with
.Fl x
or
.Fl y .
@@ -6527,9 +6602,9 @@ will use shorter but less accurate time format for times in the past.
.Ql r
.Pq Ql t/r
will show the time relative to the current time, for example
.Ql \-1m
.Ql \1m
or
.Ql +2m23s .
.Ql 2m23s .
A custom format may be given using an
.Ql f
suffix (note that
@@ -6546,6 +6621,24 @@ see
.Xr strftime 3 .
.Pp
The
.Ql I:\&
prefix will interrogate the client.
.Ql I/f
will be true if
.Nm
believes that the client supports the given terminal feature, for example
.Ql I/f:RGB ,
.Ql I/c
will be true if a client has the given
.Xr terminfo 3
capability, for example
.Ql I/c:smcup ,
and
.Ql I/e
gives the value of a client environment variable, for example
.Ql #{I/e:FOO} .
.Pp
The
.Ql b:\&
and
.Ql d:\&

10
tmux.h
View File

@@ -2784,6 +2784,7 @@ int tty_term_read_list(const char *, int, char ***, u_int *,
char **);
void tty_term_free_list(char **, u_int);
int tty_term_has(struct tty_term *, enum tty_code_code);
int tty_term_has_name(struct tty_term *, const char *);
const char *tty_term_string(struct tty_term *, enum tty_code_code);
const char *tty_term_string_i(struct tty_term *, enum tty_code_code, int);
const char *tty_term_string_ii(struct tty_term *, enum tty_code_code, int,
@@ -2801,6 +2802,7 @@ const char *tty_term_describe(struct tty_term *, enum tty_code_code);
/* tty-features.c */
void tty_add_features(int *, const char *, const char *);
const char *tty_get_features(int);
int tty_feature_present(struct tty_term *, const char *);
int tty_apply_features(struct tty_term *, int);
void tty_default_features(int *, const char *, u_int);
@@ -3529,8 +3531,9 @@ int window_pane_get_bg_control_client(struct window_pane *);
int window_get_bg_client(struct window_pane *);
enum client_theme window_pane_get_theme(struct window_pane *);
void window_pane_send_theme_update(struct window_pane *);
struct style_range *window_pane_border_status_get_range(struct window_pane *,
u_int, u_int);
int window_get_pane_status(struct window *);
struct style_range *window_pane_status_get_range(struct window_pane *, u_int,
u_int);
int window_pane_is_floating(struct window_pane *);
/* layout.c */
@@ -3628,6 +3631,7 @@ void mode_tree_resize(struct mode_tree_data *, u_int, u_int);
struct mode_tree_item *mode_tree_add(struct mode_tree_data *,
struct mode_tree_item *, void *, uint64_t, const char *,
const char *, int);
void mode_tree_view_name(struct mode_tree_data *, const char *);
void mode_tree_draw_as_parent(struct mode_tree_item *);
void mode_tree_no_tag(struct mode_tree_item *);
void mode_tree_align(struct mode_tree_item *, int);
@@ -3669,7 +3673,7 @@ int window_copy_get_current_offset(struct window_pane *, u_int *,
char *window_copy_get_hyperlink(struct window_pane *, u_int, u_int);
void window_copy_set_line_numbers(struct window_pane *, int);
/* window-option.c */
/* window-customize.c */
extern const struct window_mode window_customize_mode;
/* names.c */

View File

@@ -442,6 +442,45 @@ tty_get_features(int feat)
return (s);
}
int
tty_feature_present(struct tty_term *term, const char *name)
{
const struct tty_feature *tf = NULL;
const char *const *capability;
u_int i;
char *copy;
for (i = 0; i < nitems(tty_features); i++) {
tf = tty_features[i];
if (strcmp(tf->name, name) == 0) {
if (term->features & (1 << i))
return (1);
break;
}
}
/*
* We don't just have the feature flag set. Check if the capabilities
* supported by the client are actual set instead.
*/
if (tf == NULL || strcmp(name, "ignorefkeys") == 0)
return (0);
if (tf->flags != 0 && (term->flags & tf->flags) != tf->flags)
return (0);
capability = tf->capabilities;
while (*capability != NULL) {
copy = xstrdup(*capability);
copy[strcspn(copy, "=")] = '\0';
if (!tty_term_has_name(term, copy)) {
free(copy);
return (0);
}
free(copy);
capability++;
}
return (1);
}
int
tty_apply_features(struct tty_term *term, int feat)
{

View File

@@ -776,6 +776,18 @@ tty_term_has(struct tty_term *term, enum tty_code_code code)
return (term->codes[code].type != TTYCODE_NONE);
}
int
tty_term_has_name(struct tty_term *term, const char *name)
{
u_int i;
for (i = 0; i < tty_term_ncodes(); i++) {
if (strcmp(tty_term_codes[i].name, name) == 0)
return (tty_term_has(term, i));
}
return (0);
}
const char *
tty_term_string(struct tty_term *term, enum tty_code_code code)
{

View File

@@ -47,6 +47,93 @@ static void window_client_key(struct window_mode_entry *,
"M-#{a:#{e|+:97,#{e|-:#{line},10}}}" \
"}"
#define WINDOW_CLIENT_FEATURE(f) \
"#{?#{I/f:" #f "}," \
"#[fg=green],#[dim]}#{p/15:#{l:" #f "}}" \
"#[default]"
static const char *window_client_info_lines[] = {
"Client Name #[acs]x#[default] "
"#{client_name} "
"#[dim](PID #{client_pid})#[default]",
"Session #[acs]x#[default] "
"#{session_name}",
"Attach Time #[acs]x#[default] "
"#{t:client_created} "
"#[dim](#{t/r:client_created})#[default]",
"Activity Time #[acs]x#[default] "
"#{t:client_activity} "
"#[dim](#{t/r:client_activity})#[default]",
"Terminal Type #[acs]x#[default] "
"#{?client_termtype,#{client_termtype},Unknown}",
"TERM #[acs]x#[default] "
"#{client_termname}",
"Size #[acs]x#[default] "
"#{client_width}x#{client_height} "
"#[dim](cell #{client_cell_width}x#{client_cell_height})#[default]",
"Bytes Written #[acs]x#[default] "
"#{client_written} "
"#[dim](#{client_discarded} discarded)#[default]",
"Features #[acs]x#[default] "
WINDOW_CLIENT_FEATURE(256) " "
WINDOW_CLIENT_FEATURE(RGB) " "
WINDOW_CLIENT_FEATURE(bpaste) " "
WINDOW_CLIENT_FEATURE(ccolour),
" #[acs]x#[default] "
WINDOW_CLIENT_FEATURE(clipboard) " "
WINDOW_CLIENT_FEATURE(cstyle) " "
WINDOW_CLIENT_FEATURE(extkeys) " "
WINDOW_CLIENT_FEATURE(focus),
" #[acs]x#[default] "
WINDOW_CLIENT_FEATURE(hyperlinks) " "
WINDOW_CLIENT_FEATURE(ignorefkeys) " "
WINDOW_CLIENT_FEATURE(margins) " "
WINDOW_CLIENT_FEATURE(mouse),
" #[acs]x#[default] "
WINDOW_CLIENT_FEATURE(osc7) " "
WINDOW_CLIENT_FEATURE(overline) " "
WINDOW_CLIENT_FEATURE(progressbar) " "
WINDOW_CLIENT_FEATURE(rectfill),
" #[acs]x#[default] "
WINDOW_CLIENT_FEATURE(sixel) " "
WINDOW_CLIENT_FEATURE(strikethrough) " "
WINDOW_CLIENT_FEATURE(sync) " "
WINDOW_CLIENT_FEATURE(title),
" #[acs]x#[default] "
WINDOW_CLIENT_FEATURE(usstyle),
"#[acs]qqqqqqqqqqqqqqn#{R:q,#{window_width}}#[default]",
"prefix #[acs]x#[default] "
"#{prefix}",
"mouse #[acs]x#[default] "
"#{?mouse,#{?#{I/c:kmous},,#[fg=red]}on,#[dim]off} "
"#{?#{I/c:kmous},,#[align=right]unavailable: [kmous] missing}",
"set-clipboard #[acs]x#[default] "
"#{?#{!=:#{set-clipboard},off},#{?#{I/f:clipboard},,#[fg=red]}#{set-clipboard},#[dim]off} "
"#{?#{I/f:clipboard},,#[align=right]unavailable: [Ms] missing}",
"get-clipboard #[acs]x#[default] "
"#{?#{!=:#{get-clipboard},off},#{?#{I/f:clipboard},,#[fg=red]}#{get-clipboard},#[dim]off} "
"#{?#{I/f:clipboard},,#[align=right]unavailable: [Ms] missing}",
"focus-events #[acs]x#[default] "
"#{?focus-events,#{?#{I/f:focus},,#[fg=red]}on,#[dim]off} "
"#{?#{I/f:focus},,#[align=right]unavailable: [Enfcs] or [Dcfcs] missing}",
"extended-keys #[acs]x#[default] "
"#{?#{!=:#{extended-keys},off},#{?#{I/f:extkeys},,#[fg=red]}#{extended-keys},#[dim]off} "
"#{?#{I/f:extkeys},,#[align=right]unavailable: [Eneks] or [Dseks] missing}",
"set-titles #[acs]x#[default] "
"#{?set-titles,on,#[dim]off}",
"escape-time #[acs]x#[default] "
"#{escape-time} ms",
};
static const struct menu_item window_client_menu_items[] = {
{ "Detach", 'd', NULL },
{ "Detach Tagged", 'D', NULL },
@@ -82,7 +169,9 @@ struct window_client_modedata {
char *format;
char *key_format;
char *command;
int hide_preview_this_pane;
int preview_is_info;
struct window_client_itemdata **item_list;
u_int item_size;
@@ -162,6 +251,32 @@ window_client_build(void *modedata, struct sort_criteria *sort_crit,
}
}
static void
window_client_draw_info(__unused void *modedata, void *itemdata,
struct screen_write_ctx *ctx, u_int sx, u_int sy)
{
struct window_client_itemdata *item = itemdata;
struct client *c = item->c;
struct screen *s = ctx->s;
u_int cx = s->cx, cy = s->cy, i;
struct format_tree *ft;
char *expanded;
ft = format_create_defaults(NULL, c, NULL, NULL, NULL);
screen_write_cursormove(ctx, cx, cy, 0);
for (i = 0; i < nitems(window_client_info_lines); i++) {
if (i == sy)
break;
expanded = format_expand(ft, window_client_info_lines[i]);
screen_write_cursormove(ctx, cx, cy + i, 0);
format_draw(ctx, &grid_default_cell, sx, expanded, NULL, 0);
free(expanded);
}
format_free(ft);
}
static void
window_client_draw(void *modedata, void *itemdata,
struct screen_write_ctx *ctx, u_int sx, u_int sy)
@@ -175,6 +290,10 @@ window_client_draw(void *modedata, void *itemdata,
if (c->session == NULL || (c->flags & CLIENT_UNATTACHEDFLAGS))
return;
if (data->preview_is_info) {
window_client_draw_info(modedata, itemdata, ctx, sx, sy);
return;
}
wp = c->session->curw->window->active;
if (data->hide_preview_this_pane && wp == data->wp) {
if (!TAILQ_EMPTY(&c->session->curw->window->last_panes))
@@ -250,6 +369,7 @@ window_client_sort(struct sort_criteria *sort_crit)
}
static const char* window_client_help_lines[] = {
"\r\033[1m i \033[0m\016x\017 \033[0mToggle info view\n",
"\r\033[1m Enter \033[0m\016x\017 \033[0mChoose selected %1\n",
"\r\033[1m d \033[0m\016x\017 \033[0mDetach selected %1\n",
"\r\033[1m D \033[0m\016x\017 \033[0mDetach tagged %1s\n",
@@ -280,6 +400,7 @@ window_client_init(struct window_mode_entry *wme,
wme->data = data = xcalloc(1, sizeof *data);
data->wp = wp;
data->hide_preview_this_pane = args != NULL && args_has(args, 'h');
data->preview_is_info = args != NULL && args_has(args, 'i');
if (args == NULL || !args_has(args, 'F'))
data->format = xstrdup(WINDOW_CLIENT_DEFAULT_FORMAT);
@@ -300,6 +421,11 @@ window_client_init(struct window_mode_entry *wme,
window_client_help, data, window_client_menu_items, &s);
mode_tree_zoom(data->data, args);
if (data->preview_is_info)
mode_tree_view_name(data->data, "info");
else
mode_tree_view_name(data->data, "preview");
mode_tree_build(data->data);
mode_tree_draw(data->data);
@@ -389,6 +515,14 @@ window_client_key(struct window_mode_entry *wme, struct client *c,
mode_tree_each_tagged(mtd, window_client_do_detach, c, key, 0);
mode_tree_build(mtd);
break;
case 'i':
data->preview_is_info = !data->preview_is_info;
if (data->preview_is_info)
mode_tree_view_name(mtd, "info");
else
mode_tree_view_name(mtd, "preview");
mode_tree_build(mtd);
break;
case '\r':
item = mode_tree_get_current(mtd);
mode_tree_run_command(c, NULL, data->command, item->c->ttyname);

View File

@@ -175,7 +175,7 @@ window_clock_init(struct window_mode_entry *wme,
struct window_clock_mode_data *data;
struct screen *s;
wme->data = data = xmalloc(sizeof *data);
wme->data = data = xcalloc(1, sizeof *data);
data->tim = time(NULL);
evtimer_set(&data->timer, window_clock_timer_callback, wme);

View File

@@ -5102,14 +5102,10 @@ window_copy_set_line_numbers(struct window_pane *wp, int enabled)
struct window_mode_entry *wme = TAILQ_FIRST(&wp->modes);
struct window_copy_mode_data *data;
if (wme == NULL)
return;
if (wme->mode != &window_copy_mode)
if (wme == NULL || wme->mode != &window_copy_mode)
return;
data = wme->data;
if (data == NULL)
return;
if (data->line_numbers == enabled)
if (data == NULL || data->line_numbers == enabled)
return;
data->line_numbers = enabled;
window_copy_redraw_screen(wme);
@@ -6109,6 +6105,7 @@ static void
window_copy_cursor_up(struct window_mode_entry *wme, int scroll_only)
{
struct window_copy_mode_data *data = wme->data;
struct options *oo = wme->wp->window->options;
struct screen *s = &data->screen;
u_int ox, oy, px, py;
int norectsel;
@@ -6124,6 +6121,11 @@ 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);
if (scroll_only && options_get_number(oo, "mode-keys") == MODEKEY_VI) {
if (data->cy < screen_size_y(s) - 1)
window_copy_update_cursor(wme, data->cx, data->cy + 1);
}
if (scroll_only || data->cy == 0) {
if (norectsel)
data->cx = data->lastcx;
@@ -6183,6 +6185,7 @@ static void
window_copy_cursor_down(struct window_mode_entry *wme, int scroll_only)
{
struct window_copy_mode_data *data = wme->data;
struct options *oo = wme->wp->window->options;
struct screen *s = &data->screen;
u_int ox, oy, px, py;
int norectsel;
@@ -6198,6 +6201,11 @@ 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);
if (scroll_only && options_get_number(oo, "mode-keys") == MODEKEY_VI) {
if (data->cy > 0)
window_copy_update_cursor(wme, data->cx, data->cy - 1);
}
if (scroll_only || data->cy == screen_size_y(s) - 1) {
if (norectsel)
data->cx = data->lastcx;

View File

@@ -648,7 +648,7 @@ window_get_active_at(struct window *w, u_int x, u_int y)
int pane_status, xoff, yoff;
u_int sx, sy;
pane_status = options_get_number(w->options, "pane-border-status");
pane_status = window_get_pane_status(w);
if (pane_status == PANE_STATUS_TOP) {
/*
@@ -656,10 +656,12 @@ window_get_active_at(struct window *w, u_int x, u_int y)
* bottom border.
*/
TAILQ_FOREACH(wp, &w->z_index, zentry) {
if (!window_pane_visible(wp) || window_pane_is_floating(wp))
if (!window_pane_visible(wp) ||
window_pane_is_floating(wp))
continue;
window_pane_full_size_offset(wp, &xoff, &yoff, &sx, &sy);
window_pane_full_size_offset(wp, &xoff, &yoff, &sx,
&sy);
if ((int)x < xoff || x > xoff + sx)
continue;
if ((int)y == yoff - 1)
@@ -706,7 +708,7 @@ window_find_string(struct window *w, const char *s)
x = w->sx / 2;
y = w->sy / 2;
status = options_get_number(w->options, "pane-border-status");
status = window_get_pane_status(w);
if (status == PANE_STATUS_TOP)
top++;
else if (status == PANE_STATUS_BOTTOM)
@@ -1587,7 +1589,7 @@ window_pane_find_up(struct window_pane *wp)
if (wp == NULL)
return (NULL);
w = wp->window;
status = options_get_number(w->options, "pane-border-status");
status = window_get_pane_status(w);
list = NULL;
size = 0;
@@ -1648,7 +1650,7 @@ window_pane_find_down(struct window_pane *wp)
if (wp == NULL)
return (NULL);
w = wp->window;
status = options_get_number(w->options, "pane-border-status");
status = window_get_pane_status(w);
list = NULL;
size = 0;
@@ -2164,21 +2166,19 @@ window_pane_send_theme_update(struct window_pane *wp)
}
struct style_range *
window_pane_border_status_get_range(struct window_pane *wp, u_int x, u_int y)
window_pane_status_get_range(struct window_pane *wp, u_int x, u_int y)
{
struct style_ranges *srs;
struct window *w;
struct options *wo;
u_int line;
int pane_status;
if (wp == NULL)
return (NULL);
w = wp->window;
wo = w->options;
srs = &wp->border_status_line.ranges;
pane_status = options_get_number(wo, "pane-border-status");
pane_status = window_get_pane_status(w);
if (pane_status == PANE_STATUS_TOP)
line = wp->yoff - 1;
else if (pane_status == PANE_STATUS_BOTTOM)
@@ -2193,6 +2193,12 @@ window_pane_border_status_get_range(struct window_pane *wp, u_int x, u_int y)
return (style_ranges_get_range(srs, x - wp->xoff - 2));
}
int
window_get_pane_status(struct window *w)
{
return (options_get_number(w->options, "pane-border-status"));
}
int
window_pane_is_floating(struct window_pane *wp)
{