Merge branch 'master' into sixel

pull/3363/head
Nicholas Marriott 2021-12-08 10:37:33 +00:00
commit 906c92a5f4
39 changed files with 1218 additions and 433 deletions

View File

@ -29,7 +29,7 @@ uname -sp && tmux -V && echo $TERM
Also include:
- Your platform (Linux, OS X, or whatever).
- Your platform (Linux, macOS, or whatever).
- A brief description of the problem with steps to reproduce.

2
.github/README.md vendored
View File

@ -4,7 +4,7 @@ tmux is a terminal multiplexer: it enables a number of terminals to be created,
accessed, and controlled from a single screen. tmux may be detached from a
screen and continue running in the background, then later reattached.
This release runs on OpenBSD, FreeBSD, NetBSD, Linux, OS X and Solaris.
This release runs on OpenBSD, FreeBSD, NetBSD, Linux, macOS and Solaris.
## Dependencies

2
README
View File

@ -4,7 +4,7 @@ tmux is a terminal multiplexer: it enables a number of terminals to be created,
accessed, and controlled from a single screen. tmux may be detached from a
screen and continue running in the background, then later reattached.
This release runs on OpenBSD, FreeBSD, NetBSD, Linux, OS X and Solaris.
This release runs on OpenBSD, FreeBSD, NetBSD, Linux, macOS and Solaris.
* Dependencies

View File

@ -3,7 +3,7 @@ tmuxへようこそ!
tmuxはターミナルマルチプレクサーです。複数のターミナルを一つのスクリーン内に作成し、操作することができます。
バックグラウンドで処理を実行中に一度スクリーンから離れて後から復帰することも可能です。
OpenBSD、FreeBSD、NetBSD、Linux、OS X、Solarisで実行できます。
OpenBSD、FreeBSD、NetBSD、Linux、macOS、Solarisで実行できます。
tmuxはlibevent 2.x.に依存します。 下記からダウンロードしてください。

View File

@ -108,6 +108,7 @@ args_value_as_string(struct args_value *value)
case ARGS_STRING:
return (value->string);
}
fatalx("unexpected argument type");
}
/* Create an empty arguments set. */
@ -753,6 +754,7 @@ args_make_commands(struct args_command_state *state, int argc, char **argv,
case CMD_PARSE_SUCCESS:
return (pr->cmdlist);
}
fatalx("invalid parse return state");
}
/* Free commands state. */

View File

@ -72,7 +72,7 @@ cmd_confirm_before_exec(struct cmd *self, struct cmdq_item *item)
int wait = !args_has(args, 'b');
cdata = xcalloc(1, sizeof *cdata);
cdata->cmdlist = args_make_commands_now(self, item, 0, 0);
cdata->cmdlist = args_make_commands_now(self, item, 0, 1);
if (cdata->cmdlist == NULL)
return (CMD_RETURN_ERROR);

View File

