mirror of
https://github.com/tmux/tmux.git
synced 2025-01-09 01:28:49 +00:00
Merge branch 'master' into sixel
This commit is contained in:
commit
906c92a5f4
2
.github/CONTRIBUTING.md
vendored
2
.github/CONTRIBUTING.md
vendored
@ -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
2
.github/README.md
vendored
@ -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
2
README
@ -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
|
||||
|
||||
|
@ -3,7 +3,7 @@ tmuxへようこそ!
|
||||
tmuxはターミナルマルチプレクサーです。複数のターミナルを一つのスクリーン内に作成し、操作することができます。
|
||||
バックグラウンドで処理を実行中に一度スクリーンから離れて後から復帰することも可能です。
|
||||
|
||||
OpenBSD、FreeBSD、NetBSD、Linux、OS X、Solarisで実行できます。
|
||||
OpenBSD、FreeBSD、NetBSD、Linux、macOS、Solarisで実行できます。
|
||||
|
||||
tmuxはlibevent 2.x.に依存します。 下記からダウンロードしてください。
|
||||
|
||||
|
@ -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. */
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
15
colour.c
15
colour.c
@ -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)
|
||||
|
@ -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)
|
||||
|
26
format.c
26
format.c
@ -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
76
input.c
@ -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
7
job.c
@ -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
49
menu.c
@ -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
|
||||
|
18
mode-tree.c
18
mode-tree.c
@ -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)
|
||||
|
@ -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,
|
||||
|
50
options.c
50
options.c
@ -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);
|
||||
|
@ -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
142
popup.c
@ -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);
|
||||
|
2
resize.c
2
resize.c
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
43
screen.c
43
screen.c
@ -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. */
|
||||
|
@ -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 &&
|
||||
|
22
status.c
22
status.c
@ -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)
|
||||
|
109
tmux.h
109
tmux.h
@ -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 *);
|
||||
|
||||
|
@ -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
|
||||
|
76
tty-acs.c
76
tty-acs.c
@ -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)
|
||||
{
|
||||
|
@ -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
260
tty.c
@ -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
15
utf8.c
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user