aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGES26
-rw-r--r--cmd-command-prompt.c25
-rw-r--r--cmd-confirm-before.c16
-rw-r--r--cmd-new-session.c15
-rw-r--r--cmd-refresh-client.c5
-rw-r--r--cmd-resize-pane.c56
-rw-r--r--cmd-send-keys.c2
-rw-r--r--cmd-set-option.c60
-rw-r--r--cmd-show-options.c17
-rw-r--r--configure.ac11
-rw-r--r--environ.c10
-rw-r--r--format.c36
-rw-r--r--grid-view.c16
-rw-r--r--grid.c10
-rw-r--r--input.c59
-rw-r--r--key-bindings.c17
-rw-r--r--layout-set.c5
-rw-r--r--regress/control-client-size.sh49
-rw-r--r--regress/new-session-size.sh27
-rw-r--r--resize.c3
-rw-r--r--screen-write.c33
-rw-r--r--server-client.c17
-rw-r--r--server-fn.c2
-rw-r--r--status.c23
-rw-r--r--tmux.17
-rw-r--r--tmux.h35
-rw-r--r--tty-acs.c37
-rw-r--r--tty-term.c1
-rw-r--r--tty.c325
-rw-r--r--window-copy.c27
-rw-r--r--window.c1
31 files changed, 617 insertions, 356 deletions
diff --git a/CHANGES b/CHANGES
index 4c84c923..7634bae5 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,29 @@
+CHANGES FROM 2.5 to master
+
+* Support OSC 10 and OSC 11 to set foreground and background colours.
+
+* Check the U8 capability to determine whether to use UTF-8 line drawing
+ characters for ACS.
+
+* Some missing notifications for layout changes.
+
+* Control mode clients now do not affect session sizes until they issue
+ refresh-client -C. new-session -x and -y works with control clients even if
+ the session is not detached.
+
+* All new sessions that are unattached (whether with -d or started with no
+ terminal) are now created with size 80 x 24. Whether the status line is on or
+ off does not affect the size of new sessions until they are attached.
+
+* Expand formats in option names and add -F flag to expand them in option values.
+
+* Remember the search string for a pane even if copy mode is exited and entered
+ again.
+
+* Some further BCE fixes (scroll up, reverse index).
+
+* Improvements to how terminals are cleared (entirely or partially).
+
CHANGES FROM 2.4 to 2.5 09 May 2017
* Reset updated flag when restarting #() command so that new output is properly
diff --git a/cmd-command-prompt.c b/cmd-command-prompt.c
index 45a71525..d7159ad0 100644
--- a/cmd-command-prompt.c
+++ b/cmd-command-prompt.c
@@ -32,7 +32,8 @@
static enum cmd_retval cmd_command_prompt_exec(struct cmd *,
struct cmdq_item *);
-static int cmd_command_prompt_callback(void *, const char *, int);
+static int cmd_command_prompt_callback(struct client *, void *,
+ const char *, int);
static void cmd_command_prompt_free(void *);
const struct cmd_entry cmd_command_prompt_entry = {
@@ -48,17 +49,16 @@ const struct cmd_entry cmd_command_prompt_entry = {
};
struct cmd_command_prompt_cdata {
- struct client *c;
- int flags;
+ int flags;
- char *inputs;
- char *next_input;
+ char *inputs;
+ char *next_input;
- char *prompts;
- char *next_prompt;
+ char *prompts;
+ char *next_prompt;
- char *template;
- int idx;
+ char *template;
+ int idx;
};
static enum cmd_retval
@@ -78,7 +78,6 @@ cmd_command_prompt_exec(struct cmd *self, struct cmdq_item *item)
return (CMD_RETURN_NORMAL);
cdata = xcalloc(1, sizeof *cdata);
- cdata->c = c;
cdata->inputs = NULL;
cdata->next_input = NULL;
@@ -142,10 +141,10 @@ cmd_command_prompt_error(struct cmdq_item *item, void *data)
}
static int
-cmd_command_prompt_callback(void *data, const char *s, int done)
+cmd_command_prompt_callback(struct client *c, void *data, const char *s,
+ int done)
{
struct cmd_command_prompt_cdata *cdata = data;
- struct client *c = cdata->c;
struct cmd_list *cmdlist;
struct cmdq_item *new_item;
char *cause, *new_template, *prompt, *ptr;
@@ -193,7 +192,7 @@ cmd_command_prompt_callback(void *data, const char *s, int done)
if (!done)
free(new_template);
- if (c->prompt_callbackfn != cmd_command_prompt_callback)
+ if (c->prompt_inputcb != cmd_command_prompt_callback)
return (1);
return (0);
}
diff --git a/cmd-confirm-before.c b/cmd-confirm-before.c
index 3042d066..7036d34b 100644
--- a/cmd-confirm-before.c
+++ b/cmd-confirm-before.c
@@ -31,7 +31,8 @@
static enum cmd_retval cmd_confirm_before_exec(struct cmd *,
struct cmdq_item *);
-static int cmd_confirm_before_callback(void *, const char *, int);
+static int cmd_confirm_before_callback(struct client *, void *,
+ const char *, int);
static void cmd_confirm_before_free(void *);
const struct cmd_entry cmd_confirm_before_entry = {
@@ -46,8 +47,7 @@ const struct cmd_entry cmd_confirm_before_entry = {
};
struct cmd_confirm_before_data {
- char *cmd;
- struct client *client;
+ char *cmd;
};
static enum cmd_retval
@@ -74,9 +74,6 @@ cmd_confirm_before_exec(struct cmd *self, struct cmdq_item *item)
cdata = xmalloc(sizeof *cdata);
cdata->cmd = xstrdup(args->argv[0]);
- cdata->client = c;
- cdata->client->references++;
-
status_prompt_set(c, new_prompt, NULL,
cmd_confirm_before_callback, cmd_confirm_before_free, cdata,
PROMPT_SINGLE);
@@ -97,10 +94,10 @@ cmd_confirm_before_error(struct cmdq_item *item, void *data)
}
static int
-cmd_confirm_before_callback(void *data, const char *s, __unused int done)
+cmd_confirm_before_callback(struct client *c, void *data, const char *s,
+ __unused int done)
{
struct cmd_confirm_before_data *cdata = data;
- struct client *c = cdata->client;
struct cmd_list *cmdlist;
struct cmdq_item *new_item;
char *cause;
@@ -135,9 +132,6 @@ static void
cmd_confirm_before_free(void *data)
{
struct cmd_confirm_before_data *cdata = data;
- struct client *c = cdata->client;
-
- server_client_unref(c);
free(cdata->cmd);
free(cdata);
diff --git a/cmd-new-session.c b/cmd-new-session.c
index 1813288d..efddc228 100644
--- a/cmd-new-session.c
+++ b/cmd-new-session.c
@@ -77,6 +77,7 @@ cmd_new_session_exec(struct cmd *self, struct cmdq_item *item)
const char *path, *cmd, *cwd, *to_free = NULL;
char **argv, *cause, *cp;
int detached, already_attached, idx, argc;
+ int is_control = 0;
u_int sx, sy;
struct environ_entry *envent;
struct cmd_find_state fs;
@@ -139,6 +140,8 @@ cmd_new_session_exec(struct cmd *self, struct cmdq_item *item)
detached = args_has(args, 'd');
if (c == NULL)
detached = 1;
+ else if (c->flags & CLIENT_CONTROL)
+ is_control = 1;
/* Is this client already attached? */
already_attached = 0;
@@ -185,29 +188,31 @@ cmd_new_session_exec(struct cmd *self, struct cmdq_item *item)
}
/* Find new session size. */
- if (c != NULL) {
+ if (!detached) {
sx = c->tty.sx;
sy = c->tty.sy;
+ if (!is_control &&
+ sy > 0 &&
+ options_get_number(global_s_options, "status"))
+ sy--;
} else {
sx = 80;
sy = 24;
}
- if (detached && args_has(args, 'x')) {
+ if ((is_control || detached) && args_has(args, 'x')) {
sx = strtonum(args_get(args, 'x'), 1, USHRT_MAX, &errstr);
if (errstr != NULL) {
cmdq_error(item, "width %s", errstr);
goto error;
}
}
- if (detached && args_has(args, 'y')) {
+ if ((is_control || detached) && args_has(args, 'y')) {
sy = strtonum(args_get(args, 'y'), 1, USHRT_MAX, &errstr);
if (errstr != NULL) {
cmdq_error(item, "height %s", errstr);
goto error;
}
}
- if (sy > 0 && options_get_number(global_s_options, "status"))
- sy--;
if (sx == 0)
sx = 1;
if (sy == 0)
diff --git a/cmd-refresh-client.c b/cmd-refresh-client.c
index 5190df89..df1d2135 100644
--- a/cmd-refresh-client.c
+++ b/cmd-refresh-client.c
@@ -67,8 +67,9 @@ cmd_refresh_client_exec(struct cmd *self, struct cmdq_item *item)
cmdq_error(item, "not a control client");
return (CMD_RETURN_ERROR);
}
- if (tty_set_size(&c->tty, w, h))
- recalculate_sizes();
+ tty_set_size(&c->tty, w, h);
+ c->flags |= CLIENT_SIZECHANGED;
+ recalculate_sizes();
} else if (args_has(args, 'S')) {
c->flags |= CLIENT_STATUSFORCE;
server_status_client(c);
diff --git a/cmd-resize-pane.c b/cmd-resize-pane.c
index 2ad11c23..bbb78de7 100644
--- a/cmd-resize-pane.c
+++ b/cmd-resize-pane.c
@@ -129,9 +129,8 @@ static void
cmd_resize_pane_mouse_update(struct client *c, struct mouse_event *m)
{
struct winlink *wl;
- struct window_pane *wp;
- int found;
- u_int y, ly;
+ struct window_pane *loop, *wp_x, *wp_y;
+ u_int y, ly, x, lx, sx, sy, ex, ey;
wl = cmd_mouse_window(m, NULL);
if (wl == NULL) {
@@ -139,37 +138,48 @@ cmd_resize_pane_mouse_update(struct client *c, struct mouse_event *m)
return;
}
- y = m->y;
+ y = m->y; x = m->x;
if (m->statusat == 0 && y > 0)
y--;
else if (m->statusat > 0 && y >= (u_int)m->statusat)
y = m->statusat - 1;
- ly = m->ly;
+ ly = m->ly; lx = m->lx;
if (m->statusat == 0 && ly > 0)
ly--;
else if (m->statusat > 0 && ly >= (u_int)m->statusat)
ly = m->statusat - 1;
- found = 0;
- TAILQ_FOREACH(wp, &wl->window->panes, entry) {
- if (!window_pane_visible(wp))
+ wp_x = wp_y = NULL;
+ TAILQ_FOREACH(loop, &wl->window->panes, entry) {
+ if (!window_pane_visible(loop))
continue;
- if (wp->xoff + wp->sx == m->lx &&
- wp->yoff <= 1 + ly &&
- wp->yoff + wp->sy >= ly) {
- layout_resize_pane(wp, LAYOUT_LEFTRIGHT, m->x - m->lx, 0);
- found = 1;
- }
- if (wp->yoff + wp->sy == ly &&
- wp->xoff <= 1 + m->lx &&
- wp->xoff + wp->sx >= m->lx) {
- layout_resize_pane(wp, LAYOUT_TOPBOTTOM, y - ly, 0);
- found = 1;
- }
+ sx = loop->xoff;
+ if (sx != 0)
+ sx--;
+ ex = loop->xoff + loop->sx;
+
+ sy = loop->yoff;
+ if (sy != 0)
+ sy--;
+ ey = loop->yoff + loop->sy;
+
+ if ((lx == sx || lx == ex) &&
+ (ly >= sy && ly <= ey) &&
+ (wp_x == NULL || loop->sy > wp_x->sy))
+ wp_x = loop;
+ if ((ly == sy || ly == ey) &&
+ (lx >= sx && lx <= ex) &&
+ (wp_y == NULL || loop->sx > wp_y->sx))
+ wp_y = loop;
}
- if (found)
- server_redraw_window(wl->window);
- else
+ if (wp_x == NULL && wp_y == NULL) {
c->tty.mouse_drag_update = NULL;
+ return;
+ }
+ if (wp_x != NULL)
+ layout_resize_pane(wp_x, LAYOUT_LEFTRIGHT, x - lx, 0);
+ if (wp_y != NULL)
+ layout_resize_pane(wp_y, LAYOUT_TOPBOTTOM, y - ly, 0);
+ server_redraw_window(wl->window);
}
diff --git a/cmd-send-keys.c b/cmd-send-keys.c
index e54574fe..5c6db347 100644
--- a/cmd-send-keys.c
+++ b/cmd-send-keys.c
@@ -73,7 +73,7 @@ cmd_send_keys_inject(struct client *c, struct cmdq_item *item, key_code key)
bd = RB_FIND(key_bindings, &table->key_bindings, &bd_find);
if (bd != NULL) {
table->references++;
- key_bindings_dispatch(bd, c, NULL, &item->target);
+ key_bindings_dispatch(bd, item, c, NULL, &item->target);
key_bindings_unref_table(table);
}
}
diff --git a/cmd-set-option.c b/cmd-set-option.c
index b35d60d8..ad058b8e 100644
--- a/cmd-set-option.c
+++ b/cmd-set-option.c
@@ -42,8 +42,8 @@ const struct cmd_entry cmd_set_option_entry = {
.name = "set-option",
.alias = "set",
- .args = { "agoqst:uw", 1, 2 },
- .usage = "[-agosquw] [-t target-window] option [value]",
+ .args = { "aFgoqst:uw", 1, 2 },
+ .usage = "[-aFgosquw] [-t target-window] option [value]",
.target = { 't', CMD_FIND_WINDOW, CMD_FIND_CANFAIL },
@@ -55,8 +55,8 @@ const struct cmd_entry cmd_set_window_option_entry = {
.name = "set-window-option",
.alias = "setw",
- .args = { "agoqt:u", 1, 2 },
- .usage = "[-agoqu] " CMD_TARGET_WINDOW_USAGE " option [value]",
+ .args = { "aFgoqt:u", 1, 2 },
+ .usage = "[-aFgoqu] " CMD_TARGET_WINDOW_USAGE " option [value]",
.target = { 't', CMD_FIND_WINDOW, CMD_FIND_CANFAIL },
@@ -70,33 +70,38 @@ cmd_set_option_exec(struct cmd *self, struct cmdq_item *item)
struct args *args = self->args;
int append = args_has(args, 'a');
struct cmd_find_state *fs = &item->target;
+ struct client *c, *loop;
struct session *s = fs->s;
struct winlink *wl = fs->wl;
struct window *w;
- struct client *c;
enum options_table_scope scope;
struct options *oo;
struct options_entry *parent, *o;
- char *name;
- const char *value, *target;
+ char *name, *argument, *value = NULL, *cause;
+ const char *target;
int window, idx, already, error, ambiguous;
- char *cause;
+
+ /* Expand argument. */
+ c = cmd_find_client(item, NULL, 1);
+ argument = format_single(item, args->argv[0], c, s, wl, NULL);
/* Parse option name and index. */
- name = options_match(args->argv[0], &idx, &ambiguous);
+ name = options_match(argument, &idx, &ambiguous);
if (name == NULL) {
if (args_has(args, 'q'))
- return (CMD_RETURN_NORMAL);
+ goto out;
if (ambiguous)
- cmdq_error(item, "ambiguous option: %s", args->argv[0]);
+ cmdq_error(item, "ambiguous option: %s", argument);
else
- cmdq_error(item, "invalid option: %s", args->argv[0]);
- return (CMD_RETURN_ERROR);
+ cmdq_error(item, "invalid option: %s", argument);
+ goto fail;
}
if (args->argc < 2)
value = NULL;
+ else if (args_has(args, 'F'))
+ value = format_single(item, args->argv[1], c, s, wl, NULL);
else
- value = args->argv[1];
+ value = xstrdup(args->argv[1]);
/*
* Figure out the scope: for user options it comes from the arguments,
@@ -114,12 +119,12 @@ cmd_set_option_exec(struct cmd *self, struct cmdq_item *item)
scope = OPTIONS_TABLE_WINDOW;
else {
scope = OPTIONS_TABLE_NONE;
- xasprintf(&cause, "unknown option: %s", args->argv[0]);
+ xasprintf(&cause, "unknown option: %s", argument);
}
}
if (scope == OPTIONS_TABLE_NONE) {
if (args_has(args, 'q'))
- return (CMD_RETURN_NORMAL);
+ goto out;
cmdq_error(item, "%s", cause);
free(cause);
goto fail;
@@ -159,7 +164,7 @@ cmd_set_option_exec(struct cmd *self, struct cmdq_item *item)
/* Check that array options and indexes match up. */
if (idx != -1) {
if (*name == '@' || options_array_size(parent, NULL) == -1) {
- cmdq_error(item, "not an array: %s", args->argv[0]);
+ cmdq_error(item, "not an array: %s", argument);
goto fail;
}
}
@@ -176,8 +181,8 @@ cmd_set_option_exec(struct cmd *self, struct cmdq_item *item)
}
if (already) {
if (args_has(args, 'q'))
- return (CMD_RETURN_NORMAL);
- cmdq_error(item, "already set: %s", args->argv[0]);
+ goto out;
+ cmdq_error(item, "already set: %s", argument);
goto fail;
}
}
@@ -217,7 +222,7 @@ cmd_set_option_exec(struct cmd *self, struct cmdq_item *item)
options_array_clear(o);
options_array_assign(o, value);
} else if (options_array_set(o, idx, value, append) != 0) {
- cmdq_error(item, "invalid index: %s", args->argv[0]);
+ cmdq_error(item, "invalid index: %s", argument);
goto fail;
}
}
@@ -232,8 +237,8 @@ cmd_set_option_exec(struct cmd *self, struct cmdq_item *item)
}
}
if (strcmp(name, "key-table") == 0) {
- TAILQ_FOREACH(c, &clients, entry)
- server_client_set_key_table(c, NULL);
+ TAILQ_FOREACH(loop, &clients, entry)
+ server_client_set_key_table(loop, NULL);
}
if (strcmp(name, "status") == 0 ||
strcmp(name, "status-interval") == 0)
@@ -257,15 +262,20 @@ cmd_set_option_exec(struct cmd *self, struct cmdq_item *item)
* anyway.
*/
recalculate_sizes();
- TAILQ_FOREACH(c, &clients, entry) {
- if (c->session != NULL)
- server_redraw_client(c);
+ TAILQ_FOREACH(loop, &clients, entry) {
+ if (loop->session != NULL)
+ server_redraw_client(loop);
}
+out:
+ free(argument);
+ free(value);
free(name);
return (CMD_RETURN_NORMAL);
fail:
+ free(argument);
+ free(value);
free(name);
return (CMD_RETURN_ERROR);
}
diff --git a/cmd-show-options.c b/cmd-show-options.c
index 382dd7fb..2dc3dee3 100644
--- a/cmd-show-options.c
+++ b/cmd-show-options.c
@@ -127,25 +127,36 @@ cmd_show_options_one(struct cmd *self, struct cmdq_item *item,
struct options *oo)
{
struct args *args = self->args;
+ struct client *c = cmd_find_client(item, NULL, 1);
+ struct session *s = item->target.s;
+ struct winlink *wl = item->target.wl;
struct options_entry *o;
int idx, ambiguous;
- const char *name = args->argv[0];
+ char *name;
+ name = format_single(item, args->argv[0], c, s, wl, NULL);
o = options_match_get(oo, name, &idx, 1, &ambiguous);
if (o == NULL) {
- if (args_has(args, 'q'))
+ if (args_has(args, 'q')) {
+ free(name);
return (CMD_RETURN_NORMAL);
+ }
if (ambiguous) {
cmdq_error(item, "ambiguous option: %s", name);
+ free(name);
return (CMD_RETURN_ERROR);
}
if (*name != '@' &&
- options_match_get(oo, name, &idx, 0, &ambiguous) != NULL)
+ options_match_get(oo, name, &idx, 0, &ambiguous) != NULL) {
+ free(name);
return (CMD_RETURN_NORMAL);
+ }
cmdq_error(item, "unknown option: %s", name);
+ free(name);
return (CMD_RETURN_ERROR);
}
cmd_show_options_print(self, item, o, idx);
+ free(name);
return (CMD_RETURN_NORMAL);
}
diff --git a/configure.ac b/configure.ac
index 3591a730..dcf62ab9 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,6 +1,6 @@
# configure.ac
-AC_INIT(tmux, 2.5)
+AC_INIT(tmux, master)
AC_PREREQ([2.60])
AC_CONFIG_AUX_DIR(etc)
@@ -104,7 +104,6 @@ AC_REPLACE_FUNCS([ \
closefrom \
explicit_bzero \
fgetln \
- fparseln \
freezero \
getdtablecount \
getprogname \
@@ -454,6 +453,14 @@ else
AC_LIBOBJ(getopt)
fi
+# Look for fparseln in libutil.
+AC_SEARCH_LIBS(fparseln, util, found_fparseln=yes, found_fparseln=no)
+if test "x$found_fparseln" = xyes; then
+ AC_DEFINE(HAVE_FPARSELN)
+else
+ AC_LIBOBJ(fparseln)
+fi
+
# Look for fdforkpty and forkpty in libutil.
AC_SEARCH_LIBS(fdforkpty, util, found_fdforkpty=yes, found_fdforkpty=no)
if test "x$found_fdforkpty" = xyes; then
diff --git a/environ.c b/environ.c
index d884330e..29191ee5 100644
--- a/environ.c
+++ b/environ.c
@@ -208,9 +208,15 @@ environ_push(struct environ *env)
/* Log the environment. */
void
-environ_log(struct environ *env, const char *prefix)
+environ_log(struct environ *env, const char *fmt, ...)
{
struct environ_entry *envent;
+ va_list ap;
+ char *prefix;
+
+ va_start(ap, fmt);
+ vasprintf(&prefix, fmt, ap);
+ va_end(ap);
RB_FOREACH(envent, environ, env) {
if (envent->value != NULL && *envent->name != '\0') {
@@ -218,6 +224,8 @@ environ_log(struct environ *env, const char *prefix)
envent->value);
}
}
+
+ free(prefix);
}
/* Create initial environment for new child. */
diff --git a/format.c b/format.c
index 35d8ee28..d017aa0a 100644
--- a/format.c
+++ b/format.c
@@ -43,28 +43,6 @@ typedef void (*format_cb)(struct format_tree *, struct format_entry *);
static char *format_job_get(struct format_tree *, const char *);
static void format_job_timer(int, short, void *);
-static void format_cb_host(struct format_tree *, struct format_entry *);
-static void format_cb_host_short(struct format_tree *,
- struct format_entry *);
-static void format_cb_pid(struct format_tree *, struct format_entry *);
-static void format_cb_session_alerts(struct format_tree *,
- struct format_entry *);
-static void format_cb_window_layout(struct format_tree *,
- struct format_entry *);
-static void format_cb_window_visible_layout(struct format_tree *,
- struct format_entry *);
-static void format_cb_start_command(struct format_tree *,
- struct format_entry *);
-static void format_cb_current_command(struct format_tree *,
- struct format_entry *);
-static void format_cb_history_bytes(struct format_tree *,
- struct format_entry *);
-static void format_cb_pane_tabs(struct format_tree *,
- struct format_entry *);
-
-static void format_cb_current_path(struct format_tree *,
- struct format_entry *);
-
static char *format_find(struct format_tree *, const char *, int);
static void format_add_cb(struct format_tree *, const char *, format_cb);
static void format_add_tv(struct format_tree *, const char *,
@@ -217,7 +195,6 @@ format_job_update(struct job *job)
struct format_job *fj = job->data;
char *line;
time_t t;
- struct client *c;
if ((line = evbuffer_readline(job->event->input)) == NULL)
return;
@@ -226,12 +203,12 @@ format_job_update(struct job *job)
free(fj->out);
fj->out = line;
- log_debug("%s: %s: %s", __func__, fj->cmd, fj->out);
+ log_debug("%s: %p %s: %s", __func__, fj, fj->cmd, fj->out);
t = time (NULL);
if (fj->status && fj->last != t) {
- TAILQ_FOREACH(c, &clients, entry)
- server_status_client(c);
+ if (fj->client != NULL)
+ server_status_client(fj->client);
fj->last = t;
}
}
@@ -256,10 +233,11 @@ format_job_complete(struct job *job)
} else
buf = line;
+ log_debug("%s: %p %s: %s", __func__, fj, fj->cmd, buf);
+
if (*buf != '\0' || !fj->updated) {
free(fj->out);
fj->out = buf;
- log_debug("%s: %s: %s", __func__, fj->cmd, fj->out);
} else
free(buf);
@@ -1416,8 +1394,8 @@ format_defaults_pane(struct format_tree *ft, struct window_pane *wp)
format_add(ft, "pane_synchronized", "%d",
!!options_get_number(wp->window->options, "synchronize-panes"));
- format_add(ft, "pane_search_string", "%s",
- window_copy_search_string(wp));
+ if (wp->searchstr != NULL)
+ format_add(ft, "pane_search_string", "%s", wp->searchstr);
format_add(ft, "pane_tty", "%s", wp->tty);
format_add(ft, "pane_pid", "%ld", (long) wp->pid);
diff --git a/grid-view.c b/grid-view.c
index fe096252..033ec033 100644
--- a/grid-view.c
+++ b/grid-view.c
@@ -96,32 +96,34 @@ grid_view_clear(struct grid *gd, u_int px, u_int py, u_int nx, u_int ny,
/* Scroll region up. */
void
-grid_view_scroll_region_up(struct grid *gd, u_int rupper, u_int rlower)
+grid_view_scroll_region_up(struct grid *gd, u_int rupper, u_int rlower,
+ u_int bg)
{
if (gd->flags & GRID_HISTORY) {
- grid_collect_history(gd, 8);
+ grid_collect_history(gd, bg);
if (rupper == 0 && rlower == gd->sy - 1)
- grid_scroll_history(gd, 8);
+ grid_scroll_history(gd, bg);
else {
rupper = grid_view_y(gd, rupper);
rlower = grid_view_y(gd, rlower);
- grid_scroll_history_region(gd, rupper, rlower);
+ grid_scroll_history_region(gd, rupper, rlower, bg);
}
} else {
rupper = grid_view_y(gd, rupper);
rlower = grid_view_y(gd, rlower);
- grid_move_lines(gd, rupper, rupper + 1, rlower - rupper, 8);
+ grid_move_lines(gd, rupper, rupper + 1, rlower - rupper, bg);
}
}
/* Scroll region down. */
void
-grid_view_scroll_region_down(struct grid *gd, u_int rupper, u_int rlower)
+grid_view_scroll_region_down(struct grid *gd, u_int rupper, u_int rlower,
+ u_int bg)
{
rupper = grid_view_y(gd, rupper);
rlower = grid_view_y(gd, rlower);
- grid_move_lines(gd, rupper + 1, rupper, rlower - rupper, 8);
+ grid_move_lines(gd, rupper + 1, rupper, rlower - rupper, bg);
}
/* Insert lines. */
diff --git a/grid.c b/grid.c
index 3fa96d42..83ad89ed 100644
--- a/grid.c
+++ b/grid.c
@@ -284,9 +284,9 @@ grid_clear_history(struct grid *gd)
/* Scroll a region up, moving the top line into the history. */
void
-grid_scroll_history_region(struct grid *gd, u_int upper, u_int lower)
+grid_scroll_history_region(struct grid *gd, u_int upper, u_int lower, u_int bg)
{
- struct grid_line *gl_history, *gl_upper, *gl_lower;
+ struct grid_line *gl_history, *gl_upper;
u_int yy;
/* Create a space for a new line. */
@@ -302,14 +302,13 @@ grid_scroll_history_region(struct grid *gd, u_int upper, u_int lower)
upper++;
gl_upper = &gd->linedata[upper];
lower++;
- gl_lower = &gd->linedata[lower];
/* Move the line into the history. */
memcpy(gl_history, gl_upper, sizeof *gl_history);
/* Then move the region up and clear the bottom line. */
memmove(gl_upper, gl_upper + 1, (lower - upper) * sizeof *gl_upper);
- memset(gl_lower, 0, sizeof *gl_lower);
+ grid_empty_line(gd, lower, bg);
/* Move the history offset down over the line. */
gd->hscrolled++;
@@ -666,8 +665,7 @@ grid_string_cells_bg(const struct grid_cell *gc, int *values)
/*
* Returns ANSI code to set particular attributes (colour, bold and so on)
- * given a current state. The output buffer must be able to hold at least 57
- * bytes.
+ * given a current state.
*/
static void
grid_string_cells_code(const struct grid_cell *lastgc,
diff --git a/input.c b/input.c
index 22dd1ee2..ba97baec 100644
--- a/input.c
+++ b/input.c
@@ -110,6 +110,8 @@ static void input_set_state(struct window_pane *,
static void input_reset_cell(struct input_ctx *);
static void input_osc_4(struct window_pane *, const char *);
+static void input_osc_10(struct window_pane *, const char *);
+static void input_osc_11(struct window_pane *, const char *);
static void input_osc_52(struct window_pane *, const char *);
static void input_osc_104(struct window_pane *, const char *);
@@ -1123,7 +1125,7 @@ input_c0_dispatch(struct input_ctx *ictx)
case '\012': /* LF */
case '\013': /* VT */
case '\014': /* FF */
- screen_write_linefeed(sctx, 0);
+ screen_write_linefeed(sctx, 0, ictx->cell.cell.bg);
break;
case '\015': /* CR */
screen_write_carriagereturn(sctx);
@@ -1168,18 +1170,18 @@ input_esc_dispatch(struct input_ctx *ictx)
screen_write_reset(sctx);
break;
case INPUT_ESC_IND:
- screen_write_linefeed(sctx, 0);
+ screen_write_linefeed(sctx, 0, ictx->cell.cell.bg);
break;
case INPUT_ESC_NEL:
screen_write_carriagereturn(sctx);
- screen_write_linefeed(sctx, 0);
+ screen_write_linefeed(sctx, 0, ictx->cell.cell.bg);
break;
case INPUT_ESC_HTS:
if (s->cx < screen_size_x(s))
bit_set(s->tabs, s->cx);
break;
case INPUT_ESC_RI:
- screen_write_reverseindex(sctx);
+ screen_write_reverseindex(sctx, ictx->cell.cell.bg);
break;
case INPUT_ESC_DECKPAM:
screen_write_mode_set(sctx, MODE_KKEYPAD);
@@ -1417,7 +1419,8 @@ input_csi_dispatch(struct input_ctx *ictx)
input_csi_dispatch_sm_private(ictx);
break;
case INPUT_CSI_SU:
- screen_write_scrollup(sctx, input_get(ictx, 0, 1, 1));
+ screen_write_scrollup(sctx, input_get(ictx, 0, 1, 1),
+ ictx->cell.cell.bg);
break;
case INPUT_CSI_TBC:
switch (input_get(ictx, 0, 0, 0)) {
@@ -1899,13 +1902,19 @@ input_exit_osc(struct input_ctx *ictx)
case 4:
input_osc_4(ictx->wp, p);
break;
- case 52:
- input_osc_52(ictx->wp, p);
+ case 10:
+ input_osc_10(ictx->wp, p);
+ break;
+ case 11:
+ input_osc_11(ictx->wp, p);
break;
case 12:
if (*p != '?') /* ? is colour request */
screen_set_cursor_colour(ictx->ctx.s, p);
break;
+ case 52:
+ input_osc_52(ictx->wp, p);
+ break;
case 104:
input_osc_104(ictx->wp, p);
break;
@@ -2051,6 +2060,42 @@ bad:
free(copy);
}
+/* Handle the OSC 10 sequence for setting background colour. */
+static void
+input_osc_10(struct window_pane *wp, const char *p)
+{
+ u_int r, g, b;
+
+ if (sscanf(p, "rgb:%2x/%2x/%2x", &r, &g, &b) != 3)
+ goto bad;
+
+ wp->colgc.fg = colour_join_rgb(r, g, b);
+ wp->flags |= PANE_REDRAW;
+
+ return;
+
+bad:
+ log_debug("bad OSC 10: %s", p);
+}
+
+/* Handle the OSC 11 sequence for setting background colour. */
+static void
+input_osc_11(struct window_pane *wp, const char *p)
+{
+ u_int r, g, b;
+
+ if (sscanf(p, "rgb:%2x/%2x/%2x", &r, &g, &b) != 3)
+ goto bad;
+
+ wp->colgc.bg = colour_join_rgb(r, g, b);
+ wp->flags |= PANE_REDRAW;
+
+ return;
+
+bad:
+ log_debug("bad OSC 11: %s", p);
+}
+
/* Handle the OSC 52 sequence for setting the clipboard. */
static void
input_osc_52(struct window_pane *wp, const char *p)
diff --git a/key-bindings.c b/key-bindings.c
index 9e327655..8f56cbee 100644
--- a/key-bindings.c
+++ b/key-bindings.c
@@ -400,11 +400,11 @@ key_bindings_read_only(struct cmdq_item *item, __unused void *data)
}
void
-key_bindings_dispatch(struct key_binding *bd, struct client *c,
- struct mouse_event *m, struct cmd_find_state *fs)
+key_bindings_dispatch(struct key_binding *bd, struct cmdq_item *item,
+ struct client *c, struct mouse_event *m, struct cmd_find_state *fs)
{
struct cmd *cmd;
- struct cmdq_item *item;
+ struct cmdq_item *new_item;
int readonly;
readonly = 1;
@@ -413,11 +413,14 @@ key_bindings_dispatch(struct key_binding *bd, struct client *c,
readonly = 0;
}
if (!readonly && (c->flags & CLIENT_READONLY))
- cmdq_append(c, cmdq_get_callback(key_bindings_read_only, NULL));
+ new_item = cmdq_get_callback(key_bindings_read_only, NULL);
else {
- item = cmdq_get_command(bd->cmdlist, fs, m, 0);
+ new_item = cmdq_get_command(bd->cmdlist, fs, m, 0);
if (bd->flags & KEY_BINDING_REPEAT)
- item->shared->flags |= CMDQ_SHARED_REPEAT;
- cmdq_append(c, item);
+ new_item->shared->flags |= CMDQ_SHARED_REPEAT;
}
+ if (item != NULL)
+ cmdq_insert_after(item, new_item);
+ else
+ cmdq_append(c, new_item);
}
diff --git a/layout-set.c b/layout-set.c
index db621f61..7ba18fea 100644
--- a/layout-set.c
+++ b/layout-set.c
@@ -165,6 +165,7 @@ layout_set_even_h(struct window *w)
layout_print_cell(w->layout_root, __func__, 1);
+ notify_window("window-layout-changed", w);
server_redraw_window(w);
}
@@ -219,6 +220,7 @@ layout_set_even_v(struct window *w)
layout_print_cell(w->layout_root, __func__, 1);
+ notify_window("window-layout-changed", w);
server_redraw_window(w);
}
@@ -342,6 +344,7 @@ layout_set_main_h(struct window *w)
layout_print_cell(w->layout_root, __func__, 1);
+ notify_window("window-layout-changed", w);
server_redraw_window(w);
}
@@ -465,6 +468,7 @@ layout_set_main_v(struct window *w)
layout_print_cell(w->layout_root, __func__, 1);
+ notify_window("window-layout-changed", w);
server_redraw_window(w);
}
@@ -567,5 +571,6 @@ layout_set_tiled(struct window *w)
layout_print_cell(w->layout_root, __func__, 1);
+ notify_window("window-layout-changed", w);
server_redraw_window(w);
}
diff --git a/regress/control-client-size.sh b/regress/control-client-size.sh
new file mode 100644
index 00000000..cef48a0e
--- /dev/null
+++ b/regress/control-client-size.sh
@@ -0,0 +1,49 @@
+#!/bin/sh
+
+# 947
+# size in control mode should change after refresh-client -C, and -x and -y
+# should work without -d for control clients
+
+PATH=/bin:/usr/bin
+TERM=screen
+
+[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
+TMUX="$TEST_TMUX -Ltest"
+$TMUX kill-server 2>/dev/null
+
+TMP=$(mktemp)
+OUT=$(mktemp)
+trap "rm -f $TMP $OUT" 0 1 15
+
+$TMUX -f/dev/null new -d || exit 1
+sleep 1
+cat <<EOF|$TMUX -C a >$TMP
+ls -F':#{session_width} #{session_height}'
+refresh -C 100,50
+ls -F':#{session_width} #{session_height}'
+EOF
+grep ^: $TMP >$OUT
+printf ":80 24\n:100 50\n"|cmp -s $OUT || exit 1
+$TMUX kill-server 2>/dev/null
+
+$TMUX -f/dev/null new -d || exit 1
+sleep 1
+cat <<EOF|$TMUX -C a >$TMP
+ls -F':#{session_width} #{session_height}'
+refresh -C 80,24
+ls -F':#{session_width} #{session_height}'
+EOF
+grep ^: $TMP >$OUT
+printf ":80 24\n:80 24\n"|cmp -s $OUT || exit 1
+$TMUX kill-server 2>/dev/null
+
+cat <<EOF|$TMUX -C new -x 100 -y 50 >$TMP
+ls -F':#{session_width} #{session_height}'
+refresh -C 80,24
+ls -F':#{session_width} #{session_height}'
+EOF
+grep ^: $TMP >$OUT
+printf ":100 50\n:80 24\n"|cmp -s $OUT || exit 1
+$TMUX kill-server 2>/dev/null
+
+exit 0
diff --git a/regress/new-session-size.sh b/regress/new-session-size.sh
new file mode 100644
index 00000000..f9394f35
--- /dev/null
+++ b/regress/new-session-size.sh
@@ -0,0 +1,27 @@
+#!/bin/sh
+
+# new-session without clients should be the right size
+
+PATH=/bin:/usr/bin
+TERM=screen
+
+[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
+TMUX="$TEST_TMUX -Ltest"
+$TMUX kill-server 2>/dev/null
+
+TMP=$(mktemp)
+trap "rm -f $TMP" 0 1 15
+
+$TMUX -f/dev/null new -d </dev/null || exit 1
+sleep 1
+$TMUX ls -F "#{session_width} #{session_height}" >$TMP
+printf "80 24\n"|cmp -s $TMP || exit 1
+$TMUX kill-server 2>/dev/null
+
+$TMUX -f/dev/null new -d -x 100 -y 50 </dev/null || exit 1
+sleep 1
+$TMUX ls -F "#{session_width} #{session_height}" >$TMP
+printf "100 50\n"|cmp -s $TMP || exit 1
+$TMUX kill-server 2>/dev/null
+
+exit 0
diff --git a/resize.c b/resize.c
index ff1c9eec..4c41f769 100644
--- a/resize.c
+++ b/resize.c
@@ -60,6 +60,9 @@ recalculate_sizes(void)
TAILQ_FOREACH(c, &clients, entry) {
if (c->flags & CLIENT_SUSPENDED)
continue;
+ if ((c->flags & (CLIENT_CONTROL|CLIENT_SIZECHANGED)) ==
+ CLIENT_CONTROL)
+ continue;
if (c->session == s) {
if (c->tty.sx < ssx)
ssx = c->tty.sx;
diff --git a/screen-write.c b/screen-write.c
index 0a63e1b6..1af623b1 100644
--- a/screen-write.c
+++ b/screen-write.c
@@ -75,6 +75,9 @@ screen_write_start(struct screen_write_ctx *ctx, struct window_pane *wp,
TAILQ_INIT(&ctx->list[y].items);
ctx->item = xcalloc(1, sizeof *ctx->item);
+ ctx->scrolled = 0;
+ ctx->bg = 8;
+
if (wp != NULL)
snprintf(tmp, sizeof tmp, "pane %%%u", wp->id);
log_debug("%s: size %ux%u, %s", __func__, screen_size_x(ctx->s),
@@ -812,15 +815,16 @@ screen_write_cursormove(struct screen_write_ctx *ctx, u_int px, u_int py)
/* Reverse index (up with scroll). */
void
-screen_write_reverseindex(struct screen_write_ctx *ctx)
+screen_write_reverseindex(struct screen_write_ctx *ctx, u_int bg)
{
struct screen *s = ctx->s;
struct tty_ctx ttyctx;
screen_write_initctx(ctx, &ttyctx);
+ ttyctx.bg = bg;
if (s->cy == s->rupper)
- grid_view_scroll_region_down(s->grid, s->rupper, s->rlower);
+ grid_view_scroll_region_down(s->grid, s->rupper, s->rlower, bg);
else if (s->cy > 0)
s->cy--;
@@ -854,7 +858,7 @@ screen_write_scrollregion(struct screen_write_ctx *ctx, u_int rupper,
/* Line feed. */
void
-screen_write_linefeed(struct screen_write_ctx *ctx, int wrapped)
+screen_write_linefeed(struct screen_write_ctx *ctx, int wrapped, u_int bg)
{
struct screen *s = ctx->s;
struct grid *gd = s->grid;
@@ -869,8 +873,13 @@ screen_write_linefeed(struct screen_write_ctx *ctx, int wrapped)
log_debug("%s: at %u,%u (region %u-%u)", __func__, s->cx, s->cy,
s->rupper, s->rlower);
+ if (bg != ctx->bg) {
+ screen_write_collect_flush(ctx, 1);
+ ctx->bg = bg;
+ }
+
if (s->cy == s->rlower) {
- grid_view_scroll_region_up(gd, s->rupper, s->rlower);
+ grid_view_scroll_region_up(gd, s->rupper, s->rlower, bg);
screen_write_collect_scroll(ctx);
ctx->scrolled++;
} else if (s->cy < screen_size_y(s) - 1)
@@ -879,7 +888,7 @@ screen_write_linefeed(struct screen_write_ctx *ctx, int wrapped)
/* Scroll up. */
void
-screen_write_scrollup(struct screen_write_ctx *ctx, u_int lines)
+screen_write_scrollup(struct screen_write_ctx *ctx, u_int lines, u_int bg)
{
struct screen *s = ctx->s;
struct grid *gd = s->grid;
@@ -890,8 +899,13 @@ screen_write_scrollup(struct screen_write_ctx *ctx, u_int lines)
else if (lines > s->rlower - s->rupper + 1)
lines = s->rlower - s->rupper + 1;
+ if (bg != ctx->bg) {
+ screen_write_collect_flush(ctx, 1);
+ ctx->bg = bg;
+ }
+
for (i = 0; i < lines; i++) {
- grid_view_scroll_region_up(gd, s->rupper, s->rlower);
+ grid_view_scroll_region_up(gd, s->rupper, s->rlower, bg);
screen_write_collect_scroll(ctx);
}
ctx->scrolled += lines;
@@ -1046,9 +1060,12 @@ screen_write_collect_flush(struct screen_write_ctx *ctx, int scroll_only)
screen_write_initctx(ctx, &ttyctx);
ttyctx.num = ctx->scrolled;
+ ttyctx.bg = ctx->bg;
tty_write(tty_cmd_scrollup, &ttyctx);
}
ctx->scrolled = 0;
+ ctx->bg = 8;
+
if (scroll_only)
return;
@@ -1143,7 +1160,7 @@ screen_write_collect_add(struct screen_write_ctx *ctx,
if (s->cx > sx - 1) {
log_debug("%s: wrapped at %u,%u", __func__, s->cx, s->cy);
ci->wrapped = 1;
- screen_write_linefeed(ctx, 1);
+ screen_write_linefeed(ctx, 1, 8);
s->cx = 0;
}
@@ -1204,7 +1221,7 @@ screen_write_cell(struct screen_write_ctx *ctx, const struct grid_cell *gc)
/* Check this will fit on the current line and wrap if not. */
if ((s->mode & MODE_WRAP) && s->cx > sx - width) {
- screen_write_linefeed(ctx, 1);
+ screen_write_linefeed(ctx, 1, 8);
s->cx = 0;
}
diff --git a/server-client.c b/server-client.c
index e8a9f757..e6761e30 100644
--- a/server-client.c
+++ b/server-client.c
@@ -49,7 +49,8 @@ static void server_client_dispatch_shell(struct client *);
/* Identify mode callback. */
static void
-server_client_callback_identify(__unused int fd, __unused short events, void *data)
+server_client_callback_identify(__unused int fd, __unused short events,
+ void *data)
{
server_client_clear_identify(data, NULL);
}
@@ -328,7 +329,7 @@ server_client_free(__unused int fd, __unused short events, void *arg)
void
server_client_suspend(struct client *c)
{
- struct session *s = c->session;
+ struct session *s = c->session;
if (s == NULL || (c->flags & CLIENT_DETACHING))
return;
@@ -342,7 +343,7 @@ server_client_suspend(struct client *c)
void
server_client_detach(struct client *c, enum msgtype msgtype)
{
- struct session *s = c->session;
+ struct session *s = c->session;
if (s == NULL || (c->flags & CLIENT_DETACHING))
return;
@@ -945,7 +946,7 @@ retry:
server_status_client(c);
/* Execute the key binding. */
- key_bindings_dispatch(bd, c, m, &fs);
+ key_bindings_dispatch(bd, NULL, c, m, &fs);
key_bindings_unref_table(table);
return;
}
@@ -1238,7 +1239,7 @@ server_client_check_redraw(struct client *c)
struct session *s = c->session;
struct tty *tty = &c->tty;
struct window_pane *wp;
- int needed, flags, masked;
+ int needed, flags, masked;
struct timeval tv = { .tv_usec = 1000 };
static struct event ev;
size_t left;
@@ -1543,7 +1544,7 @@ static void
server_client_dispatch_identify(struct client *c, struct imsg *imsg)
{
const char *data, *home;
- size_t datalen;
+ size_t datalen;
int flags;
char *name;
@@ -1688,7 +1689,7 @@ void
server_client_push_stdout(struct client *c)
{
struct msg_stdout_data data;
- size_t sent, left;
+ size_t sent, left;
left = EVBUFFER_LENGTH(c->stdout_data);
while (left != 0) {
@@ -1729,7 +1730,7 @@ void
server_client_push_stderr(struct client *c)
{
struct msg_stderr_data data;
- size_t sent, left;
+ size_t sent, left;
if (c->stderr_data == c->stdout_data) {
server_client_push_stdout(c);
diff --git a/server-fn.c b/server-fn.c
index 0be7f70d..5b1af13e 100644
--- a/server-fn.c
+++ b/server-fn.c
@@ -300,7 +300,7 @@ server_destroy_pane(struct window_pane *wp, int notify)
screen_write_start(&ctx, wp, &wp->base);
screen_write_scrollregion(&ctx, 0, screen_size_y(ctx.s) - 1);
screen_write_cursormove(&ctx, 0, screen_size_y(ctx.s) - 1);
- screen_write_linefeed(&ctx, 1);
+ screen_write_linefeed(&ctx, 1, 8);
memcpy(&gc, &grid_default_cell, sizeof gc);
gc.attr |= GRID_ATTR_BRIGHT;
screen_write_puts(&ctx, &gc, "Pane is dead");
diff --git a/status.c b/status.c
index 6a35529d..1833d459 100644
--- a/status.c
+++ b/status.c
@@ -656,8 +656,7 @@ status_message_redraw(struct client *c)
/* Enable status line prompt. */
void
status_prompt_set(struct client *c, const char *msg, const char *input,
- int (*callbackfn)(void *, const char *, int), void (*freefn)(void *),
- void *data, int flags)
+ prompt_input_cb inputcb, prompt_free_cb freecb, void *data, int flags)
{
struct format_tree *ft;
time_t t;
@@ -677,8 +676,8 @@ status_prompt_set(struct client *c, const char *msg, const char *input,
c->prompt_buffer = utf8_fromcstr(tmp);
c->prompt_index = utf8_strlen(c->prompt_buffer);
- c->prompt_callbackfn = callbackfn;
- c->prompt_freefn = freefn;
+ c->prompt_inputcb = inputcb;
+ c->prompt_freecb = freecb;
c->prompt_data = data;
c->prompt_hindex = 0;
@@ -692,7 +691,7 @@ status_prompt_set(struct client *c, const char *msg, const char *input,
if ((flags & PROMPT_INCREMENTAL) && *tmp != '\0') {
xasprintf(&cp, "=%s", tmp);
- c->prompt_callbackfn(c->prompt_data, cp, 0);
+ c->prompt_inputcb(c, c->prompt_data, cp, 0);
free(cp);
}
@@ -707,8 +706,8 @@ status_prompt_clear(struct client *c)
if (c->prompt_string == NULL)
return;
- if (c->prompt_freefn != NULL && c->prompt_data != NULL)
- c->prompt_freefn(c->prompt_data);
+ if (c->prompt_freecb != NULL && c->prompt_data != NULL)
+ c->prompt_freecb(c->prompt_data);
free(c->prompt_string);
c->prompt_string = NULL;
@@ -995,7 +994,7 @@ status_prompt_key(struct client *c, key_code key)
if (key >= '0' && key <= '9')
goto append_key;
s = utf8_tocstr(c->prompt_buffer);
- c->prompt_callbackfn(c->prompt_data, s, 1);
+ c->prompt_inputcb(c, c->prompt_data, s, 1);
status_prompt_clear(c);
free(s);
return (1);
@@ -1276,13 +1275,13 @@ process_key:
s = utf8_tocstr(c->prompt_buffer);
if (*s != '\0')
status_prompt_add_history(s);
- if (c->prompt_callbackfn(c->prompt_data, s, 1) == 0)
+ if (c->prompt_inputcb(c, c->prompt_data, s, 1) == 0)
status_prompt_clear(c);
free(s);
break;
case '\033': /* Escape */
case '\003': /* C-c */
- if (c->prompt_callbackfn(c->prompt_data, NULL, 1) == 0)
+ if (c->prompt_inputcb(c, c->prompt_data, NULL, 1) == 0)
status_prompt_clear(c);
break;
case '\022': /* C-r */
@@ -1330,7 +1329,7 @@ append_key:
s = utf8_tocstr(c->prompt_buffer);
if (strlen(s) != 1)
status_prompt_clear(c);
- else if (c->prompt_callbackfn(c->prompt_data, s, 1) == 0)
+ else if (c->prompt_inputcb(c, c->prompt_data, s, 1) == 0)
status_prompt_clear(c);
free(s);
}
@@ -1340,7 +1339,7 @@ changed:
if (c->prompt_flags & PROMPT_INCREMENTAL) {
s = utf8_tocstr(c->prompt_buffer);
xasprintf(&cp, "%c%s", prefix, s);
- c->prompt_callbackfn(c->prompt_data, cp, 0);
+ c->prompt_inputcb(c, c->prompt_data, cp, 0);
free(cp);
free(s);
}
diff --git a/tmux.1 b/tmux.1
index 5284f5cc..05a19e2c 100644
--- a/tmux.1
+++ b/tmux.1
@@ -2335,7 +2335,7 @@ abc123
Commands which set options are as follows:
.Bl -tag -width Ds
.It Xo Ic set-option
-.Op Fl agoqsuw
+.Op Fl aFgoqsuw
.Op Fl t Ar target-session | Ar target-window
.Ar option Ar value
.Xc
@@ -2351,6 +2351,8 @@ otherwise a session option.
If
.Fl g
is given, the global session or window option is set.
+.Fl F
+expands formats in the option value.
The
.Fl u
flag unsets an option, so a session inherits the option from the global
@@ -2901,7 +2903,7 @@ The default is
.Ql \ -_@ .
.El
.It Xo Ic set-window-option
-.Op Fl agoqu
+.Op Fl aFgoqu
.Op Fl t Ar target-window
.Ar option Ar value
.Xc
@@ -2909,6 +2911,7 @@ The default is
Set a window option.
The
.Fl a ,
+.Fl F ,
.Fl g ,
.Fl o ,
.Fl q
diff --git a/tmux.h b/tmux.h
index 40bc99fd..4ee32160 100644
--- a/tmux.h
+++ b/tmux.h
@@ -405,6 +405,7 @@ enum tty_code_code {
TTYC_SS, /* set cursor style, Ss */
TTYC_TC, /* 24-bit "true" colour, Tc */
TTYC_TSL, /* to_status_line, tsl */
+ TTYC_U8,
TTYC_VPA, /* row_address, cv */
TTYC_XENL, /* eat_newline_glitch, xn */
TTYC_XT, /* xterm(1)-compatible title, XT */
@@ -676,6 +677,7 @@ struct screen_write_ctx {
struct screen_write_collect_item *item;
struct screen_write_collect_line *list;
u_int scrolled;
+ u_int bg;
u_int cells;
u_int written;
@@ -796,6 +798,7 @@ struct window_pane {
struct event modetimer;
time_t modelast;
u_int modeprefix;
+ char *searchstr;
TAILQ_ENTRY(window_pane) entry;
RB_ENTRY(window_pane) tree_entry;
@@ -1285,6 +1288,8 @@ struct cmd_entry {
};
/* Client connection. */
+typedef int (*prompt_input_cb)(struct client *, void *, const char *, int);
+typedef void (*prompt_free_cb)(void *);
struct client {
const char *name;
struct tmuxpeer *peer;
@@ -1349,11 +1354,13 @@ struct client {
#define CLIENT_STATUSFORCE 0x80000
#define CLIENT_DOUBLECLICK 0x100000
#define CLIENT_TRIPLECLICK 0x200000
+#define CLIENT_SIZECHANGED 0x400000
int flags;
struct key_table *keytable;
struct event identify_timer;
- void (*identify_callback)(struct client *, struct window_pane *);
+ void (*identify_callback)(struct client *,
+ struct window_pane *);
void *identify_callback_data;
char *message_string;
@@ -1364,8 +1371,8 @@ struct client {
char *prompt_string;
struct utf8_data *prompt_buffer;
size_t prompt_index;
- int (*prompt_callbackfn)(void *, const char *, int);
- void (*prompt_freefn)(void *);
+ prompt_input_cb prompt_inputcb;
+ prompt_free_cb prompt_freecb;
void *prompt_data;
u_int prompt_hindex;
enum { PROMPT_ENTRY, PROMPT_COMMAND } prompt_mode;
@@ -1624,7 +1631,7 @@ void environ_put(struct environ *, const char *);
void environ_unset(struct environ *, const char *);
void environ_update(struct options *, struct environ *, struct environ *);
void environ_push(struct environ *);
-void environ_log(struct environ *, const char *);
+void printflike(2, 3) environ_log(struct environ *, const char *, ...);
struct environ *environ_for_session(struct session *, int);
/* tty.c */
@@ -1702,6 +1709,7 @@ int tty_term_flag(struct tty_term *, enum tty_code_code);
const char *tty_term_describe(struct tty_term *, enum tty_code_code);
/* tty-acs.c */
+int tty_acs_needed(struct tty *);
const char *tty_acs_get(struct tty *, u_char);
/* tty-keys.c */
@@ -1805,8 +1813,8 @@ void key_bindings_add(const char *, key_code, int, struct cmd_list *);
void key_bindings_remove(const char *, key_code);
void key_bindings_remove_table(const char *);
void key_bindings_init(void);
-void key_bindings_dispatch(struct key_binding *, struct client *,
- struct mouse_event *, struct cmd_find_state *);
+void key_bindings_dispatch(struct key_binding *, struct cmdq_item *,
+ struct client *, struct mouse_event *, struct cmd_find_state *);
/* key-string.c */
key_code key_string_lookup_string(const char *);
@@ -1888,7 +1896,7 @@ void printflike(2, 3) status_message_set(struct client *, const char *, ...);
void status_message_clear(struct client *);
int status_message_redraw(struct client *);
void status_prompt_set(struct client *, const char *, const char *,
- int (*)(void *, const char *, int), void (*)(void *), void *, int);
+ prompt_input_cb, prompt_free_cb, void *, int);
void status_prompt_clear(struct client *);
int status_prompt_redraw(struct client *);
int status_prompt_key(struct client *, key_code);
@@ -1933,7 +1941,7 @@ void grid_destroy(struct grid *);
int grid_compare(struct grid *, struct grid *);
void grid_collect_history(struct grid *, u_int);
void grid_scroll_history(struct grid *, u_int);
-void grid_scroll_history_region(struct grid *, u_int, u_int);
+void grid_scroll_history_region(struct grid *, u_int, u_int, u_int);
void grid_clear_history(struct grid *);
const struct grid_line *grid_peek_line(struct grid *, u_int);
void grid_get_cell(struct grid *, u_int, u_int, struct grid_cell *);
@@ -1958,8 +1966,8 @@ void grid_view_set_cells(struct grid *, u_int, u_int,
const struct grid_cell *, const char *, size_t);
void grid_view_clear_history(struct grid *, u_int);
void grid_view_clear(struct grid *, u_int, u_int, u_int, u_int, u_int);
-void grid_view_scroll_region_up(struct grid *, u_int, u_int);
-void grid_view_scroll_region_down(struct grid *, u_int, u_int);
+void grid_view_scroll_region_up(struct grid *, u_int, u_int, u_int);
+void grid_view_scroll_region_down(struct grid *, u_int, u_int, u_int);
void grid_view_insert_lines(struct grid *, u_int, u_int, u_int);
void grid_view_insert_lines_region(struct grid *, u_int, u_int, u_int,
u_int);
@@ -2006,10 +2014,10 @@ void screen_write_clearline(struct screen_write_ctx *, u_int);
void screen_write_clearendofline(struct screen_write_ctx *, u_int);
void screen_write_clearstartofline(struct screen_write_ctx *, u_int);
void screen_write_cursormove(struct screen_write_ctx *, u_int, u_int);
-void screen_write_reverseindex(struct screen_write_ctx *);
+void screen_write_reverseindex(struct screen_write_ctx *, u_int);
void screen_write_scrollregion(struct screen_write_ctx *, u_int, u_int);
-void screen_write_linefeed(struct screen_write_ctx *, int);
-void screen_write_scrollup(struct screen_write_ctx *, u_int);
+void screen_write_linefeed(struct screen_write_ctx *, int, u_int);
+void screen_write_scrollup(struct screen_write_ctx *, u_int, u_int);
void screen_write_carriagereturn(struct screen_write_ctx *);
void screen_write_clearendofscreen(struct screen_write_ctx *, u_int);
void screen_write_clearstartofscreen(struct screen_write_ctx *, u_int);
@@ -2180,7 +2188,6 @@ void window_copy_vadd(struct window_pane *, const char *, va_list);
void window_copy_pageup(struct window_pane *, int);
void window_copy_start_drag(struct client *, struct mouse_event *);
int window_copy_scroll_position(struct window_pane *);
-const char *window_copy_search_string(struct window_pane *);
/* window-choose.c */
extern const struct window_mode window_choose_mode;
diff --git a/tty-acs.c b/tty-acs.c
index 6e3103d9..1f7a2b11 100644
--- a/tty-acs.c
+++ b/tty-acs.c
@@ -74,23 +74,48 @@ tty_acs_cmp(const void *key, const void *value)
return (ch - entry->key);
}
+/* Should this terminal use ACS instead of UTF-8 line drawing? */
+int
+tty_acs_needed(struct tty *tty)
+{
+ if (tty == NULL)
+ return (0);
+
+ /*
+ * If the U8 flag is present, it marks whether a terminal supports
+ * UTF-8 and ACS together.
+ *
+ * If it is present and zero, we force ACS - this gives users a way to
+ * turn off UTF-8 line drawing.
+ *
+ * If it is nonzero, we can fall through to the default and use UTF-8
+ * line drawing on UTF-8 terminals.
+ */
+ if (tty_term_has(tty->term, TTYC_U8) &&
+ tty_term_number(tty->term, TTYC_U8) == 0)
+ return (1);
+
+ if (tty->flags & TTY_UTF8)
+ return (0);
+ return (1);
+}
+
/* Retrieve ACS to output as a string. */
const char *
tty_acs_get(struct tty *tty, u_char ch)
{
- struct tty_acs_entry *entry;
+ struct tty_acs_entry *entry;
- /* If not a UTF-8 terminal, use the ACS set. */
- if (tty != NULL && !(tty->flags & TTY_UTF8)) {
+ /* Use the ACS set instead of UTF-8 if needed. */
+ if (tty_acs_needed(tty)) {
if (tty->term->acs[ch][0] == '\0')
return (NULL);
return (&tty->term->acs[ch][0]);
}
/* Otherwise look up the UTF-8 translation. */
- entry = bsearch(&ch,
- tty_acs_table, nitems(tty_acs_table), sizeof tty_acs_table[0],
- tty_acs_cmp);
+ entry = bsearch(&ch, tty_acs_table, nitems(tty_acs_table),
+ sizeof tty_acs_table[0], tty_acs_cmp);
if (entry == NULL)
return (NULL);
return (entry->string);
diff --git a/tty-term.c b/tty-term.c
index b8a25de5..9fd9b090 100644
--- a/tty-term.c
+++ b/tty-term.c
@@ -257,6 +257,7 @@ static const struct tty_term_code_entry tty_term_codes[] = {
[TTYC_TC] = { TTYCODE_FLAG, "Tc" },
[TTYC_TSL] = { TTYCODE_STRING, "tsl" },
[TTYC_VPA] = { TTYCODE_STRING, "vpa" },
+ [TTYC_U8] = { TTYCODE_NUMBER, "U8" },
[TTYC_XENL] = { TTYCODE_FLAG, "xenl" },
[TTYC_XT] = { TTYCODE_FLAG, "XT" },
};
diff --git a/tty.c b/tty.c
index 1c39fce4..d792c9c2 100644
--- a/tty.c
+++ b/tty.c
@@ -71,8 +71,6 @@ static void tty_default_colours(struct grid_cell *,
static void tty_default_attributes(struct tty *, const struct window_pane *,
u_int);
-#define tty_use_acs(tty) \
- (tty_term_has((tty)->term, TTYC_ACSC) && !((tty)->flags & TTY_UTF8))
#define tty_use_margin(tty) \
((tty)->term_type == TTY_VT420)
@@ -278,7 +276,8 @@ tty_open(struct tty *tty, char **cause)
void
tty_start_tty(struct tty *tty)
{
- struct termios tio;
+ struct client *c = tty->client;
+ struct termios tio;
if (tty->fd != -1 && tcgetattr(tty->fd, &tty->tio) == 0) {
setblocking(tty->fd, 0);
@@ -299,10 +298,14 @@ tty_start_tty(struct tty *tty)
tty_putcode(tty, TTYC_SMCUP);
tty_putcode(tty, TTYC_SMKX);
- if (tty_use_acs(tty))
- tty_putcode(tty, TTYC_ENACS);
tty_putcode(tty, TTYC_CLEAR);
+ if (tty_acs_needed(tty)) {
+ log_debug("%s: using capabilities for ACS", c->name);
+ tty_putcode(tty, TTYC_ENACS);
+ } else
+ log_debug("%s: using UTF-8 for ACS", c->name);
+
tty_putcode(tty, TTYC_CNORM);
if (tty_term_has(tty->term, TTYC_KMOUS))
tty_puts(tty, "\033[?1000l\033[?1002l\033[?1006l\033[?1005l");
@@ -351,7 +354,7 @@ tty_stop_tty(struct tty *tty)
return;
tty_raw(tty, tty_term_string2(tty->term, TTYC_CSR, 0, ws.ws_row - 1));
- if (tty_use_acs(tty))
+ if (tty_acs_needed(tty))
tty_raw(tty, tty_term_string(tty->term, TTYC_RMACS));
tty_raw(tty, tty_term_string(tty->term, TTYC_SGR0));
tty_raw(tty, tty_term_string(tty->term, TTYC_RMKX));
@@ -754,6 +757,115 @@ tty_redraw_region(struct tty *tty, const struct tty_ctx *ctx)
}
}
+static void
+tty_clear_line(struct tty *tty, const struct window_pane *wp, u_int py,
+ u_int px, u_int nx, u_int bg)
+{
+ log_debug("%s: %u at %u,%u", __func__, nx, px, py);
+
+ /* Nothing to clear. */
+ if (nx == 0)
+ return;
+
+ /* If genuine BCE is available, can try escape sequences. */
+ if (!tty_fake_bce(tty, wp, bg)) {
+ /* Off the end of the line, use EL if available. */
+ if (px + nx >= tty->sx && tty_term_has(tty->term, TTYC_EL)) {
+ tty_cursor(tty, px, py);
+ tty_putcode(tty, TTYC_EL);
+ return;
+ }
+
+ /* At the start of the line. Use EL1. */
+ if (px == 0 && tty_term_has(tty->term, TTYC_EL1)) {
+ tty_cursor(tty, px + nx - 1, py);
+ tty_putcode(tty, TTYC_EL1);
+ return;
+ }
+
+ /* Section of line. Use ECH if possible. */
+ if (tty_term_has(tty->term, TTYC_ECH)) {
+ tty_cursor(tty, px, py);
+ tty_putcode1(tty, TTYC_ECH, nx);
+ return;
+ }
+ }
+
+ /* Couldn't use an escape sequence, use spaces. */
+ tty_cursor(tty, px, py);
+ tty_repeat_space(tty, nx);
+}
+
+static void
+tty_clear_area(struct tty *tty, const struct window_pane *wp, u_int py,
+ u_int ny, u_int px, u_int nx, u_int bg)
+{
+ u_int yy;
+ char tmp[64];
+
+ log_debug("%s: %u,%u at %u,%u", __func__, nx, ny, px, py);
+
+ /* Nothing to clear. */
+ if (nx == 0 || ny == 0)
+ return;
+
+ /* If genuine BCE is available, can try escape sequences. */
+ if (!tty_fake_bce(tty, wp, bg)) {
+ /* Use ED if clearing off the bottom of the terminal. */
+ if (px == 0 &&
+ px + nx >= tty->sx &&
+ py + ny >= tty->sy &&
+ tty_term_has(tty->term, TTYC_ED)) {
+ tty_cursor(tty, 0, py);
+ tty_putcode(tty, TTYC_ED);
+ return;
+ }
+
+ /*
+ * On VT420 compatible terminals we can use DECFRA if the
+ * background colour isn't default (because it doesn't work
+ * after SGR 0).
+ */
+ if (tty->term_type == TTY_VT420 && bg != 8) {
+ xsnprintf(tmp, sizeof tmp, "\033[32;%u;%u;%u;%u$x",
+ py + 1, px + 1, py + ny, px + nx);
+ tty_puts(tty, tmp);
+ return;
+ }
+
+ /* Full lines can be scrolled away to clear them. */
+ if (px == 0 &&
+ px + nx >= tty->sx &&
+ ny > 2 &&
+ tty_term_has(tty->term, TTYC_CSR) &&
+ tty_term_has(tty->term, TTYC_INDN)) {
+ tty_region(tty, py, py + ny - 1);
+ tty_margin_off(tty);
+ tty_putcode1(tty, TTYC_INDN, ny);
+ return;
+ }
+
+ /*
+ * If margins are supported, can just scroll the area off to
+ * clear it.
+ */
+ if (nx > 2 &&
+ ny > 2 &&
+ tty_term_has(tty->term, TTYC_CSR) &&
+ tty_use_margin(tty) &&
+ tty_term_has(tty->term, TTYC_INDN)) {
+ tty_region(tty, py, py + ny - 1);
+ tty_margin(tty, px, px + nx - 1);
+ tty_putcode1(tty, TTYC_INDN, ny);
+ return;
+ }
+ }
+
+ /* Couldn't use an escape sequence, loop over the lines. */
+ for (yy = py; yy < py + ny; yy++)
+ tty_clear_line(tty, wp, yy, px, nx, bg);
+}
+
void
tty_draw_pane(struct tty *tty, const struct window_pane *wp, u_int py, u_int ox,
u_int oy)
@@ -766,7 +878,7 @@ tty_draw_line(struct tty *tty, const struct window_pane *wp,
struct screen *s, u_int py, u_int ox, u_int oy)
{
struct grid_cell gc, last;
- u_int i, j, sx, width;
+ u_int i, j, sx, nx, width;
int flags, cleared = 0;
char buf[512];
size_t len;
@@ -861,16 +973,10 @@ tty_draw_line(struct tty *tty, const struct window_pane *wp,
tty_putn(tty, buf, len, width);
}
- if (!cleared && sx < tty->sx) {
+ nx = screen_size_x(s) - sx;
+ if (!cleared && sx < tty->sx && nx != 0) {
tty_default_attributes(tty, wp, 8);
- tty_cursor(tty, ox + sx, oy + py);
- if (sx != screen_size_x(s) &&
- ox + screen_size_x(s) >= tty->sx &&
- tty_term_has(tty->term, TTYC_EL) &&
- !tty_fake_bce(tty, wp, 8))
- tty_putcode(tty, TTYC_EL);
- else
- tty_repeat_space(tty, screen_size_x(s) - sx);
+ tty_clear_line(tty, wp, oy + py, ox + sx, nx, 8);
}
tty->flags = (tty->flags & ~TTY_NOCURSOR) | flags;
@@ -1018,73 +1124,54 @@ void
tty_cmd_clearline(struct tty *tty, const struct tty_ctx *ctx)
{
struct window_pane *wp = ctx->wp;
- struct screen *s = wp->screen;
- u_int sx = screen_size_x(s);
+ u_int nx, py = ctx->yoff + ctx->ocy;
tty_default_attributes(tty, wp, ctx->bg);
- tty_cursor_pane(tty, ctx, 0, ctx->ocy);
-
- if (tty_pane_full_width(tty, ctx) &&
- !tty_fake_bce(tty, wp, ctx->bg) &&
- tty_term_has(tty->term, TTYC_EL))
- tty_putcode(tty, TTYC_EL);
- else
- tty_repeat_space(tty, sx);
+ nx = screen_size_x(wp->screen);
+ tty_clear_line(tty, wp, py, ctx->xoff, nx, ctx->bg);
}
void
tty_cmd_clearendofline(struct tty *tty, const struct tty_ctx *ctx)
{
struct window_pane *wp = ctx->wp;
- struct screen *s = wp->screen;
- u_int sx = screen_size_x(s);
+ u_int nx, py = ctx->yoff + ctx->ocy;
tty_default_attributes(tty, wp, ctx->bg);
- tty_cursor_pane(tty, ctx, ctx->ocx, ctx->ocy);
-
- if (tty_pane_full_width(tty, ctx) &&
- tty_term_has(tty->term, TTYC_EL) &&
- !tty_fake_bce(tty, wp, ctx->bg))
- tty_putcode(tty, TTYC_EL);
- else
- tty_repeat_space(tty, sx - ctx->ocx);
+ nx = screen_size_x(wp->screen) - ctx->ocx;
+ tty_clear_line(tty, wp, py, ctx->xoff + ctx->ocx, nx, ctx->bg);
}
void
tty_cmd_clearstartofline(struct tty *tty, const struct tty_ctx *ctx)
{
struct window_pane *wp = ctx->wp;
+ u_int py = ctx->yoff + ctx->ocy;
tty_default_attributes(tty, wp, ctx->bg);
- if (ctx->xoff == 0 &&
- tty_term_has(tty->term, TTYC_EL1) &&
- !tty_fake_bce(tty, ctx->wp, ctx->bg)) {
- tty_cursor_pane(tty, ctx, ctx->ocx, ctx->ocy);
- tty_putcode(tty, TTYC_EL1);
- } else {
- tty_cursor_pane(tty, ctx, 0, ctx->ocy);
- tty_repeat_space(tty, ctx->ocx + 1);
- }
+ tty_clear_line(tty, wp, py, ctx->xoff, ctx->ocx + 1, ctx->bg);
}
void
tty_cmd_reverseindex(struct tty *tty, const struct tty_ctx *ctx)
{
+ struct window_pane *wp = ctx->wp;
+
if (ctx->ocy != ctx->orupper)
return;
if (!tty_pane_full_width(tty, ctx) ||
- tty_fake_bce(tty, ctx->wp, 8) ||
+ tty_fake_bce(tty, wp, 8) ||
!tty_term_has(tty->term, TTYC_CSR) ||
!tty_term_has(tty->term, TTYC_RI)) {
tty_redraw_region(tty, ctx);
return;
}
- tty_attributes(tty, &grid_default_cell, ctx->wp);
+ tty_default_attributes(tty, wp, ctx->bg);
tty_region_pane(tty, ctx, ctx->orupper, ctx->orlower);
tty_margin_off(tty);
@@ -1108,7 +1195,7 @@ tty_cmd_linefeed(struct tty *tty, const struct tty_ctx *ctx)
return;
}
- tty_attributes(tty, &grid_default_cell, wp);
+ tty_default_attributes(tty, wp, ctx->bg);
tty_region_pane(tty, ctx, ctx->orupper, ctx->orlower);
tty_margin_pane(tty, ctx);
@@ -1130,7 +1217,7 @@ void
tty_cmd_scrollup(struct tty *tty, const struct tty_ctx *ctx)
{
struct window_pane *wp = ctx->wp;
- u_int i, lines;
+ u_int i;
if ((!tty_pane_full_width(tty, ctx) && !tty_use_margin(tty)) ||
tty_fake_bce(tty, wp, 8) ||
@@ -1139,142 +1226,86 @@ tty_cmd_scrollup(struct tty *tty, const struct tty_ctx *ctx)
return;
}
- tty_attributes(tty, &grid_default_cell, wp);
+ tty_default_attributes(tty, wp, ctx->bg);
tty_region_pane(tty, ctx, ctx->orupper, ctx->orlower);
tty_margin_pane(tty, ctx);
- /*
- * Konsole has a bug where it will ignore SU if the parameter is more
- * than the height of the scroll region. Clamping the parameter doesn't
- * hurt in any case.
- */
- lines = tty->rlower - tty->rupper;
- if (lines > ctx->num)
- lines = ctx->num;
-
- if (lines == 1 || !tty_term_has(tty->term, TTYC_INDN)) {
+ if (ctx->num == 1 || !tty_term_has(tty->term, TTYC_INDN)) {
tty_cursor(tty, tty->rright, tty->rlower);
- for (i = 0; i < lines; i++)
+ for (i = 0; i < ctx->num; i++)
tty_putc(tty, '\n');
} else
- tty_putcode1(tty, TTYC_INDN, lines);
+ tty_putcode1(tty, TTYC_INDN, ctx->num);
}
void
tty_cmd_clearendofscreen(struct tty *tty, const struct tty_ctx *ctx)
{
struct window_pane *wp = ctx->wp;
- struct screen *s = wp->screen;
- u_int i, j;
- u_int sx = screen_size_x(s), sy = screen_size_y(s);
+ u_int px, py, nx, ny;
tty_default_attributes(tty, wp, ctx->bg);
- tty_region_pane(tty, ctx, 0, sy - 1);
+ tty_region_pane(tty, ctx, 0, screen_size_y(wp->screen) - 1);
tty_margin_off(tty);
- if (tty_pane_full_width(tty, ctx) &&
- ctx->yoff + wp->sy >= tty->sy - 1 &&
- status_at_line(tty->client) <= 0 &&
- tty_term_has(tty->term, TTYC_ED)) {
- tty_cursor_pane(tty, ctx, ctx->ocx, ctx->ocy);
- tty_putcode(tty, TTYC_ED);
- } else if (tty_pane_full_width(tty, ctx) &&
- tty_term_has(tty->term, TTYC_EL) &&
- !tty_fake_bce(tty, wp, ctx->bg)) {
- tty_cursor_pane(tty, ctx, ctx->ocx, ctx->ocy);
- tty_putcode(tty, TTYC_EL);
- if (ctx->ocy != sy - 1) {
- tty_cursor_pane(tty, ctx, 0, ctx->ocy + 1);
- for (i = ctx->ocy + 1; i < sy; i++) {
- tty_putcode(tty, TTYC_EL);
- if (i == sy - 1)
- continue;
- tty_emulate_repeat(tty, TTYC_CUD, TTYC_CUD1, 1);
- tty->cy++;
- }
- }
- } else {
- tty_cursor_pane(tty, ctx, ctx->ocx, ctx->ocy);
- tty_repeat_space(tty, sx - ctx->ocx);
- for (j = ctx->ocy + 1; j < sy; j++) {
- tty_cursor_pane(tty, ctx, 0, j);
- tty_repeat_space(tty, sx);
- }
- }
+ px = ctx->xoff;
+ nx = screen_size_x(wp->screen);
+ py = ctx->yoff + ctx->ocy + 1;
+ ny = screen_size_y(wp->screen) - ctx->ocy - 1;
+
+ tty_clear_area(tty, wp, py, ny, px, nx, ctx->bg);
+
+ px = ctx->xoff + ctx->ocx;
+ nx = screen_size_x(wp->screen) - ctx->ocx;
+ py = ctx->yoff + ctx->ocy;
+
+ tty_clear_line(tty, wp, py, px, nx, ctx->bg);
}
void
tty_cmd_clearstartofscreen(struct tty *tty, const struct tty_ctx *ctx)
{
struct window_pane *wp = ctx->wp;
- struct screen *s = wp->screen;
- u_int i, j;
- u_int sx = screen_size_x(s), sy = screen_size_y(s);
+ u_int px, py, nx, ny;
tty_default_attributes(tty, wp, ctx->bg);
- tty_region_pane(tty, ctx, 0, sy - 1);
+ tty_region_pane(tty, ctx, 0, screen_size_y(wp->screen) - 1);
tty_margin_off(tty);
- if (tty_pane_full_width(tty, ctx) &&
- tty_term_has(tty->term, TTYC_EL) &&
- !tty_fake_bce(tty, wp, ctx->bg)) {
- tty_cursor_pane(tty, ctx, 0, 0);
- for (i = 0; i < ctx->ocy; i++) {
- tty_putcode(tty, TTYC_EL);
- tty_emulate_repeat(tty, TTYC_CUD, TTYC_CUD1, 1);
- tty->cy++;
- }
- } else {
- tty_cursor_pane(tty, ctx, 0, 0);
- for (j = 0; j < ctx->ocy; j++) {
- tty_cursor_pane(tty, ctx, 0, j);
- tty_repeat_space(tty, sx);
- }
- }
- tty_cursor_pane(tty, ctx, 0, ctx->ocy);
- tty_repeat_space(tty, ctx->ocx + 1);
+ px = ctx->xoff;
+ nx = screen_size_x(wp->screen);
+ py = ctx->yoff;
+ ny = ctx->ocy - 1;
+
+ tty_clear_area(tty, wp, py, ny, px, nx, ctx->bg);
+
+ px = ctx->xoff;
+ nx = ctx->ocx + 1;
+ py = ctx->yoff + ctx->ocy;
+
+ tty_clear_line(tty, wp, py, px, nx, ctx->bg);
}
void
tty_cmd_clearscreen(struct tty *tty, const struct tty_ctx *ctx)
{
struct window_pane *wp = ctx->wp;
- struct screen *s = wp->screen;
- u_int i, j;
- u_int sx = screen_size_x(s), sy = screen_size_y(s);
+ u_int px, py, nx, ny;
tty_default_attributes(tty, wp, ctx->bg);
- tty_region_pane(tty, ctx, 0, sy - 1);
+ tty_region_pane(tty, ctx, 0, screen_size_y(wp->screen) - 1);
tty_margin_off(tty);
- if (tty_pane_full_width(tty, ctx) &&
- ctx->yoff + wp->sy >= tty->sy - 1 &&
- status_at_line(tty->client) <= 0 &&
- tty_term_has(tty->term, TTYC_ED)) {
- tty_cursor_pane(tty, ctx, 0, 0);
- tty_putcode(tty, TTYC_ED);
- } else if (tty_pane_full_width(tty, ctx) &&
- tty_term_has(tty->term, TTYC_EL) &&
- !tty_fake_bce(tty, wp, ctx->bg)) {
- tty_cursor_pane(tty, ctx, 0, 0);
- for (i = 0; i < sy; i++) {
- tty_putcode(tty, TTYC_EL);
- if (i != sy - 1) {
- tty_emulate_repeat(tty, TTYC_CUD, TTYC_CUD1, 1);
- tty->cy++;
- }
- }
- } else {
- tty_cursor_pane(tty, ctx, 0, 0);
- for (j = 0; j < sy; j++) {
- tty_cursor_pane(tty, ctx, 0, j);
- tty_repeat_space(tty, sx);
- }
- }
+ px = ctx->xoff;
+ nx = screen_size_x(wp->screen);
+ py = ctx->yoff;
+ ny = screen_size_y(wp->screen);
+
+ tty_clear_area(tty, wp, py, ny, px, nx, ctx->bg);
}
void
@@ -1389,7 +1420,7 @@ tty_reset(struct tty *tty)
struct grid_cell *gc = &tty->cell;
if (!grid_cells_equal(gc, &grid_default_cell)) {
- if ((gc->attr & GRID_ATTR_CHARSET) && tty_use_acs(tty))
+ if ((gc->attr & GRID_ATTR_CHARSET) && tty_acs_needed(tty))
tty_putcode(tty, TTYC_RMACS);
tty_putcode(tty, TTYC_SGR0);
memcpy(gc, &grid_default_cell, sizeof *gc);
@@ -1739,7 +1770,7 @@ tty_attributes(struct tty *tty, const struct grid_cell *gc,
tty_putcode(tty, TTYC_INVIS);
if (changed & GRID_ATTR_STRIKETHROUGH)
tty_putcode(tty, TTYC_SMXX);
- if ((changed & GRID_ATTR_CHARSET) && tty_use_acs(tty))
+ if ((changed & GRID_ATTR_CHARSET) && tty_acs_needed(tty))
tty_putcode(tty, TTYC_SMACS);
}
diff --git a/window-copy.c b/window-copy.c
index 8424bfa6..6d1a9f69 100644
--- a/window-copy.c
+++ b/window-copy.c
@@ -208,8 +208,13 @@ window_copy_init(struct window_pane *wp)
data->rectflag = 0;
data->scroll_exit = 0;
- data->searchtype = WINDOW_COPY_OFF;
- data->searchstr = NULL;
+ if (wp->searchstr != NULL) {
+ data->searchtype = WINDOW_COPY_SEARCHUP;
+ data->searchstr = xstrdup(wp->searchstr);
+ } else {
+ data->searchtype = WINDOW_COPY_OFF;
+ data->searchstr = NULL;
+ }
data->searchmark = NULL;
data->searchx = data->searchy = data->searcho = -1;
@@ -316,7 +321,7 @@ window_copy_vadd(struct window_pane *wp, const char *fmt, va_list ap)
* (so it's on a new line).
*/
screen_write_carriagereturn(&back_ctx);
- screen_write_linefeed(&back_ctx, 0);
+ screen_write_linefeed(&back_ctx, 0, 8);
} else
data->backing_written = 1;
old_cy = backing->cy;
@@ -1134,6 +1139,9 @@ window_copy_search(struct window_pane *wp, int direction, int moveflag)
u_int fx, fy, endline;
int wrapflag, cis, found;
+ free(wp->searchstr);
+ wp->searchstr = xstrdup(data->searchstr);
+
fx = data->cx;
fy = screen_hsize(data->backing) - data->oy + data->cy;
@@ -2482,16 +2490,3 @@ window_copy_drag_update(__unused struct client *c, struct mouse_event *m)
if (window_copy_update_selection(wp, 1))
window_copy_redraw_selection(wp, old_cy);
}
-
-const char *
-window_copy_search_string(struct window_pane *wp)
-{
- struct window_copy_mode_data *data;
-
- if (wp->mode != &window_copy_mode)
- return ("");
- data = wp->modedata;
- if (data->searchtype == WINDOW_COPY_OFF || data->searchstr == NULL)
- return ("");
- return (data->searchstr);
-}
diff --git a/window.c b/window.c
index 92742685..f5024c43 100644
--- a/window.c
+++ b/window.c
@@ -828,6 +828,7 @@ static void
window_pane_destroy(struct window_pane *wp)
{
window_pane_reset_mode(wp);
+ free(wp->searchstr);
if (wp->fd != -1) {
#ifdef HAVE_UTEMPTER