@ -52,10 +52,12 @@ const struct cmd_entry cmd_display_popup_entry = {
.name = "display-popup",
.alias = "popup",
.args = { "BCc:d:Eh:t:w:x:y:", 0, -1, NULL },
.usage = "[-BCE] [-c target-client] [-d start-directory] [-h height] "
CMD_TARGET_PANE_USAGE " [-w width] "
"[-x position] [-y position] [shell-command]",
.args = { "Bb:Cc:d:e:Eh:s:S:t:T:w:x:y:", 0, -1, NULL },
.usage = "[-BCE] [-b border-lines] [-c target-client] "
"[-d start-directory] [-e environment] [-h height] "
"[-s style] [-S border-style] " CMD_TARGET_PANE_USAGE
"[-T title] [-w width] [-x position] [-y position] "
"[shell-command]",
.target = { 't', CMD_FIND_PANE, 0 },
@ -353,9 +355,16 @@ cmd_display_popup_exec(struct cmd *self, struct cmdq_item *item)
struct client *tc = cmdq_get_target_client(item);
struct tty *tty = &tc->tty;
const char *value, *shell, *shellcmd = NULL;
char *cwd, *cause, **argv = NULL;
const char *style = args_get(args, 's');
const char *border_style = args_get(args, 'S');
char *cwd, *cause = NULL, **argv = NULL, *title;
int flags = 0, argc = 0;
enum box_lines lines = BOX_LINES_DEFAULT;
u_int px, py, w, h, count = args_count(args);
struct args_value *av;
struct environ *env = NULL;
struct options *o = s->curw->window->options;
struct options_entry *oe;
if (args_has(args, 'C')) {
server_client_clear_overlay(tc);
@ -391,6 +400,20 @@ cmd_display_popup_exec(struct cmd *self, struct cmdq_item *item)
if (!cmd_display_menu_get_position(tc, item, args, &px, &py, w, h))
return (CMD_RETURN_NORMAL);
value = args_get(args, 'b');
if (args_has(args, 'B'))
lines = BOX_LINES_NONE;
else if (value != NULL) {
oe = options_get(o, "popup-border-lines");
lines = options_find_choice(options_table_entry(oe), value,
&cause);
if (cause != NULL) {
cmdq_error(item, "popup-border-lines %s", cause);
free(cause);
return (CMD_RETURN_ERROR);
}
}
value = args_get(args, 'd');
if (value != NULL)
cwd = format_single_from_target(item, value);
@ -409,17 +432,34 @@ cmd_display_popup_exec(struct cmd *self, struct cmdq_item *item)
} else
args_to_vector(args, &argc, &argv);
if (args_has(args, 'e') >= 1) {
env = environ_create();
av = args_first_value(args, 'e');
while (av != NULL) {
environ_put(env, av->string, 0);
av = args_next_value(av);
}
}
if (args_has(args, 'T'))
title = format_single_from_target(item, args_get(args, 'T'));
else
title = xstrdup("");
if (args_has(args, 'E') > 1)
flags |= POPUP_CLOSEEXITZERO;
else if (args_has(args, 'E'))
flags |= POPUP_CLOSEEXIT;
if (args_has(args, 'B'))
flags |= POPUP_NOBORDER;
if (popup_display(flags, item, px, py, w, h, shellcmd, argc, argv, cwd,
tc, s, NULL, NULL) != 0) {
if (popup_display(flags, lines, item, px, py, w, h, env, shellcmd, argc,
argv, cwd, title, tc, s, style, border_style, NULL, NULL) != 0) {
cmd_free_argv(argc, argv);
if (env != NULL)
environ_free(env);
free(title);
return (CMD_RETURN_NORMAL);
}
if (env != NULL)
environ_free(env);
free(title);
cmd_free_argv(argc, argv);
return (CMD_RETURN_WAIT);
}

View File

@ -118,7 +118,7 @@ cmd_if_shell_exec(struct cmd *self, struct cmdq_item *item)
if (cdata->client != NULL)
cdata->client->references++;
if (job_run(shellcmd, 0, NULL, s,
if (job_run(shellcmd, 0, NULL, NULL, s,
server_client_get_cwd(cmdq_get_client(item), s), NULL,
cmd_if_shell_callback, cmd_if_shell_free, cdata, 0, -1,
-1) == NULL) {

View File

@ -130,7 +130,7 @@ cmd_pipe_pane_exec(struct cmd *self, struct cmdq_item *item)
sigprocmask(SIG_SETMASK, &oldset, NULL);
close(pipe_fd[0]);
null_fd = open(_PATH_DEVNULL, O_WRONLY, 0);
null_fd = open(_PATH_DEVNULL, O_WRONLY);
if (out) {
if (dup2(pipe_fd[1], STDIN_FILENO) == -1)
_exit(1);

View File

@ -188,7 +188,7 @@ cmd_run_shell_timer(__unused int fd, __unused short events, void* arg)
cmd_run_shell_free(cdata);
return;
}
if (job_run(cmd, 0, NULL, cdata->s, cdata->cwd, NULL,
if (job_run(cmd, 0, NULL, NULL, cdata->s, cdata->cwd, NULL,
cmd_run_shell_callback, cmd_run_shell_free, cdata,
cdata->flags, -1, -1) == NULL)
cmd_run_shell_free(cdata);

View File

@ -203,6 +203,8 @@ cmd_send_keys_exec(struct cmd *self, struct cmdq_item *item)
}
if (count == 0) {
if (args_has(args, 'N') || args_has(args, 'R'))
return (CMD_RETURN_NORMAL);
for (; np != 0; np--)
cmd_send_keys_inject_key(item, NULL, event->key);
return (CMD_RETURN_NORMAL);

View File

@ -126,6 +126,12 @@ cmd_show_options_exec(struct cmd *self, struct cmdq_item *item)
parent = 0;
if (o != NULL)
cmd_show_options_print(self, item, o, idx, parent);
else if (*name == '@') {
if (args_has(args, 'q'))
goto fail;
cmdq_error(item, "invalid option: %s", argument);
goto fail;
}
free(name);
free(argument);

View File

@ -105,6 +105,21 @@ colour_split_rgb(int c, u_char *r, u_char *g, u_char *b)
*b = c & 0xff;
}
/* Force colour to RGB if not already. */
int
colour_force_rgb(int c)
{
if (c & COLOUR_FLAG_RGB)
return (c);
if (c & COLOUR_FLAG_256)
return (colour_256toRGB(c));
if (c >= 0 && c <= 7)
return (colour_256toRGB(c));
if (c >= 90 && c <= 97)
return (colour_256toRGB(8 + c - 90));
return (-1);
}
/* Convert colour to a string. */
const char *
colour_tostring(int c)

View File

@ -677,7 +677,8 @@ format_draw_many(struct screen_write_ctx *ctx, struct style *sy, char ch,
/* Draw a format to a screen. */
void
format_draw(struct screen_write_ctx *octx, const struct grid_cell *base,
u_int available, const char *expanded, struct style_ranges *srs)
u_int available, const char *expanded, struct style_ranges *srs,
int default_colours)
{
enum { LEFT,
CENTRE,
@ -819,6 +820,10 @@ format_draw(struct screen_write_ctx *octx, const struct grid_cell *base,
log_debug("%s: style '%s' -> '%s'", __func__, tmp,
style_tostring(&sy));
free(tmp);
if (default_colours) {
sy.gc.bg = base->bg;
sy.gc.fg = base->fg;
}
/* If this style has a fill colour, store it for later. */
if (sy.fill != 8)

View File

@ -101,6 +101,7 @@ format_job_cmp(struct format_job *fj1, struct format_job *fj2)
#define FORMAT_WINDOW_NAME 0x4000
#define FORMAT_SESSION_NAME 0x8000
#define FORMAT_CHARACTER 0x10000
#define FORMAT_COLOUR 0x20000
/* Limit on recursion. */
#define FORMAT_LOOP_LIMIT 100
@ -390,7 +391,7 @@ format_job_get(struct format_expand_state *es, const char *cmd)
if (force && fj->job != NULL)
job_free(fj->job);
if (force || (fj->job == NULL && fj->last != t)) {
fj->job = job_run(expanded, 0, NULL, NULL,
fj->job = job_run(expanded, 0, NULL, NULL, NULL,
server_client_get_cwd(ft->client, NULL), format_job_update,
format_job_complete, NULL, fj, JOB_NOWAIT, -1, -1);
if (fj->job == NULL) {
@ -3555,7 +3556,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,d,n,t,w,q,E,T,S,W,P,<,>
* l,m,C,a,b,c,d,n,t,w,q,E,T,S,W,P,<,>
* =a
* =/a
* =/a/
@ -3572,7 +3573,7 @@ format_build_modifiers(struct format_expand_state *es, const char **s,
cp++;
/* Check single character modifiers with no arguments. */
if (strchr("labdnwETSWP<>", cp[0]) != NULL &&
if (strchr("labcdnwETSWP<>", cp[0]) != NULL &&
format_is_end(cp[1])) {
format_add_modifier(&list, count, cp, 1, NULL, 0);
cp++;
@ -4052,10 +4053,10 @@ format_replace(struct format_expand_state *es, const char *key, size_t keylen,
const char *errstr, *copy, *cp, *marker = NULL;
const char *time_format = NULL;
char *copy0, *condition, *found, *new;
char *value, *left, *right, c;
char *value, *left, *right;
size_t valuelen;
int modifiers = 0, limit = 0, width = 0;
int j;
int j, c;
struct format_modifier *list, *cmp = NULL, *search = NULL;
struct format_modifier **sub = NULL, *mexp = NULL, *fm;
u_int i, count, nsub = 0;
@ -4126,6 +4127,9 @@ format_replace(struct format_expand_state *es, const char *key, size_t keylen,
case 'b':
modifiers |= FORMAT_BASENAME;
break;
case 'c':
modifiers |= FORMAT_COLOUR;
break;
case 'd':
modifiers |= FORMAT_DIRNAME;
break;
@ -4201,6 +4205,18 @@ format_replace(struct format_expand_state *es, const char *key, size_t keylen,
goto done;
}
/* Is this a colour? */
if (modifiers & FORMAT_COLOUR) {
new = format_expand1(es, copy);
c = colour_fromstring(new);
if (c == -1 || (c = colour_force_rgb(c)) == -1)
value = xstrdup("");
else
xasprintf(&value, "%06x", c & 0xffffff);
free(new);
goto done;
}
/* Is this a loop, comparison or condition? */
if (modifiers & FORMAT_SESSIONS) {
value = format_loop_sessions(es, copy);

76
input.c
View File

@ -137,10 +137,12 @@ static void input_reset_cell(struct input_ctx *);
static void input_osc_4(struct input_ctx *, const char *);
static void input_osc_10(struct input_ctx *, const char *);
static void input_osc_11(struct input_ctx *, const char *);
static void input_osc_12(struct input_ctx *, const char *);
static void input_osc_52(struct input_ctx *, const char *);
static void input_osc_104(struct input_ctx *, const char *);
static void input_osc_110(struct input_ctx *, const char *);
static void input_osc_111(struct input_ctx *, const char *);
static void input_osc_112(struct input_ctx *, const char *);
/* Transition entry/exit handlers. */
static void input_clear(struct input_ctx *);
@ -1617,7 +1619,7 @@ input_csi_dispatch(struct input_ctx *ictx)
case INPUT_CSI_DECSCUSR:
n = input_get(ictx, 0, 0, 0);
if (n != -1)
screen_set_cursor_style(s, n);
screen_set_cursor_style(n, &s->cstyle, &s->mode);
break;
case INPUT_CSI_XDA:
n = input_get(ictx, 0, 0, 0);
@ -1683,6 +1685,7 @@ input_csi_dispatch_rm_private(struct input_ctx *ictx)
break;
case 12:
screen_write_mode_clear(sctx, MODE_CURSOR_BLINKING);
screen_write_mode_set(sctx, MODE_CURSOR_BLINKING_SET);
break;
case 25: /* TCEM */
screen_write_mode_clear(sctx, MODE_CURSOR);
@ -1772,6 +1775,7 @@ input_csi_dispatch_sm_private(struct input_ctx *ictx)
break;
case 12:
screen_write_mode_set(sctx, MODE_CURSOR_BLINKING);
screen_write_mode_set(sctx, MODE_CURSOR_BLINKING_SET);
break;
case 25: /* TCEM */
screen_write_mode_set(sctx, MODE_CURSOR);
@ -2322,8 +2326,7 @@ input_exit_osc(struct input_ctx *ictx)
input_osc_11(ictx, p);
break;
case 12:
if (utf8_isvalid(p) && *p != '?') /* ? is colour request */
screen_set_cursor_colour(sctx->s, p);
input_osc_12(ictx, p);
break;
case 52:
input_osc_52(ictx, p);
@ -2338,8 +2341,7 @@ input_exit_osc(struct input_ctx *ictx)
input_osc_111(ictx, p);
break;
case 112:
if (*p == '\0') /* no arguments allowed */
screen_set_cursor_colour(sctx->s, "");
input_osc_112(ictx, p);
break;
default:
log_debug("%s: unknown '%u'", __func__, option);
@ -2392,6 +2394,7 @@ static void
input_exit_rename(struct input_ctx *ictx)
{
struct window_pane *wp = ictx->wp;
struct window *w;
struct options_entry *o;
if (wp == NULL)
@ -2404,17 +2407,20 @@ input_exit_rename(struct input_ctx *ictx)
if (!utf8_isvalid(ictx->input_buf))
return;
w = wp->window;
if (ictx->input_len == 0) {
o = options_get_only(wp->window->options, "automatic-rename");
o = options_get_only(w->options, "automatic-rename");
if (o != NULL)
options_remove_or_default(o, -1, NULL);
return;
if (!options_get_number(w->options, "automatic-rename"))
window_set_name(w, "");
} else {
options_set_number(w->options, "automatic-rename", 0);
window_set_name(w, ictx->input_buf);
}
window_set_name(wp->window, ictx->input_buf);
options_set_number(wp->window->options, "automatic-rename", 0);
server_redraw_window_borders(wp->window);
server_status_window(wp->window);
server_redraw_window_borders(w);
server_status_window(w);
}
/* Open UTF-8 character. */
@ -2501,7 +2507,9 @@ input_osc_colour_reply(struct input_ctx *ictx, u_int n, int c)
u_char r, g, b;
const char *end;
if (c == 8 || (~c & COLOUR_FLAG_RGB))
if (c != -1)
c = colour_force_rgb(c);
if (c == -1)
return;
colour_split_rgb(c, &r, &g, &b);
@ -2509,7 +2517,8 @@ input_osc_colour_reply(struct input_ctx *ictx, u_int n, int c)
end = "\007";
else
end = "\033\\";
input_reply(ictx, "\033]%u;rgb:%02hhx/%02hhx/%02hhx%s", n, r, g, b, end);
input_reply(ictx, "\033]%u;rgb:%02hhx%02hhx/%02hhx%02hhx/%02hhx%02hhx%s",
n, r, r, g, g, b, b, end);
}
/* Handle the OSC 4 sequence for setting (multiple) palette entries. */
@ -2533,6 +2542,12 @@ input_osc_4(struct input_ctx *ictx, const char *p)
}
s = strsep(&next, ";");
if (strcmp(s, "?") == 0) {
c = colour_palette_get(ictx->palette, idx);
if (c != -1)
input_osc_colour_reply(ictx, 4, c);
continue;
}
if ((c = input_osc_parse_colour(s)) == -1) {
s = next;
continue;
@ -2576,7 +2591,7 @@ input_osc_10(struct input_ctx *ictx, const char *p)
}
}
/* Handle the OSC 110 sequence for resetting background colour. */
/* Handle the OSC 110 sequence for resetting foreground colour. */
static void
input_osc_110(struct input_ctx *ictx, const char *p)
{
@ -2636,6 +2651,39 @@ input_osc_111(struct input_ctx *ictx, const char *p)
}
}
/* Handle the OSC 12 sequence for setting and querying cursor colour. */
static void
input_osc_12(struct input_ctx *ictx, const char *p)
{
struct window_pane *wp = ictx->wp;
int c;
if (strcmp(p, "?") == 0) {
if (wp != NULL) {
c = ictx->ctx.s->ccolour;
if (c == -1)
c = ictx->ctx.s->default_ccolour;
input_osc_colour_reply(ictx, 12, c);
}
return;
}
if ((c = input_osc_parse_colour(p)) == -1) {
log_debug("bad OSC 12: %s", p);
return;
}
screen_set_cursor_colour(ictx->ctx.s, c);
}
/* Handle the OSC 112 sequence for resetting cursor colour. */
static void
input_osc_112(struct input_ctx *ictx, const char *p)
{
if (*p == '\0') /* no arguments allowed */
screen_set_cursor_colour(ictx->ctx.s, -1);
}
/* Handle the OSC 52 sequence for setting the clipboard. */
static void
input_osc_52(struct input_ctx *ictx, const char *p)

7
job.c
View File

@ -69,7 +69,7 @@ static LIST_HEAD(joblist, job) all_jobs = LIST_HEAD_INITIALIZER(all_jobs);
/* Start a job running. */
struct job *
job_run(const char *cmd, int argc, char **argv, struct session *s,
job_run(const char *cmd, int argc, char **argv, struct environ *e, struct session *s,
const char *cwd, job_update_cb updatecb, job_complete_cb completecb,
job_free_cb freecb, void *data, int flags, int sx, int sy)
{
@ -87,6 +87,9 @@ job_run(const char *cmd, int argc, char **argv, struct session *s,
* if-shell to decide on default-terminal based on outside TERM.
*/
env = environ_for_session(s, !cfg_finished);
if (e != NULL) {
environ_copy(e, env);
}
sigfillset(&set);
sigprocmask(SIG_BLOCK, &set, &oldset);
@ -137,7 +140,7 @@ job_run(const char *cmd, int argc, char **argv, struct session *s,
close(out[1]);
close(out[0]);
nullfd = open(_PATH_DEVNULL, O_RDWR, 0);
nullfd = open(_PATH_DEVNULL, O_RDWR);
if (nullfd == -1)
fatal("open failed");
if (dup2(nullfd, STDERR_FILENO) == -1)

49
menu.c
View File

@ -55,10 +55,11 @@ menu_add_item(struct menu *menu, const struct menu_item *item,
struct cmdq_item *qitem, struct client *c, struct cmd_find_state *fs)
{
struct menu_item *new_item;
const char *key, *cmd;
const char *key = NULL, *cmd, *suffix = "";
char *s, *name;
u_int width;
u_int width, max_width;
int line;
size_t keylen, slen;
line = (item == NULL || item->name == NULL || *item->name == '\0');
if (line && menu->count == 0)
@ -80,11 +81,34 @@ menu_add_item(struct menu *menu, const struct menu_item *item,
menu->count--;
return;
}
max_width = c->tty.sx - 4;
slen = strlen(s);
if (*s != '-' && item->key != KEYC_UNKNOWN && item->key != KEYC_NONE) {
key = key_string_lookup_key(item->key, 0);
xasprintf(&name, "%s#[default] #[align=right](%s)", s, key);
} else
xasprintf(&name, "%s", s);
keylen = strlen(key) + 3; /* 3 = space and two brackets */
/*
* Add the key if it is shorter than a quarter of the available
* space or there is space for the entire item text and the
* key.
*/
if (keylen <= max_width / 4)
max_width -= keylen;
else if (keylen >= max_width || slen >= max_width - keylen)
key = NULL;
}
if (slen > max_width) {
max_width--;
suffix = ">";
}
if (key != NULL)
xasprintf(&name, "%.*s%s#[default] #[align=right](%s)",
(int)max_width, s, suffix, key);
else
xasprintf(&name, "%.*s%s", (int)max_width, s, suffix);
new_item->name = name;
free(s);
@ -100,6 +124,8 @@ menu_add_item(struct menu *menu, const struct menu_item *item,
new_item->key = item->key;
width = format_width(new_item->name);
if (*new_item->name == '-')
width--;
if (width > menu->width)
menu->width = width;
}
@ -140,17 +166,16 @@ menu_mode_cb(__unused struct client *c, void *data, __unused u_int *cx,
return (&md->s);
}
int
menu_check_cb(__unused struct client *c, void *data, u_int px, u_int py)
/* Return parts of the input range which are not obstructed by the menu. */
void
menu_check_cb(__unused struct client *c, void *data, u_int px, u_int py,
u_int nx, struct overlay_ranges *r)
{
struct menu_data *md = data;
struct menu *menu = md->menu;
if (px < md->px || px > md->px + menu->width + 3)
return (1);
if (py < md->py || py > md->py + menu->count + 1)
return (1);
return (0);
server_client_overlay_range(md->px, md->py, menu->width + 4,
menu->count + 2, px, py, nx, r);
}
void

View File

@ -716,14 +716,14 @@ mode_tree_draw(struct mode_tree_data *mtd)
screen_write_nputs(&ctx, w, &gc0, "%s", text);
if (mti->text != NULL) {
format_draw(&ctx, &gc0, w - width, mti->text,
NULL);
NULL, 0);
}
} else {
screen_write_clearendofline(&ctx, gc.bg);
screen_write_nputs(&ctx, w, &gc, "%s", text);
if (mti->text != NULL) {
format_draw(&ctx, &gc, w - width, mti->text,
NULL);
NULL, 0);
}
}
free(text);
@ -736,10 +736,8 @@ mode_tree_draw(struct mode_tree_data *mtd)
}
sy = screen_size_y(s);
if (!mtd->preview || sy <= 4 || h <= 4 || sy - h <= 4 || w <= 4) {
screen_write_stop(&ctx);
return;
}
if (!mtd->preview || sy <= 4 || h <= 4 || sy - h <= 4 || w <= 4)
goto done;
line = &mtd->line_list[mtd->current];
mti = line->item;
@ -747,7 +745,7 @@ mode_tree_draw(struct mode_tree_data *mtd)
mti = mti->parent;
screen_write_cursormove(&ctx, 0, h, 0);
screen_write_box(&ctx, w, sy - h);
screen_write_box(&ctx, w, sy - h, BOX_LINES_DEFAULT, NULL, NULL);
if (mtd->sort_list != NULL) {
xasprintf(&text, " %s (sort: %s%s)", mti->name,
@ -783,6 +781,8 @@ mode_tree_draw(struct mode_tree_data *mtd)
mtd->drawcb(mtd->modedata, mti->itemdata, &ctx, box_x, box_y);
}
done:
screen_write_cursormove(&ctx, 0, mtd->current - mtd->offset, 0);
screen_write_stop(&ctx);
}
@ -1055,7 +1055,6 @@ 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++) {
@ -1064,7 +1063,6 @@ 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++) {
@ -1073,10 +1071,12 @@ mode_tree_key(struct mode_tree_data *mtd, struct client *c, key_code *key,
mode_tree_down(mtd, 1);
}
break;
case 'g':
case KEYC_HOME:
mtd->current = 0;
mtd->offset = 0;
break;
case 'G':
case KEYC_END:
mtd->current = mtd->line_size - 1;
if (mtd->current > mtd->height - 1)

View File

@ -56,12 +56,19 @@ static const char *options_table_bell_action_list[] = {
static const char *options_table_visual_bell_list[] = {
"off", "on", "both", NULL
};
static const char *options_table_cursor_style_list[] = {
"default", "blinking-block", "block", "blinking-underline", "underline",
"blinking-bar", "bar", NULL
};
static const char *options_table_pane_status_list[] = {
"off", "top", "bottom", NULL
};
static const char *options_table_pane_lines_list[] = {
static const char *options_table_pane_border_lines_list[] = {
"single", "double", "heavy", "simple", "number", NULL
};
static const char *options_table_popup_border_lines_list[] = {
"single", "double", "heavy", "simple", "rounded", "padded", "none", NULL
};
static const char *options_table_set_clipboard_list[] = {
"off", "external", "on", NULL
};
@ -184,6 +191,7 @@ const struct options_name_map options_other_names[] = {
{ "display-panes-color", "display-panes-colour" },
{ "display-panes-active-color", "display-panes-active-colour" },
{ "clock-mode-color", "clock-mode-colour" },
{ "cursor-color", "cursor-colour" },
{ "pane-colors", "pane-colours" },
{ NULL, NULL }
};
@ -231,6 +239,21 @@ const struct options_table_entry options_table[] = {
"If empty, no command is run."
},
{ .name = "cursor-colour",
.type = OPTIONS_TABLE_COLOUR,
.scope = OPTIONS_TABLE_WINDOW|OPTIONS_TABLE_PANE,
.default_num = -1,
.text = "Colour of the cursor."
},
{ .name = "cursor-style",
.type = OPTIONS_TABLE_CHOICE,
.scope = OPTIONS_TABLE_WINDOW|OPTIONS_TABLE_PANE,
.choices = options_table_cursor_style_list,
.default_num = 0,
.text = "Style of the cursor."
},
{ .name = "default-terminal",
.type = OPTIONS_TABLE_STRING,
.scope = OPTIONS_TABLE_SERVER,
@ -950,7 +973,7 @@ const struct options_table_entry options_table[] = {
{ .name = "pane-border-lines",
.type = OPTIONS_TABLE_CHOICE,
.scope = OPTIONS_TABLE_WINDOW,
.choices = options_table_pane_lines_list,
.choices = options_table_pane_border_lines_list,
.default_num = PANE_LINES_SINGLE,
.text = "Type of characters used to draw pane border lines. Some of "
"these are only supported on terminals with UTF-8 support."
@ -981,6 +1004,33 @@ const struct options_table_entry options_table[] = {
.text = "The default colour palette for colours zero to 255."
},
{ .name = "popup-style",
.type = OPTIONS_TABLE_STRING,
.scope = OPTIONS_TABLE_WINDOW,
.default_str = "default",
.flags = OPTIONS_TABLE_IS_STYLE,
.separator = ",",
.text = "Default style of popups."
},
{ .name = "popup-border-style",
.type = OPTIONS_TABLE_STRING,
.scope = OPTIONS_TABLE_WINDOW,
.default_str = "default",
.flags = OPTIONS_TABLE_IS_STYLE,
.separator = ",",
.text = "Default style of popup borders."
},
{ .name = "popup-border-lines",
.type = OPTIONS_TABLE_CHOICE,
.scope = OPTIONS_TABLE_WINDOW,
.choices = options_table_popup_border_lines_list,
.default_num = BOX_LINES_SINGLE,
.text = "Type of characters used to draw popup border lines. Some of "
"these are only supported on terminals with UTF-8 support."
},
{ .name = "remain-on-exit",
.type = OPTIONS_TABLE_CHOICE,
.scope = OPTIONS_TABLE_WINDOW|OPTIONS_TABLE_PANE,

View File

@ -989,28 +989,39 @@ options_from_string_flag(struct options *oo, const char *name,
return (0);
}
int
options_find_choice(const struct options_table_entry *oe, const char *value,
char **cause)
{
const char **cp;
int n = 0, choice = -1;
for (cp = oe->choices; *cp != NULL; cp++) {
if (strcmp(*cp, value) == 0)
choice = n;
n++;
}
if (choice == -1) {
xasprintf(cause, "unknown value: %s", value);
return (-1);
}
return (choice);
}
static int
options_from_string_choice(const struct options_table_entry *oe,
struct options *oo, const char *name, const char *value, char **cause)
{
const char **cp;
int n, choice = -1;
int choice = -1;
if (value == NULL) {
choice = options_get_number(oo, name);
if (choice < 2)
choice = !choice;
} else {
n = 0;
for (cp = oe->choices; *cp != NULL; cp++) {
if (strcmp(*cp, value) == 0)
choice = n;
n++;
}
if (choice == -1) {
xasprintf(cause, "unknown value: %s", value);
choice = options_find_choice(oe, value, cause);
if (choice < 0)
return (-1);
}
}
options_set_number(oo, name, choice);
return (0);
@ -1095,15 +1106,30 @@ options_push_changes(const char *name)
struct session *s;
struct window *w;
struct window_pane *wp;
int c;
if (strcmp(name, "automatic-rename") == 0) {
RB_FOREACH(w, windows, &windows) {
if (w->active == NULL)
continue;
if (options_get_number(w->options, "automatic-rename"))
if (options_get_number(w->options, name))
w->active->flags |= PANE_CHANGED;
}
}
if (strcmp(name, "cursor-colour") == 0) {
RB_FOREACH(wp, window_pane_tree, &all_window_panes) {
c = options_get_number(wp->options, name);
wp->screen->default_ccolour = c;
}
}
if (strcmp(name, "cursor-style") == 0) {
RB_FOREACH(wp, window_pane_tree, &all_window_panes) {
wp->screen->default_mode = 0;
screen_set_cursor_style(options_get_number(wp->options,
name), &wp->screen->default_cstyle,
&wp->screen->default_mode);
}
}
if (strcmp(name, "key-table") == 0) {
TAILQ_FOREACH(loop, &clients, entry)
server_client_set_key_table(loop, NULL);

View File

@ -18,6 +18,7 @@
#include <sys/param.h> /* MAXCOMLEN */
#include <sys/types.h>
#include <sys/signal.h>
#include <sys/proc.h>
#include <sys/sysctl.h>
#include <sys/stat.h>

142
popup.c
View File

@ -30,9 +30,15 @@ struct popup_data {
struct client *c;
struct cmdq_item *item;
int flags;
char *title;
struct grid_cell border_cell;
enum box_lines border_lines;
struct screen s;
struct grid_cell defaults;
struct colour_palette palette;
struct job *job;
struct input_ctx *ictx;
int status;
@ -116,7 +122,7 @@ popup_set_client_cb(struct tty_ctx *ttyctx, struct client *c)
ttyctx->wsx = c->tty.sx;
ttyctx->wsy = c->tty.sy;
if (pd->flags & POPUP_NOBORDER) {
if (pd->border_lines == BOX_LINES_NONE) {
ttyctx->xoff = ttyctx->rxoff = pd->px;
ttyctx->yoff = ttyctx->ryoff = pd->py;
} else {
@ -132,6 +138,7 @@ popup_init_ctx_cb(struct screen_write_ctx *ctx, struct tty_ctx *ttyctx)
{
struct popup_data *pd = ctx->arg;
memcpy(&ttyctx->defaults, &pd->defaults, sizeof ttyctx->defaults);
ttyctx->palette = &pd->palette;
ttyctx->redraw_cb = popup_redraw_cb;
ttyctx->set_client_cb = popup_set_client_cb;
@ -146,7 +153,7 @@ popup_mode_cb(__unused struct client *c, void *data, u_int *cx, u_int *cy)
if (pd->md != NULL)
return (menu_mode_cb(c, pd->md, cx, cy));
if (pd->flags & POPUP_NOBORDER) {
if (pd->border_lines == BOX_LINES_NONE) {
*cx = pd->px + pd->s.cx;
*cy = pd->py + pd->s.cy;
} else {
@ -156,18 +163,49 @@ popup_mode_cb(__unused struct client *c, void *data, u_int *cx, u_int *cy)
return (&pd->s);
}
static int
popup_check_cb(struct client *c, void *data, u_int px, u_int py)
/* Return parts of the input range which are not obstructed by the popup. */
static void
popup_check_cb(struct client* c, void *data, u_int px, u_int py, u_int nx,
struct overlay_ranges *r)
{
struct popup_data *pd = data;
struct overlay_ranges or[2];
u_int i, j, k = 0;
if (pd->md != NULL && menu_check_cb(c, pd->md, px, py) == 0)
return (0);
if (px < pd->px || px > pd->px + pd->sx - 1)
return (1);
if (py < pd->py || py > pd->py + pd->sy - 1)
return (1);
return (0);
if (pd->md != NULL) {
/* Check each returned range for the menu against the popup. */
menu_check_cb(c, pd->md, px, py, nx, r);
for (i = 0; i < 2; i++) {
server_client_overlay_range(pd->px, pd->py, pd->sx,
pd->sy, r->px[i], py, r->nx[i], &or[i]);
}
/*
* or has up to OVERLAY_MAX_RANGES non-overlapping ranges,
* ordered from left to right. Collect them in the output.
*/
for (i = 0; i < 2; i++) {
/* Each or[i] only has 2 ranges. */
for (j = 0; j < 2; j++) {
if (or[i].nx[j] > 0) {
r->px[k] = or[i].px[j];
r->nx[k] = or[i].nx[j];
k++;
}
}
}
/* Zero remaining ranges if any. */
for (i = k; i < OVERLAY_MAX_RANGES; i++) {
r->px[i] = 0;
r->nx[i] = 0;
}
return;
}
server_client_overlay_range(pd->px, pd->py, pd->sx, pd->sy, px, py, nx,
r);
}
static void
@ -179,26 +217,29 @@ popup_draw_cb(struct client *c, void *data, struct screen_redraw_ctx *rctx)
struct screen_write_ctx ctx;
u_int i, px = pd->px, py = pd->py;
struct colour_palette *palette = &pd->palette;
struct grid_cell gc;
struct grid_cell defaults;
screen_init(&s, pd->sx, pd->sy, 0);
screen_write_start(&ctx, &s);
screen_write_clearscreen(&ctx, 8);
if (pd->flags & POPUP_NOBORDER) {
if (pd->border_lines == BOX_LINES_NONE) {
screen_write_cursormove(&ctx, 0, 0, 0);
screen_write_fast_copy(&ctx, &pd->s, 0, 0, pd->sx, pd->sy);
} else if (pd->sx > 2 && pd->sy > 2) {
screen_write_box(&ctx, pd->sx, pd->sy);
screen_write_box(&ctx, pd->sx, pd->sy, pd->border_lines,
&pd->border_cell, pd->title);
screen_write_cursormove(&ctx, 1, 1, 0);
screen_write_fast_copy(&ctx, &pd->s, 0, 0, pd->sx - 2,
pd->sy - 2);
}
screen_write_stop(&ctx);
memcpy(&gc, &grid_default_cell, sizeof gc);
gc.fg = pd->palette.fg;
gc.bg = pd->palette.bg;
memcpy(&defaults, &pd->defaults, sizeof defaults);
if (defaults.fg == 8)
defaults.fg = palette->fg;
if (defaults.bg == 8)
defaults.bg = palette->bg;
if (pd->md != NULL) {
c->overlay_check = menu_check_cb;
@ -207,8 +248,10 @@ popup_draw_cb(struct client *c, void *data, struct screen_redraw_ctx *rctx)
c->overlay_check = NULL;
c->overlay_data = NULL;
}
for (i = 0; i < pd->sy; i++)
tty_draw_line(tty, &s, 0, i, pd->sx, px, py + i, &gc, palette);
for (i = 0; i < pd->sy; i++) {
tty_draw_line(tty, &s, 0, i, pd->sx, px, py + i, &defaults,
palette);
}
if (pd->md != NULL) {
c->overlay_check = NULL;
c->overlay_data = NULL;
@ -245,6 +288,7 @@ popup_free_cb(struct client *c, void *data)
screen_free(&pd->s);
colour_palette_free(&pd->palette);
free(pd->title);
free(pd);
}
@ -278,7 +322,7 @@ popup_resize_cb(__unused struct client *c, void *data)
pd->px = pd->ppx;
/* Avoid zero size screens. */
if (pd->flags & POPUP_NOBORDER) {
if (pd->border_lines == BOX_LINES_NONE) {
screen_resize(&pd->s, pd->sx, pd->sy, 0);
if (pd->job != NULL)
job_resize(pd->job, pd->sx, pd->sy );
@ -404,7 +448,7 @@ popup_handle_drag(struct client *c, struct popup_data *pd,
pd->ppy = py;
server_redraw_client(c);
} else if (pd->dragging == SIZE) {
if (pd->flags & POPUP_NOBORDER) {
if (pd->border_lines == BOX_LINES_NONE) {
if (m->x < pd->px + 1)
return;
if (m->y < pd->py + 1)
@ -420,7 +464,7 @@ popup_handle_drag(struct client *c, struct popup_data *pd,
pd->psx = pd->sx;
pd->psy = pd->sy;
if (pd->flags & POPUP_NOBORDER) {
if (pd->border_lines == BOX_LINES_NONE) {
screen_resize(&pd->s, pd->sx, pd->sy, 0);
if (pd->job != NULL)
job_resize(pd->job, pd->sx, pd->sy);
@ -468,7 +512,7 @@ popup_key_cb(struct client *c, void *data, struct key_event *event)
goto menu;
return (0);
}
if (~pd->flags & POPUP_NOBORDER) {
if (pd->border_lines != BOX_LINES_NONE) {
if (m->x == pd->px)
border = LEFT;
else if (m->x == pd->px + pd->sx - 1)
@ -502,7 +546,7 @@ popup_key_cb(struct client *c, void *data, struct key_event *event)
if (pd->job != NULL) {
if (KEYC_IS_MOUSE(event->key)) {
/* Must be inside, checked already. */
if (pd->flags & POPUP_NOBORDER) {
if (pd->border_lines == BOX_LINES_NONE) {
px = m->x - pd->px;
py = m->y - pd->py;
} else {
@ -588,14 +632,25 @@ popup_job_complete_cb(struct job *job)
}
int
popup_display(int flags, struct cmdq_item *item, u_int px, u_int py, u_int sx,
u_int sy, const char *shellcmd, int argc, char **argv, const char *cwd,
struct client *c, struct session *s, popup_close_cb cb, void *arg)
popup_display(int flags, enum box_lines lines, struct cmdq_item *item, u_int px,
u_int py, u_int sx, u_int sy, struct environ *env, const char *shellcmd,
int argc, char **argv, const char *cwd, const char *title, struct client *c,
struct session *s, const char* style, const char* border_style,
popup_close_cb cb, void *arg)
{
struct popup_data *pd;
u_int jx, jy;
struct options *o;
struct style sytmp;
if (flags & POPUP_NOBORDER) {
if (s != NULL)
o = s->curw->window->options;
else
o = c->session->curw->window->options;
if (lines == BOX_LINES_DEFAULT)
lines = options_get_number(o, "popup-border-lines");
if (lines == BOX_LINES_NONE) {
if (sx < 1 || sy < 1)
return (-1);
jx = sx;
@ -612,6 +667,7 @@ popup_display(int flags, struct cmdq_item *item, u_int px, u_int py, u_int sx,
pd = xcalloc(1, sizeof *pd);
pd->item = item;
pd->flags = flags;
pd->title = xstrdup(title);
pd->c = c;
pd->c->references++;
@ -620,10 +676,33 @@ popup_display(int flags, struct cmdq_item *item, u_int px, u_int py, u_int sx,
pd->arg = arg;
pd->status = 128 + SIGHUP;
pd->border_lines = lines;
memcpy(&pd->border_cell, &grid_default_cell, sizeof pd->border_cell);
style_apply(&pd->border_cell, o, "popup-border-style", NULL);
if (border_style != NULL) {
style_set(&sytmp, &grid_default_cell);
if (style_parse(&sytmp, &pd->border_cell, border_style) == 0) {
pd->border_cell.fg = sytmp.gc.fg;
pd->border_cell.bg = sytmp.gc.bg;
}
}
pd->border_cell.attr = 0;
screen_init(&pd->s, sx - 2, sy - 2, 0);
colour_palette_init(&pd->palette);
colour_palette_from_option(&pd->palette, global_w_options);
memcpy(&pd->defaults, &grid_default_cell, sizeof pd->defaults);
style_apply(&pd->defaults, o, "popup-style", NULL);
if (style != NULL) {
style_set(&sytmp, &grid_default_cell);
if (style_parse(&sytmp, &pd->defaults, style) == 0) {
pd->defaults.fg = sytmp.gc.fg;
pd->defaults.bg = sytmp.gc.bg;
}
}
pd->defaults.attr = 0;
pd->px = px;
pd->py = py;
pd->sx = sx;
@ -634,7 +713,7 @@ popup_display(int flags, struct cmdq_item *item, u_int px, u_int py, u_int sx,
pd->psx = sx;
pd->psy = sy;
pd->job = job_run(shellcmd, argc, argv, s, cwd,
pd->job = job_run(shellcmd, argc, argv, env, s, cwd,
popup_job_update_cb, popup_job_complete_cb, NULL, pd,
JOB_NOWAIT|JOB_PTY|JOB_KEEPWRITE, jx, jy);
pd->ictx = input_init(NULL, job_get_event(pd->job), &pd->palette);
@ -723,8 +802,9 @@ popup_editor(struct client *c, const char *buf, size_t len,
py = (c->tty.sy / 2) - (sy / 2);
xasprintf(&cmd, "%s %s", editor, path);
if (popup_display(POPUP_INTERNAL|POPUP_CLOSEEXIT, NULL, px, py, sx, sy,
cmd, 0, NULL, _PATH_TMP, c, NULL, popup_editor_close_cb, pe) != 0) {
if (popup_display(POPUP_INTERNAL|POPUP_CLOSEEXIT, BOX_LINES_DEFAULT,
NULL, px, py, sx, sy, NULL, cmd, 0, NULL, _PATH_TMP, NULL, c, NULL,
NULL, NULL, popup_editor_close_cb, pe) != 0) {
popup_editor_free(pe);
free(cmd);
return (-1);

View File

@ -348,6 +348,8 @@ recalculate_size_skip_client(struct client *loop, __unused int type,
* is not the current window - this is used for aggressive-resize.
* Otherwise skip any session that doesn't contain the window.
*/
if (loop->session->curw == NULL)
return (1);
if (current)
return (loop->session->curw->window != w);
return (session_has(loop->session, w) == 0);

View File

@ -31,57 +31,9 @@ static void screen_redraw_draw_pane(struct screen_redraw_ctx *,
static void screen_redraw_set_context(struct client *,
struct screen_redraw_ctx *);
#define CELL_INSIDE 0
#define CELL_TOPBOTTOM 1
#define CELL_LEFTRIGHT 2
#define CELL_TOPLEFT 3
#define CELL_TOPRIGHT 4
#define CELL_BOTTOMLEFT 5
#define CELL_BOTTOMRIGHT 6
#define CELL_TOPJOIN 7
#define CELL_BOTTOMJOIN 8
#define CELL_LEFTJOIN 9
#define CELL_RIGHTJOIN 10
#define CELL_JOIN 11
#define CELL_OUTSIDE 12
#define CELL_BORDERS " xqlkmjwvtun~"
#define START_ISOLATE "\342\201\246"
#define END_ISOLATE "\342\201\251"
static const struct utf8_data screen_redraw_double_borders[] = {
{ "", 0, 0, 0 },
{ "\342\225\221", 0, 3, 1 }, /* U+2551 */
{ "\342\225\220", 0, 3, 1 }, /* U+2550 */
{ "\342\225\224", 0, 3, 1 }, /* U+2554 */
{ "\342\225\227", 0, 3, 1 }, /* U+2557 */
{ "\342\225\232", 0, 3, 1 }, /* U+255A */
{ "\342\225\235", 0, 3, 1 }, /* U+255D */
{ "\342\225\246", 0, 3, 1 }, /* U+2566 */
{ "\342\225\251", 0, 3, 1 }, /* U+2569 */
{ "\342\225\240", 0, 3, 1 }, /* U+2560 */
{ "\342\225\243", 0, 3, 1 }, /* U+2563 */
{ "\342\225\254", 0, 3, 1 }, /* U+256C */
{ "\302\267", 0, 2, 1 } /* U+00B7 */
};
static const struct utf8_data screen_redraw_heavy_borders[] = {
{ "", 0, 0, 0 },
{ "\342\224\203", 0, 3, 1 }, /* U+2503 */
{ "\342\224\201", 0, 3, 1 }, /* U+2501 */
{ "\342\224\223", 0, 3, 1 }, /* U+2513 */
{ "\342\224\217", 0, 3, 1 }, /* U+250F */
{ "\342\224\227", 0, 3, 1 }, /* U+2517 */
{ "\342\224\233", 0, 3, 1 }, /* U+251B */
{ "\342\224\263", 0, 3, 1 }, /* U+2533 */
{ "\342\224\273", 0, 3, 1 }, /* U+253B */
{ "\342\224\243", 0, 3, 1 }, /* U+2523 */
{ "\342\224\253", 0, 3, 1 }, /* U+252B */
{ "\342\225\213", 0, 3, 1 }, /* U+254B */
{ "\302\267", 0, 2, 1 } /* U+00B7 */
};
enum screen_redraw_border_type {
SCREEN_REDRAW_OUTSIDE,
SCREEN_REDRAW_INSIDE,
@ -90,8 +42,8 @@ enum screen_redraw_border_type {
/* Get cell border character. */
static void
screen_redraw_border_set(struct window_pane *wp, int pane_lines, int cell_type,
struct grid_cell *gc)
screen_redraw_border_set(struct window_pane *wp, enum pane_lines pane_lines,
int cell_type, struct grid_cell *gc)
{
u_int idx;
@ -110,15 +62,15 @@ screen_redraw_border_set(struct window_pane *wp, int pane_lines, int cell_type,
break;
case PANE_LINES_DOUBLE:
gc->attr &= ~GRID_ATTR_CHARSET;
utf8_copy(&gc->data, &screen_redraw_double_borders[cell_type]);
utf8_copy(&gc->data, tty_acs_double_borders(cell_type));
break;
case PANE_LINES_HEAVY:
gc->attr &= ~GRID_ATTR_CHARSET;
utf8_copy(&gc->data, &screen_redraw_heavy_borders[cell_type]);
utf8_copy(&gc->data, tty_acs_heavy_borders(cell_type));
break;
case PANE_LINES_SIMPLE:
gc->attr &= ~GRID_ATTR_CHARSET;
utf8_set(&gc->data, " |-+++++++++."[cell_type]);
utf8_set(&gc->data, SIMPLE_BORDERS[cell_type]);
break;
default:
gc->attr |= GRID_ATTR_CHARSET;
@ -402,7 +354,7 @@ screen_redraw_check_is(u_int px, u_int py, int pane_status,
/* Update pane status. */
static int
screen_redraw_make_pane_status(struct client *c, struct window_pane *wp,
struct screen_redraw_ctx *rctx, int pane_lines)
struct screen_redraw_ctx *rctx, enum pane_lines pane_lines)
{
struct window *w = wp->window;
struct grid_cell gc;
@ -448,7 +400,7 @@ screen_redraw_make_pane_status(struct client *c, struct window_pane *wp,
gc.attr &= ~GRID_ATTR_CHARSET;
screen_write_cursormove(&ctx, 0, 0, 0);
format_draw(&ctx, &gc, width, expanded, NULL);
format_draw(&ctx, &gc, width, expanded, NULL, 0);
screen_write_stop(&ctx);
free(expanded);
@ -527,11 +479,12 @@ screen_redraw_draw_pane_status(struct screen_redraw_ctx *ctx)
static int
screen_redraw_update(struct client *c, int flags)
{
struct window *w = c->session->curw->window;
struct window_pane *wp;
struct options *wo = w->options;
int redraw, lines;
struct screen_redraw_ctx ctx;
struct window *w = c->session->curw->window;
struct window_pane *wp;
struct options *wo = w->options;
int redraw;
enum pane_lines lines;
struct screen_redraw_ctx ctx;
if (c->message_string != NULL)
redraw = status_message_redraw(c);
@ -685,14 +638,17 @@ screen_redraw_draw_borders_cell(struct screen_redraw_ctx *ctx, u_int i, u_int j)
struct tty *tty = &c->tty;
struct format_tree *ft;
struct window_pane *wp;
u_int cell_type, x = ctx->ox + i, y = ctx->oy + j;
int pane_status = ctx->pane_status, isolates;
struct grid_cell gc;
const struct grid_cell *tmp;
struct overlay_ranges r;
u_int cell_type, x = ctx->ox + i, y = ctx->oy + j;
int pane_status = ctx->pane_status, isolates;
if (c->overlay_check != NULL &&
!c->overlay_check(c, c->overlay_data, x, y))
return;
if (c->overlay_check != NULL) {
c->overlay_check(c, c->overlay_data, x, y, 1, &r);
if (r.nx[0] + r.nx[1] == 0)
return;
}
cell_type = screen_redraw_check_cell(c, x, y, pane_status, &wp);
if (cell_type == CELL_INSIDE)

View File

@ -184,8 +184,10 @@ screen_write_initctx(struct screen_write_ctx *ctx, struct tty_ctx *ttyctx,
if (ctx->init_ctx_cb != NULL) {
ctx->init_ctx_cb(ctx, ttyctx);
if (ttyctx->palette != NULL) {
ttyctx->defaults.fg = ttyctx->palette->fg;
ttyctx->defaults.bg = ttyctx->palette->bg;
if (ttyctx->defaults.fg == 8)
ttyctx->defaults.fg = ttyctx->palette->fg;
if (ttyctx->defaults.bg == 8)
ttyctx->defaults.bg = ttyctx->palette->bg;
}
} else {
ttyctx->redraw_cb = screen_write_redraw_cb;
@ -645,9 +647,8 @@ screen_write_menu(struct screen_write_ctx *ctx, struct menu *menu,
memcpy(&default_gc, &grid_default_cell, sizeof default_gc);
screen_write_box(ctx, menu->width + 4, menu->count + 2);
screen_write_cursormove(ctx, cx + 2, cy, 0);
format_draw(ctx, &default_gc, menu->width, menu->title, NULL);
screen_write_box(ctx, menu->width + 4, menu->count + 2,
BOX_LINES_DEFAULT, &default_gc, menu->title);
for (i = 0; i < menu->count; i++) {
name = menu->items[i].name;
@ -664,10 +665,12 @@ screen_write_menu(struct screen_write_ctx *ctx, struct menu *menu,
if (*name == '-') {
name++;
default_gc.attr |= GRID_ATTR_DIM;
format_draw(ctx, gc, menu->width, name, NULL);
format_draw(ctx, gc, menu->width, name, NULL,
0);
default_gc.attr &= ~GRID_ATTR_DIM;
} else
format_draw(ctx, gc, menu->width, name, NULL);
format_draw(ctx, gc, menu->width, name, NULL,
gc == choice_gc);
gc = &default_gc;
}
}
@ -675,39 +678,95 @@ screen_write_menu(struct screen_write_ctx *ctx, struct menu *menu,
screen_write_set_cursor(ctx, cx, cy);
}
static void
screen_write_box_border_set(enum box_lines box_lines, int cell_type,
struct grid_cell *gc)
{
switch (box_lines) {
case BOX_LINES_NONE:
break;
case BOX_LINES_DOUBLE:
gc->attr &= ~GRID_ATTR_CHARSET;
utf8_copy(&gc->data, tty_acs_double_borders(cell_type));
break;
case BOX_LINES_HEAVY:
gc->attr &= ~GRID_ATTR_CHARSET;
utf8_copy(&gc->data, tty_acs_heavy_borders(cell_type));
break;
case BOX_LINES_ROUNDED:
gc->attr &= ~GRID_ATTR_CHARSET;
utf8_copy(&gc->data, tty_acs_rounded_borders(cell_type));
break;
case BOX_LINES_SIMPLE:
gc->attr &= ~GRID_ATTR_CHARSET;
utf8_set(&gc->data, SIMPLE_BORDERS[cell_type]);
break;
case BOX_LINES_PADDED:
gc->attr &= ~GRID_ATTR_CHARSET;
utf8_set(&gc->data, PADDED_BORDERS[cell_type]);
break;
case BOX_LINES_SINGLE:
case BOX_LINES_DEFAULT:
gc->attr |= GRID_ATTR_CHARSET;
utf8_set(&gc->data, CELL_BORDERS[cell_type]);
break;
}
}
/* Draw a box on screen. */
void
screen_write_box(struct screen_write_ctx *ctx, u_int nx, u_int ny)
screen_write_box(struct screen_write_ctx *ctx, u_int nx, u_int ny,
enum box_lines lines, const struct grid_cell *gcp, const char *title)
{
struct screen *s = ctx->s;
struct grid_cell gc;
struct grid_cell gc;
u_int cx, cy, i;
cx = s->cx;
cy = s->cy;
memcpy(&gc, &grid_default_cell, sizeof gc);
if (gcp != NULL)
memcpy(&gc, gcp, sizeof gc);
else
memcpy(&gc, &grid_default_cell, sizeof gc);
gc.attr |= GRID_ATTR_CHARSET;
gc.flags |= GRID_FLAG_NOPALETTE;
screen_write_putc(ctx, &gc, 'l');
/* Draw top border */
screen_write_box_border_set(lines, CELL_TOPLEFT, &gc);
screen_write_cell(ctx, &gc);
screen_write_box_border_set(lines, CELL_LEFTRIGHT, &gc);
for (i = 1; i < nx - 1; i++)
screen_write_putc(ctx, &gc, 'q');
screen_write_putc(ctx, &gc, 'k');
screen_write_cell(ctx, &gc);
screen_write_box_border_set(lines, CELL_TOPRIGHT, &gc);
screen_write_cell(ctx, &gc);
/* Draw bottom border */
screen_write_set_cursor(ctx, cx, cy + ny - 1);
screen_write_putc(ctx, &gc, 'm');
screen_write_box_border_set(lines, CELL_BOTTOMLEFT, &gc);
screen_write_cell(ctx, &gc);
screen_write_box_border_set(lines, CELL_LEFTRIGHT, &gc);
for (i = 1; i < nx - 1; i++)
screen_write_putc(ctx, &gc, 'q');
screen_write_putc(ctx, &gc, 'j');
screen_write_cell(ctx, &gc);
screen_write_box_border_set(lines, CELL_BOTTOMRIGHT, &gc);
screen_write_cell(ctx, &gc);
/* Draw sides */
screen_write_box_border_set(lines, CELL_TOPBOTTOM, &gc);
for (i = 1; i < ny - 1; i++) {
/* left side */
screen_write_set_cursor(ctx, cx, cy + i);
screen_write_putc(ctx, &gc, 'x');
}
for (i = 1; i < ny - 1; i++) {
screen_write_cell(ctx, &gc);
/* right side */
screen_write_set_cursor(ctx, cx + nx - 1, cy + i);
screen_write_putc(ctx, &gc, 'x');
screen_write_cell(ctx, &gc);
}
if (title != NULL) {
gc.attr &= ~GRID_ATTR_CHARSET;
screen_write_cursormove(ctx, cx + 2, cy, 0);
format_draw(ctx, &gc, nx - 4, title, NULL, 0);
}
screen_write_set_cursor(ctx, cx, cy);

View File

@ -81,7 +81,10 @@ screen_init(struct screen *s, u_int sx, u_int sy, u_int hlimit)
s->path = NULL;
s->cstyle = SCREEN_CURSOR_DEFAULT;
s->ccolour = xstrdup("");
s->default_cstyle = SCREEN_CURSOR_DEFAULT;
s->default_mode = 0;
s->ccolour = -1;
s->default_ccolour = -1;
s->tabs = NULL;
s->sel = NULL;
@ -127,7 +130,6 @@ screen_free(struct screen *s)
free(s->tabs);
free(s->path);
free(s->title);
free(s->ccolour);
if (s->write_list != NULL)
screen_write_free_list(s);
@ -154,48 +156,47 @@ screen_reset_tabs(struct screen *s)
bit_set(s->tabs, i);
}
/* Set screen cursor style. */
/* Set screen cursor style and mode. */
void
screen_set_cursor_style(struct screen *s, u_int style)
screen_set_cursor_style(u_int style, enum screen_cursor_style *cstyle,
int *mode)
{
log_debug("%s: new %u, was %u", __func__, style, s->cstyle);
switch (style) {
case 0:
s->cstyle = SCREEN_CURSOR_DEFAULT;
*cstyle = SCREEN_CURSOR_DEFAULT;
break;
case 1:
s->cstyle = SCREEN_CURSOR_BLOCK;
s->mode |= MODE_CURSOR_BLINKING;
*cstyle = SCREEN_CURSOR_BLOCK;
*mode |= MODE_CURSOR_BLINKING;
break;
case 2:
s->cstyle = SCREEN_CURSOR_BLOCK;
s->mode &= ~MODE_CURSOR_BLINKING;
*cstyle = SCREEN_CURSOR_BLOCK;
*mode &= ~MODE_CURSOR_BLINKING;
break;
case 3:
s->cstyle = SCREEN_CURSOR_UNDERLINE;
s->mode |= MODE_CURSOR_BLINKING;
*cstyle = SCREEN_CURSOR_UNDERLINE;
*mode |= MODE_CURSOR_BLINKING;
break;
case 4:
s->cstyle = SCREEN_CURSOR_UNDERLINE;
s->mode &= ~MODE_CURSOR_BLINKING;
*cstyle = SCREEN_CURSOR_UNDERLINE;
*mode &= ~MODE_CURSOR_BLINKING;
break;
case 5:
s->cstyle = SCREEN_CURSOR_BAR;
s->mode |= MODE_CURSOR_BLINKING;
*cstyle = SCREEN_CURSOR_BAR;
*mode |= MODE_CURSOR_BLINKING;
break;
case 6:
s->cstyle = SCREEN_CURSOR_BAR;
s->mode &= ~MODE_CURSOR_BLINKING;
*cstyle = SCREEN_CURSOR_BAR;
*mode &= ~MODE_CURSOR_BLINKING;
break;
}
}
/* Set screen cursor colour. */
void
screen_set_cursor_colour(struct screen *s, const char *colour)
screen_set_cursor_colour(struct screen *s, int colour)
{
free(s->ccolour);
s->ccolour = xstrdup(colour);
s->ccolour = colour;
}
/* Set screen title. */

View File

@ -144,6 +144,54 @@ server_client_clear_overlay(struct client *c)
server_redraw_client(c);
}
/*
* Given overlay position and dimensions, return parts of the input range which
* are visible.
*/
void
server_client_overlay_range(u_int x, u_int y, u_int sx, u_int sy, u_int px,
u_int py, u_int nx, struct overlay_ranges *r)
{
u_int ox, onx;
/* Return up to 2 ranges. */
r->px[2] = 0;
r->nx[2] = 0;
/* Trivial case of no overlap in the y direction. */
if (py < y || py > y + sy - 1) {
r->px[0] = px;
r->nx[0] = nx;
r->px[1] = 0;
r->nx[1] = 0;
return;
}
/* Visible bit to the left of the popup. */
if (px < x) {
r->px[0] = px;
r->nx[0] = x - px;
if (r->nx[0] > nx)
r->nx[0] = nx;
} else {
r->px[0] = 0;
r->nx[0] = 0;
}
/* Visible bit to the right of the popup. */
ox = x + sx;
if (px > ox)
ox = px;
onx = px + nx;
if (onx > ox) {
r->px[1] = ox;
r->nx[1] = onx - ox;
} else {
r->px[1] = 0;
r->nx[1] = 0;
}
}
/* Check if this client is inside this server. */
int
server_client_check_nested(struct client *c)
@ -465,7 +513,7 @@ server_client_detach(struct client *c, enum msgtype msgtype)
{
struct session *s = c->session;
if (s == NULL || (c->flags & CLIENT_UNATTACHEDFLAGS))
if (s == NULL || (c->flags & CLIENT_NODETACHFLAGS))
return;
c->flags |= CLIENT_EXIT;
@ -1655,7 +1703,7 @@ server_client_reset_state(struct client *c)
struct window_pane *wp = server_client_get_pane(c), *loop;
struct screen *s = NULL;
struct options *oo = c->session->options;
int mode = 0, cursor, flags;
int mode = 0, cursor, flags, n;
u_int cx = 0, cy = 0, ox, oy, sx, sy;
if (c->flags & (CLIENT_CONTROL|CLIENT_SUSPENDED))
@ -1683,7 +1731,20 @@ server_client_reset_state(struct client *c)
tty_margin_off(tty);
/* Move cursor to pane cursor and offset. */
if (c->overlay_draw == NULL) {
if (c->prompt_string != NULL) {
n = options_get_number(c->session->options, "status-position");
if (n == 0)
cy = 0;
else {
n = status_line_size(c);
if (n == 0)
cy = tty->sy - 1;
else
cy = tty->sy - n;
}
cx = c->prompt_cursor;
mode &= ~MODE_CURSOR;
} else if (c->overlay_draw == NULL) {
cursor = 0;
tty_window_offset(tty, &ox, &oy, &sx, &sy);
if (wp->xoff + s->cx >= ox && wp->xoff + s->cx <= ox + sx &&

View File

@ -439,7 +439,8 @@ status_redraw(struct client *c)
screen_write_cursormove(&ctx, 0, i, 0);
status_free_ranges(&sle->ranges);
format_draw(&ctx, &gc, width, expanded, &sle->ranges);
format_draw(&ctx, &gc, width, expanded, &sle->ranges,
0);
free(sle->expanded);
sle->expanded = expanded;
@ -562,7 +563,7 @@ status_message_redraw(struct client *c)
if (c->message_ignore_styles)
screen_write_nputs(&ctx, len, &gc, "%s", c->message_string);
else
format_draw(&ctx, &gc, c->tty.sx, c->message_string, NULL);
format_draw(&ctx, &gc, c->tty.sx, c->message_string, NULL, 0);
screen_write_stop(&ctx);
if (grid_compare(sl->active->grid, old_screen.grid) == 0) {
@ -747,6 +748,7 @@ status_prompt_redraw(struct client *c)
offset = 0;
if (pwidth > left)
pwidth = left;
c->prompt_cursor = start + c->prompt_index - offset;
width = 0;
for (i = 0; c->prompt_buffer[i].size != 0; i++) {
@ -809,14 +811,23 @@ status_prompt_translate_key(struct client *c, key_code key, key_code *new_key)
{
if (c->prompt_mode == PROMPT_ENTRY) {
switch (key) {
case '\001': /* C-a */
case '\003': /* C-c */
case '\005': /* C-e */
case '\007': /* C-g */
case '\010': /* C-h */
case '\011': /* Tab */
case '\013': /* C-k */
case '\016': /* C-n */
case '\020': /* C-p */
case '\024': /* C-t */
case '\025': /* C-u */
case '\027': /* C-w */
case '\031': /* C-y */
case '\n':
case '\r':
case KEYC_LEFT|KEYC_CTRL:
case KEYC_RIGHT|KEYC_CTRL:
case KEYC_BSPACE:
case KEYC_DC:
case KEYC_DOWN:
@ -837,6 +848,9 @@ status_prompt_translate_key(struct client *c, key_code key, key_code *new_key)
}
switch (key) {
case KEYC_BSPACE:
*new_key = KEYC_LEFT;
return (1);
case 'A':
case 'I':
case 'C':
@ -882,7 +896,7 @@ status_prompt_translate_key(struct client *c, key_code key, key_code *new_key)
*new_key = 'B'|KEYC_VI;
return (1);
case 'd':
*new_key = '\025';
*new_key = '\025'; /* C-u */
return (1);
case 'e':
*new_key = 'e'|KEYC_VI;
@ -1714,7 +1728,7 @@ status_prompt_complete_list_menu(struct client *c, char **list, u_int size,
item.name = list[i];
item.key = '0' + (i - spm->start);
item.command = NULL;
menu_add_item(menu, &item, NULL, NULL, NULL);
menu_add_item(menu, &item, NULL, c, NULL);
}
if (options_get_number(c->session->options, "status-position") == 0)

327
tmux.1

File diff suppressed because it is too large Load Diff

109
tmux.h
View File

@ -533,6 +533,7 @@ enum tty_code_code {
#define MODE_CRLF 0x4000
#define MODE_KEXTENDED 0x8000
#define MODE_CURSOR_VERY_VISIBLE 0x10000
#define MODE_CURSOR_BLINKING_SET 0x20000
#define ALL_MODES 0xffffff
#define ALL_MOUSE_MODES (MODE_MOUSE_STANDARD|MODE_MOUSE_BUTTON|MODE_MOUSE_ALL)
@ -616,6 +617,24 @@ struct colour_palette {
#define GRID_LINE_EXTENDED 0x2
#define GRID_LINE_DEAD 0x4
#define CELL_INSIDE 0
#define CELL_TOPBOTTOM 1
#define CELL_LEFTRIGHT 2
#define CELL_TOPLEFT 3
#define CELL_TOPRIGHT 4
#define CELL_BOTTOMLEFT 5
#define CELL_BOTTOMRIGHT 6
#define CELL_TOPJOIN 7
#define CELL_BOTTOMJOIN 8
#define CELL_LEFTJOIN 9
#define CELL_RIGHTJOIN 10
#define CELL_JOIN 11
#define CELL_OUTSIDE 12
#define CELL_BORDERS " xqlkmjwvtun~"
#define SIMPLE_BORDERS " |-+++++++++."
#define PADDED_BORDERS " "
/* Grid cell data. */
struct grid_cell {
struct utf8_data data;
@ -779,11 +798,16 @@ struct screen {
u_int cy; /* cursor y */
enum screen_cursor_style cstyle; /* cursor style */
char *ccolour; /* cursor colour */
enum screen_cursor_style default_cstyle;
int ccolour; /* cursor colour */
int default_ccolour;
u_int rupper; /* scroll region top */
u_int rlower; /* scroll region bottom */
int mode;
int default_mode;
u_int saved_cx;
u_int saved_cy;
struct grid *saved_grid;
@ -817,6 +841,27 @@ struct screen_write_ctx {
u_int bg;
};
/* Box border lines option. */
enum box_lines {
BOX_LINES_DEFAULT = -1,
BOX_LINES_SINGLE,
BOX_LINES_DOUBLE,
BOX_LINES_HEAVY,
BOX_LINES_SIMPLE,
BOX_LINES_ROUNDED,
BOX_LINES_PADDED,
BOX_LINES_NONE
};
/* Pane border lines option. */
enum pane_lines {
PANE_LINES_SINGLE,
PANE_LINES_DOUBLE,
PANE_LINES_HEAVY,
PANE_LINES_SIMPLE,
PANE_LINES_NUMBER
};
/* Screen redraw context. */
struct screen_redraw_ctx {
struct client *c;
@ -825,7 +870,7 @@ struct screen_redraw_ctx {
int statustop;
int pane_status;
int pane_lines;
enum pane_lines pane_lines;
struct grid_cell no_pane_gc;
int no_pane_gc_set;
@ -1079,13 +1124,6 @@ TAILQ_HEAD(winlink_stack, winlink);
#define PANE_STATUS_TOP 1
#define PANE_STATUS_BOTTOM 2
/* Pane border lines option. */
#define PANE_LINES_SINGLE 0
#define PANE_LINES_DOUBLE 1
#define PANE_LINES_HEAVY 2
#define PANE_LINES_SIMPLE 3
#define PANE_LINES_NUMBER 4
/* Layout direction. */
enum layout_type {
LAYOUT_LEFTRIGHT,
@ -1263,7 +1301,7 @@ struct tty {
u_int cx;
u_int cy;
enum screen_cursor_style cstyle;
char *ccolour;
int ccolour;
int oflag;
u_int oox;
@ -1588,10 +1626,18 @@ struct client_window {
};
RB_HEAD(client_windows, client_window);
/* Visible areas not obstructed by overlays. */
#define OVERLAY_MAX_RANGES 3
struct overlay_ranges {
u_int px[OVERLAY_MAX_RANGES];
u_int nx[OVERLAY_MAX_RANGES];
};
/* Client connection. */
typedef int (*prompt_input_cb)(struct client *, void *, const char *, int);
typedef void (*prompt_free_cb)(void *);
typedef int (*overlay_check_cb)(struct client *, void *, u_int, u_int);
typedef void (*overlay_check_cb)(struct client*, void *, u_int, u_int, u_int,
struct overlay_ranges *);
typedef struct screen *(*overlay_mode_cb)(struct client *, void *, u_int *,
u_int *);
typedef void (*overlay_draw_cb)(struct client *, void *,
@ -1691,6 +1737,9 @@ struct client {
(CLIENT_DEAD| \
CLIENT_SUSPENDED| \
CLIENT_EXIT)
#define CLIENT_NODETACHFLAGS \
(CLIENT_DEAD| \
CLIENT_EXIT)
#define CLIENT_NOSIZEFLAGS \
(CLIENT_DEAD| \
CLIENT_SUSPENDED| \
@ -1732,6 +1781,7 @@ struct client {
#define PROMPT_KEY 0x10
int prompt_flags;
enum prompt_type prompt_type;
int prompt_cursor;
struct session *session;
struct session *last_session;
@ -2013,7 +2063,7 @@ char *format_grid_line(struct grid *, u_int);
/* format-draw.c */
void format_draw(struct screen_write_ctx *,
const struct grid_cell *, u_int, const char *,
struct style_ranges *);
struct style_ranges *, int);
u_int format_width(const char *);
char *format_trim_left(const char *, u_int);
char *format_trim_right(const char *, u_int);
@ -2079,6 +2129,8 @@ struct style *options_string_to_style(struct options *, const char *,
int options_from_string(struct options *,
const struct options_table_entry *, const char *,
const char *, int, char **);
int options_find_choice(const struct options_table_entry *,
const char *, char **);
void options_push_changes(const char *);
int options_remove_or_default(struct options_entry *, int,
char **);
@ -2094,9 +2146,9 @@ typedef void (*job_free_cb) (void *);
#define JOB_NOWAIT 0x1
#define JOB_KEEPWRITE 0x2
#define JOB_PTY 0x4
struct job *job_run(const char *, int, char **, struct session *,
const char *, job_update_cb, job_complete_cb, job_free_cb,
void *, int, int, int);
struct job *job_run(const char *, int, char **, struct environ *,
struct session *, const char *, job_update_cb,
job_complete_cb, job_free_cb, void *, int, int, int);
void job_free(struct job *);
int job_transfer(struct job *, pid_t *, char *, size_t);
void job_resize(struct job *, u_int, u_int);
@ -2231,6 +2283,9 @@ void tty_default_features(int *, const char *, u_int);
int tty_acs_needed(struct tty *);
const char *tty_acs_get(struct tty *, u_char);
int tty_acs_reverse_get(struct tty *, const char *, size_t);
const struct utf8_data *tty_acs_double_borders(int);
const struct utf8_data *tty_acs_heavy_borders(int);
const struct utf8_data *tty_acs_rounded_borders(int);
/* tty-keys.c */
void tty_keys_build(struct tty *);
@ -2485,6 +2540,8 @@ void server_client_set_overlay(struct client *, u_int, overlay_check_cb,
overlay_mode_cb, overlay_draw_cb, overlay_key_cb,
overlay_free_cb, overlay_resize_cb, void *);
void server_client_clear_overlay(struct client *);
void server_client_overlay_range(u_int, u_int, u_int, u_int, u_int, u_int,
u_int, struct overlay_ranges *);
void server_client_set_key_table(struct client *, const char *);
const char *server_client_get_key_table(struct client *);
int server_client_check_nested(struct client *);
@ -2592,6 +2649,7 @@ int input_key_get_mouse(struct screen *, struct mouse_event *, u_int,
int colour_find_rgb(u_char, u_char, u_char);
int colour_join_rgb(u_char, u_char, u_char);
void colour_split_rgb(int, u_char *, u_char *, u_char *);
int colour_force_rgb(int);
const char *colour_tostring(int);
int colour_fromstring(const char *s);
int colour_256toRGB(int);
@ -2712,7 +2770,8 @@ void screen_write_hline(struct screen_write_ctx *, u_int, int, int);
void screen_write_vline(struct screen_write_ctx *, u_int, int, int);
void screen_write_menu(struct screen_write_ctx *, struct menu *, int,
const struct grid_cell *);
void screen_write_box(struct screen_write_ctx *, u_int, u_int);
void screen_write_box(struct screen_write_ctx *, u_int, u_int, int,
const struct grid_cell *, const char *);
void screen_write_preview(struct screen_write_ctx *, struct screen *, u_int,
u_int);
void screen_write_backspace(struct screen_write_ctx *);
@ -2765,8 +2824,8 @@ void screen_init(struct screen *, u_int, u_int, u_int);
void screen_reinit(struct screen *);
void screen_free(struct screen *);
void screen_reset_tabs(struct screen *);
void screen_set_cursor_style(struct screen *, u_int);
void screen_set_cursor_colour(struct screen *, const char *);
void screen_set_cursor_style(u_int, enum screen_cursor_style *, int *);
void screen_set_cursor_colour(struct screen *, int);
int screen_set_title(struct screen *, const char *);
void screen_set_path(struct screen *, const char *);
void screen_push_title(struct screen *);
@ -3117,7 +3176,8 @@ int menu_display(struct menu *, int, struct cmdq_item *, u_int,
u_int, struct client *, struct cmd_find_state *,
menu_choice_cb, void *);
struct screen *menu_mode_cb(struct client *, void *, u_int *, u_int *);
int menu_check_cb(struct client *, void *, u_int, u_int);
void menu_check_cb(struct client *, void *, u_int, u_int, u_int,
struct overlay_ranges *);
void menu_draw_cb(struct client *, void *,
struct screen_redraw_ctx *);
void menu_free_cb(struct client *, void *);
@ -3126,13 +3186,14 @@ int menu_key_cb(struct client *, void *, struct key_event *);
/* popup.c */
#define POPUP_CLOSEEXIT 0x1
#define POPUP_CLOSEEXITZERO 0x2
#define POPUP_NOBORDER 0x4
#define POPUP_INTERNAL 0x8
#define POPUP_INTERNAL 0x4
typedef void (*popup_close_cb)(int, void *);
typedef void (*popup_finish_edit_cb)(char *, size_t, void *);
int popup_display(int, struct cmdq_item *, u_int, u_int, u_int,
u_int, const char *, int, char **, const char *,
struct client *, struct session *, popup_close_cb, void *);
int popup_display(int, int, struct cmdq_item *, u_int, u_int,
u_int, u_int, struct environ *, const char *, int, char **,
const char *, const char *, struct client *,
struct session *, const char *, const char *,
popup_close_cb, void *);
int popup_editor(struct client *, const char *, size_t,
popup_finish_edit_cb, void *);

View File

@ -184,7 +184,7 @@ Oct Hex Name * (* marks function used in DEC VT series or LA series terminals)
230 98 X Reserved for for future standard
231 99 Y Reserved
232 9A Z * Reserved, but causes DEC terminals to respond with DA codes
233 9B [ CSI * Control Sequence Introducer (described in a seperate table)
233 9B [ CSI * Control Sequence Introducer (described in a separate table)
234 9C \ ST * String Terminator (VT125 exits graphics)
235 9D ] OSC Operating System Command (reprograms intelligent terminal)
236 9E ^ PM Privacy Message (password verification), terminated by ST

View File

@ -25,7 +25,7 @@
/* Table mapping ACS entries to UTF-8. */
struct tty_acs_entry {
u_char key;
u_char key;
const char *string;
};
static const struct tty_acs_entry tty_acs_table[] = {
@ -61,7 +61,7 @@ static const struct tty_acs_entry tty_acs_table[] = {
{ 'x', "\342\224\202" }, /* vertical line */
{ 'y', "\342\211\244" }, /* less-than-or-equal-to */
{ 'z', "\342\211\245" }, /* greater-than-or-equal-to */
{ '{', "\317\200" }, /* greek pi */
{ '{', "\317\200" }, /* greek pi */
{ '|', "\342\211\240" }, /* not-equal */
{ '}', "\302\243" }, /* UK pound sign */
{ '~', "\302\267" } /* bullet */
@ -110,6 +110,78 @@ static const struct tty_acs_reverse_entry tty_acs_reverse3[] = {
{ "\342\225\254", 'n' },
};
/* UTF-8 double borders. */
static const struct utf8_data tty_acs_double_borders_list[] = {
{ "", 0, 0, 0 },
{ "\342\225\221", 0, 3, 1 }, /* U+2551 */
{ "\342\225\220", 0, 3, 1 }, /* U+2550 */
{ "\342\225\224", 0, 3, 1 }, /* U+2554 */
{ "\342\225\227", 0, 3, 1 }, /* U+2557 */
{ "\342\225\232", 0, 3, 1 }, /* U+255A */
{ "\342\225\235", 0, 3, 1 }, /* U+255D */
{ "\342\225\246", 0, 3, 1 }, /* U+2566 */
{ "\342\225\251", 0, 3, 1 }, /* U+2569 */
{ "\342\225\240", 0, 3, 1 }, /* U+2560 */
{ "\342\225\243", 0, 3, 1 }, /* U+2563 */
{ "\342\225\254", 0, 3, 1 }, /* U+256C */
{ "\302\267", 0, 2, 1 } /* U+00B7 */
};
/* UTF-8 heavy borders. */
static const struct utf8_data tty_acs_heavy_borders_list[] = {
{ "", 0, 0, 0 },
{ "\342\224\203", 0, 3, 1 }, /* U+2503 */
{ "\342\224\201", 0, 3, 1 }, /* U+2501 */
{ "\342\224\217", 0, 3, 1 }, /* U+250F */
{ "\342\224\223", 0, 3, 1 }, /* U+2513 */
{ "\342\224\227", 0, 3, 1 }, /* U+2517 */
{ "\342\224\233", 0, 3, 1 }, /* U+251B */
{ "\342\224\263", 0, 3, 1 }, /* U+2533 */
{ "\342\224\273", 0, 3, 1 }, /* U+253B */
{ "\342\224\243", 0, 3, 1 }, /* U+2523 */
{ "\342\224\253", 0, 3, 1 }, /* U+252B */
{ "\342\225\213", 0, 3, 1 }, /* U+254B */
{ "\302\267", 0, 2, 1 } /* U+00B7 */
};
/* UTF-8 rounded borders. */
static const struct utf8_data tty_acs_rounded_borders_list[] = {
{ "", 0, 0, 0 },
{ "\342\224\202", 0, 3, 1 }, /* U+2502 */
{ "\342\224\200", 0, 3, 1 }, /* U+2500 */
{ "\342\225\255", 0, 3, 1 }, /* U+256D */
{ "\342\225\256", 0, 3, 1 }, /* U+256E */
{ "\342\225\260", 0, 3, 1 }, /* U+2570 */
{ "\342\225\257", 0, 3, 1 }, /* U+256F */
{ "\342\224\263", 0, 3, 1 }, /* U+2533 */
{ "\342\224\273", 0, 3, 1 }, /* U+253B */
{ "\342\224\243", 0, 3, 1 }, /* U+2523 */
{ "\342\224\253", 0, 3, 1 }, /* U+252B */
{ "\342\225\213", 0, 3, 1 }, /* U+254B */
{ "\302\267", 0, 2, 1 } /* U+00B7 */
};
/* Get cell border character for double style. */
const struct utf8_data *
tty_acs_double_borders(int cell_type)
{
return (&tty_acs_double_borders_list[cell_type]);
}
/* Get cell border character for heavy style. */
const struct utf8_data *
tty_acs_heavy_borders(int cell_type)
{
return (&tty_acs_heavy_borders_list[cell_type]);
}
/* Get cell border character for rounded style. */
const struct utf8_data *
tty_acs_rounded_borders(int cell_type)
{
return (&tty_acs_rounded_borders_list[cell_type]);
}
static int
tty_acs_cmp(const void *key, const void *value)
{

View File

@ -1204,6 +1204,9 @@ tty_keys_clipboard(__unused struct tty *tty, const char *buf, size_t len,
buf += 5;
end -= 5;
/* Adjust end so that it points to the start of the terminator. */
end -= terminator - 1;
/* Get the second argument. */
while (end != 0 && *buf != ';') {
buf++;

260
tty.c
View File

@ -38,7 +38,7 @@ static int tty_client_ready(struct client *);
static void tty_set_italics(struct tty *);
static int tty_try_colour(struct tty *, int, const char *);
static void tty_force_cursor_colour(struct tty *, const char *);
static void tty_force_cursor_colour(struct tty *, int);
static void tty_cursor_pane(struct tty *, const struct tty_ctx *, u_int,
u_int);
static void tty_cursor_pane_unless_wrap(struct tty *,
@ -71,6 +71,8 @@ static void tty_draw_pane(struct tty *, const struct tty_ctx *, u_int);
static void tty_default_attributes(struct tty *, const struct grid_cell *,
struct colour_palette *, u_int);
static int tty_check_overlay(struct tty *, u_int, u_int);
static void tty_check_overlay_range(struct tty *, u_int, u_int, u_int,
struct overlay_ranges *);
#define tty_use_margin(tty) \
(tty->term->flags & TERM_DECSLRM)
@ -103,7 +105,7 @@ tty_init(struct tty *tty, struct client *c)
tty->client = c;
tty->cstyle = SCREEN_CURSOR_DEFAULT;
tty->ccolour = xstrdup("");
tty->ccolour = -1;
if (tcgetattr(c->fd, &tty->tio) != 0)
return (-1);
@ -305,7 +307,7 @@ tty_start_tty(struct tty *tty)
{
struct client *c = tty->client;
struct termios tio;
struct timeval tv = { .tv_sec = 1 };
struct timeval tv = { .tv_sec = 3 };
setblocking(c->fd, 0);
event_add(&tty->event_in, NULL);
@ -344,8 +346,8 @@ tty_start_tty(struct tty *tty)
tty->flags |= TTY_STARTED;
tty_invalidate(tty);
if (*tty->ccolour != '\0')
tty_force_cursor_colour(tty, "");
if (tty->ccolour != -1)
tty_force_cursor_colour(tty, -1);
tty->mouse_drag_flag = 0;
tty->mouse_drag_update = NULL;
@ -409,7 +411,7 @@ tty_stop_tty(struct tty *tty)
}
if (tty->mode & MODE_BRACKETPASTE)
tty_raw(tty, tty_term_string(tty->term, TTYC_DSBP));
if (*tty->ccolour != '\0')
if (tty->ccolour != -1)
tty_raw(tty, tty_term_string(tty->term, TTYC_CR));
tty_raw(tty, tty_term_string(tty->term, TTYC_CNORM));
@ -454,7 +456,6 @@ void
tty_free(struct tty *tty)
{
tty_close(tty);
free(tty->ccolour);
}
void
@ -653,39 +654,66 @@ tty_set_title(struct tty *tty, const char *title)
}
static void
tty_force_cursor_colour(struct tty *tty, const char *ccolour)
tty_force_cursor_colour(struct tty *tty, int c)
{
if (*ccolour == '\0')
u_char r, g, b;
char s[13] = "";
if (c != -1)
c = colour_force_rgb(c);
if (c == tty->ccolour)
return;
if (c == -1)
tty_putcode(tty, TTYC_CR);
else
tty_putcode_ptr1(tty, TTYC_CS, ccolour);
free(tty->ccolour);
tty->ccolour = xstrdup(ccolour);
else {
colour_split_rgb(c, &r, &g, &b);
xsnprintf(s, sizeof s, "rgb:%02hhx/%02hhx/%02hhx", r, g, b);
tty_putcode_ptr1(tty, TTYC_CS, s);
}
tty->ccolour = c;
}
static void
tty_update_cursor(struct tty *tty, int mode, int changed, struct screen *s)
static int
tty_update_cursor(struct tty *tty, int mode, struct screen *s)
{
enum screen_cursor_style cstyle;
enum screen_cursor_style cstyle;
int ccolour, changed, cmode = mode;
/* Set cursor colour if changed. */
if (s != NULL && strcmp(s->ccolour, tty->ccolour) != 0)
tty_force_cursor_colour(tty, s->ccolour);
if (s != NULL) {
ccolour = s->ccolour;
if (s->ccolour == -1)
ccolour = s->default_ccolour;
tty_force_cursor_colour(tty, ccolour);
}
/* If cursor is off, set as invisible. */
if (~mode & MODE_CURSOR) {
if (changed & MODE_CURSOR)
if (~cmode & MODE_CURSOR) {
if (tty->mode & MODE_CURSOR)
tty_putcode(tty, TTYC_CIVIS);
return;
return (cmode);
}
/* Check if blinking or very visible flag changed or style changed. */
if (s == NULL)
cstyle = tty->cstyle;
else
else {
cstyle = s->cstyle;
if (cstyle == SCREEN_CURSOR_DEFAULT) {
if (~cmode & MODE_CURSOR_BLINKING_SET) {
if (s->default_mode & MODE_CURSOR_BLINKING)
cmode |= MODE_CURSOR_BLINKING;
else
cmode &= ~MODE_CURSOR_BLINKING;
}
cstyle = s->default_cstyle;
}
}
/* If nothing changed, do nothing. */
changed = cmode ^ tty->mode;
if ((changed & CURSOR_MODES) == 0 && cstyle == tty->cstyle)
return;
return (cmode);
/*
* Set cursor style. If an explicit style has been set with DECSCUSR,
@ -703,49 +731,56 @@ tty_update_cursor(struct tty *tty, int mode, int changed, struct screen *s)
else
tty_putcode1(tty, TTYC_SS, 0);
}
if (mode & (MODE_CURSOR_BLINKING|MODE_CURSOR_VERY_VISIBLE))
if (cmode & (MODE_CURSOR_BLINKING|MODE_CURSOR_VERY_VISIBLE))
tty_putcode(tty, TTYC_CVVIS);
break;
case SCREEN_CURSOR_BLOCK:
if (tty_term_has(tty->term, TTYC_SS)) {
if (mode & MODE_CURSOR_BLINKING)
if (cmode & MODE_CURSOR_BLINKING)
tty_putcode1(tty, TTYC_SS, 1);
else
tty_putcode1(tty, TTYC_SS, 2);
} else if (mode & MODE_CURSOR_BLINKING)
} else if (cmode & MODE_CURSOR_BLINKING)
tty_putcode(tty, TTYC_CVVIS);
break;
case SCREEN_CURSOR_UNDERLINE:
if (tty_term_has(tty->term, TTYC_SS)) {
if (mode & MODE_CURSOR_BLINKING)
if (cmode & MODE_CURSOR_BLINKING)
tty_putcode1(tty, TTYC_SS, 3);
else
tty_putcode1(tty, TTYC_SS, 4);
} else if (mode & MODE_CURSOR_BLINKING)
} else if (cmode & MODE_CURSOR_BLINKING)
tty_putcode(tty, TTYC_CVVIS);
break;
case SCREEN_CURSOR_BAR:
if (tty_term_has(tty->term, TTYC_SS)) {
if (mode & MODE_CURSOR_BLINKING)
if (cmode & MODE_CURSOR_BLINKING)
tty_putcode1(tty, TTYC_SS, 5);
else
tty_putcode1(tty, TTYC_SS, 6);
} else if (mode & MODE_CURSOR_BLINKING)
} else if (cmode & MODE_CURSOR_BLINKING)
tty_putcode(tty, TTYC_CVVIS);
break;
}
tty->cstyle = cstyle;
return (cmode);
}
void
tty_update_mode(struct tty *tty, int mode, struct screen *s)
{
struct tty_term *term = tty->term;
struct client *c = tty->client;
int changed;
if (tty->flags & TTY_NOCURSOR)
mode &= ~MODE_CURSOR;
if (tty_update_cursor(tty, mode, s) & MODE_CURSOR_BLINKING)
mode |= MODE_CURSOR_BLINKING;
else
mode &= ~MODE_CURSOR_BLINKING;
changed = mode ^ tty->mode;
if (log_get_level() != 0 && changed != 0) {
log_debug("%s: current mode %s", c->name,
@ -754,9 +789,7 @@ tty_update_mode(struct tty *tty, int mode, struct screen *s)
screen_mode_to_string(mode));
}
tty_update_cursor(tty, mode, changed, s);
if ((changed & ALL_MOUSE_MODES) &&
tty_term_has(tty->term, TTYC_KMOUS)) {
if ((changed & ALL_MOUSE_MODES) && tty_term_has(term, TTYC_KMOUS)) {
/*
* If the mouse modes have changed, clear any that are set and
* apply again. There are differences in how terminals track
@ -909,7 +942,9 @@ tty_update_window_offset(struct window *w)
struct client *c;
TAILQ_FOREACH(c, &clients, entry) {
if (c->session != NULL && c->session->curw->window == w)
if (c->session != NULL &&
c->session->curw != NULL &&
c->session->curw->window == w)
tty_update_client_offset(c);
}
}
@ -1051,8 +1086,9 @@ static void
tty_clear_line(struct tty *tty, const struct grid_cell *defaults, u_int py,
u_int px, u_int nx, u_int bg)
{
struct client *c = tty->client;
u_int i;
struct client *c = tty->client;
struct overlay_ranges r;
u_int i;
log_debug("%s: %s, %u at %u,%u", __func__, c->name, nx, px, py);
@ -1088,18 +1124,13 @@ tty_clear_line(struct tty *tty, const struct grid_cell *defaults, u_int py,
* Couldn't use an escape sequence, use spaces. Clear only the visible
* bit if there is an overlay.
*/
for (i = 0; i < nx; i++) {
if (!tty_check_overlay(tty, px + i, py))
break;
tty_check_overlay_range(tty, px, py, nx, &r);
for (i = 0; i < OVERLAY_MAX_RANGES; i++) {
if (r.nx[i] == 0)
continue;
tty_cursor(tty, r.px[i], py);
tty_repeat_space(tty, r.nx[i]);
}
tty_cursor(tty, px, py);
tty_repeat_space(tty, i);
for (; i < nx; i++) {
if (tty_check_overlay(tty, px + i, py))
break;
}
tty_cursor(tty, px + i, py);
tty_repeat_space(tty, nx - i);
}
/* Clear a line, adjusting to visible part of pane. */
@ -1311,14 +1342,44 @@ tty_check_codeset(struct tty *tty, const struct grid_cell *gc)
return (&new);
}
/*
* Check if a single character is obstructed by the overlay and return a
* boolean.
*/
static int
tty_check_overlay(struct tty *tty, u_int px, u_int py)
{
struct overlay_ranges r;
/*
* A unit width range will always return nx[2] == 0 from a check, even
* with multiple overlays, so it's sufficient to check just the first
* two entries.
*/
tty_check_overlay_range(tty, px, py, 1, &r);
if (r.nx[0] + r.nx[1] == 0)
return (0);
return (1);
}
/* Return parts of the input range which are visible. */
static void
tty_check_overlay_range(struct tty *tty, u_int px, u_int py, u_int nx,
struct overlay_ranges *r)
{
struct client *c = tty->client;
if (c->overlay_check == NULL)
return (1);
return (c->overlay_check(c, c->overlay_data, px, py));
if (c->overlay_check == NULL) {
r->px[0] = px;
r->nx[0] = nx;
r->px[1] = 0;
r->nx[1] = 0;
r->px[2] = 0;
r->nx[2] = 0;
return;
}
c->overlay_check(c, c->overlay_data, px, py, nx, r);
}
void
@ -1331,11 +1392,12 @@ tty_draw_line(struct tty *tty, struct screen *s, u_int px, u_int py, u_int nx,
const struct grid_cell *gcp;
struct grid_line *gl;
struct client *c = tty->client;
u_int i, j, ux, sx, width, hidden;
struct overlay_ranges r;
u_int i, j, ux, sx, width, hidden, eux, nxx;
u_int cellsize;
int flags, cleared = 0, wrapped = 0;
char buf[512];
size_t len;
u_int cellsize;
log_debug("%s: px=%u py=%u nx=%u atx=%u aty=%u", __func__,
px, py, nx, atx, aty);
@ -1435,29 +1497,31 @@ tty_draw_line(struct tty *tty, struct screen *s, u_int px, u_int py, u_int nx,
else
memcpy(&last, gcp, sizeof last);
tty_check_overlay_range(tty, atx + ux, aty, gcp->data.width,
&r);
hidden = 0;
for (j = 0; j < gcp->data.width; j++) {
if (!tty_check_overlay(tty, atx + ux + j, aty))
hidden++;
}
for (j = 0; j < OVERLAY_MAX_RANGES; j++)
hidden += r.nx[j];
hidden = gcp->data.width - hidden;
if (hidden != 0 && hidden == gcp->data.width) {
if (~gcp->flags & GRID_FLAG_PADDING)
ux += gcp->data.width;
} else if (hidden != 0 || ux + gcp->data.width > nx) {
if (~gcp->flags & GRID_FLAG_PADDING) {
tty_attributes(tty, &last, defaults, palette);
tty_cursor(tty, atx + ux, aty);
for (j = 0; j < gcp->data.width; j++) {
if (ux > nx)
break;
if (tty_check_overlay(tty, atx + ux,
aty))
tty_putc(tty, ' ');
else {
tty_cursor(tty, atx + ux + 1,
aty);
for (j = 0; j < OVERLAY_MAX_RANGES; j++) {
if (r.nx[j] == 0)
continue;
/* Effective width drawn so far. */
eux = r.px[j] - atx;
if (eux < nx) {
tty_cursor(tty, r.px[j], aty);
nxx = nx - eux;
if (r.nx[j] > nxx)
r.nx[j] = nxx;
tty_repeat_space(tty, r.nx[j]);
ux = eux + r.nx[j];
}
ux++;
}
}
} else if (gcp->attr & GRID_ATTR_CHARSET) {
@ -1963,7 +2027,8 @@ tty_cmd_cell(struct tty *tty, const struct tty_ctx *ctx)
{
const struct grid_cell *gcp = ctx->cell;
struct screen *s = ctx->s;
u_int i, px, py;
struct overlay_ranges r;
u_int px, py, i, vis = 0;
px = ctx->xoff + ctx->ocx - ctx->wox;
py = ctx->yoff + ctx->ocy - ctx->woy;
@ -1973,13 +2038,13 @@ tty_cmd_cell(struct tty *tty, const struct tty_ctx *ctx)
/* Handle partially obstructed wide characters. */
if (gcp->data.width > 1) {
for (i = 0; i < gcp->data.width; i++) {
if (!tty_check_overlay(tty, px + i, py)) {
tty_draw_line(tty, s, s->cx, s->cy,
gcp->data.width, px, py, &ctx->defaults,
ctx->palette);
return;
}
tty_check_overlay_range(tty, px, py, gcp->data.width, &r);
for (i = 0; i < OVERLAY_MAX_RANGES; i++)
vis += r.nx[i];
if (vis < gcp->data.width) {
tty_draw_line(tty, s, s->cx, s->cy, gcp->data.width,
px, py, &ctx->defaults, ctx->palette);
return;
}
}
@ -1997,7 +2062,9 @@ tty_cmd_cell(struct tty *tty, const struct tty_ctx *ctx)
void
tty_cmd_cells(struct tty *tty, const struct tty_ctx *ctx)
{
u_int i, hide = 0;
struct overlay_ranges r;
u_int i, px, py, cx;
char *cp = ctx->ptr;
if (!tty_is_visible(tty, ctx, ctx->ocx, ctx->ocy, ctx->num, 1))
return;
@ -2020,20 +2087,21 @@ tty_cmd_cells(struct tty *tty, const struct tty_ctx *ctx)
tty_margin_off(tty);
tty_cursor_pane_unless_wrap(tty, ctx, ctx->ocx, ctx->ocy);
tty_attributes(tty, ctx->cell, &ctx->defaults, ctx->palette);
for (i = 0; i < ctx->num; i++) {
if (!tty_check_overlay(tty, tty->cx + i, tty->cy))
break;
/* Get tty position from pane position for overlay check. */
px = ctx->xoff + ctx->ocx - ctx->wox;
py = ctx->yoff + ctx->ocy - ctx->woy;
tty_check_overlay_range(tty, px, py, ctx->num, &r);
for (i = 0; i < OVERLAY_MAX_RANGES; i++) {
if (r.nx[i] == 0)
continue;
/* Convert back to pane position for printing. */
cx = r.px[i] - ctx->xoff + ctx->wox;
tty_cursor_pane_unless_wrap(tty, ctx, cx, ctx->ocy);
tty_putn(tty, cp + r.px[i] - px, r.nx[i], r.nx[i]);
}
tty_putn(tty, ctx->ptr, i, i);
for (; i < ctx->num; i++) {
if (tty_check_overlay(tty, tty->cx + hide, tty->cy))
break;
hide++;
}
tty_cursor(tty, tty->cx + hide, tty->cy);
tty_putn(tty, (char *)ctx->ptr + i, ctx->num - i, ctx->num - i);
}
void
@ -2321,17 +2389,25 @@ tty_cursor(struct tty *tty, u_int cx, u_int cy)
if (tty->flags & TTY_BLOCK)
return;
if (cx > tty->sx - 1)
cx = tty->sx - 1;
thisx = tty->cx;
thisy = tty->cy;
/*
* If in the automargin space, and want to be there, do not move.
* Otherwise, force the cursor to be in range (and complain).
*/
if (cx == thisx && cy == thisy && cx == tty->sx)
return;
if (cx > tty->sx - 1) {
log_debug("%s: x too big %u > %u", __func__, cx, tty->sx - 1);
cx = tty->sx - 1;
}
/* No change. */
if (cx == thisx && cy == thisy)
return;
/* Very end of the line, just use absolute movement. */
/* Currently at the very end of the line - use absolute movement. */
if (thisx > tty->sx - 1)
goto absolute;

15
utf8.c
View File

@ -237,21 +237,6 @@ utf8_width(struct utf8_data *ud, int *width)
if (*width >= 0 && *width <= 0xff)
return (UTF8_DONE);
log_debug("UTF-8 %.*s, wcwidth() %d", (int)ud->size, ud->data, *width);
#ifndef __OpenBSD__
/*
* Many platforms (particularly and inevitably OS X) have no width for
* relatively common characters (wcwidth() returns -1); assume width 1
* in this case. This will be wrong for genuinely nonprintable
* characters, but they should be rare. We may pass through stuff that
* ideally we would block, but this is no worse than sending the same
* to the terminal without tmux.
*/
if (*width < 0) {
*width = 1;
return (UTF8_DONE);
}
#endif
return (UTF8_ERROR);
}

View File

@ -4531,8 +4531,8 @@ window_copy_pipe_run(struct window_mode_entry *wme, struct session *s,
if (cmd == NULL || *cmd == '\0')
cmd = options_get_string(global_options, "copy-command");
if (cmd != NULL && *cmd != '\0') {
job = job_run(cmd, 0, NULL, s, NULL, NULL, NULL, NULL, NULL,
JOB_NOWAIT, -1, -1);
job = job_run(cmd, 0, NULL, NULL, s, NULL, NULL, NULL, NULL,
NULL, JOB_NOWAIT, -1, -1);
bufferevent_write(job_get_event(job), buf, *len);
}
return (buf);

View File

@ -398,11 +398,11 @@ window_customize_build_options(struct window_customize_modedata *data,
for (i = 0; i < size; i++) {
if (oo2 != NULL)
o = options_get(oo0, list[i]);
o = options_get(oo2, list[i]);
if (o == NULL && oo1 != NULL)
o = options_get(oo1, list[i]);
if (o == NULL)
o = options_get(oo2, list[i]);
o = options_get(oo0, list[i]);
if (options_owner(o) == oo2)
scope = scope2;
else if (options_owner(o) == oo1)

View File

@ -519,7 +519,8 @@ window_tree_draw_label(struct screen_write_ctx *ctx, u_int px, u_int py,
if (ox > 1 && ox + len < sx - 1 && sy >= 3) {
screen_write_cursormove(ctx, px + ox - 1, py + oy - 1, 0);
screen_write_box(ctx, len + 2, 3);
screen_write_box(ctx, len + 2, 3, BOX_LINES_DEFAULT, NULL,
NULL);
}
screen_write_cursormove(ctx, px + ox, py + oy, 0);
screen_write_puts(ctx, gc, "%s", label);