Merge branch 'master' into sixel

topcat001 2023-07-22 17:29:10 -07:00
commit 14b8b52452
28 changed files with 512 additions and 155 deletions

View File

@ -189,7 +189,7 @@ out:
/* Parse flags argument. */
static int
args_parse_flags(const struct args_parse *parse, struct args_value *values,
u_int count, char **cause, struct args *args, int *i)
u_int count, char **cause, struct args *args, u_int *i)
{
struct args_value *value;
u_char flag;

View File

@ -245,9 +245,6 @@ client_main(struct event_base *base, int argc, char **argv, uint64_t flags,
u_int ncaps = 0;
struct args_value *values;
/* Ignore SIGCHLD now or daemon() in the server will leave a zombie. */
signal(SIGCHLD, SIG_IGN);
/* Set up the initial command. */
if (shell_command != NULL) {
msg = MSG_SHELL;
@ -533,11 +530,22 @@ client_signal(int sig)
{
struct sigaction sigact;
int status;
pid_t pid;
log_debug("%s: %s", __func__, strsignal(sig));
if (sig == SIGCHLD)
waitpid(WAIT_ANY, &status, WNOHANG);
else if (!client_attached) {
if (sig == SIGCHLD) {
for (;;) {
pid = waitpid(WAIT_ANY, &status, WNOHANG);
if (pid == 0)
break;
if (pid == -1) {
if (errno == ECHILD)
break;
log_debug("waitpid failed: %s",
strerror(errno));
}
}
} else if (!client_attached) {
if (sig == SIGTERM || sig == SIGHUP)
proc_exit(client_proc);
} else {

View File

@ -582,7 +582,7 @@ cmd_find_get_pane_with_window(struct cmd_find_state *fs, const char *pane)
/* Try special characters. */
if (strcmp(pane, "!") == 0) {
fs->wp = fs->w->last;
fs->wp = TAILQ_FIRST(&fs->w->last_panes);
if (fs->wp == NULL)
return (-1);
return (0);

View File

@ -53,8 +53,7 @@ cmd_resize_window_exec(struct cmd *self, struct cmdq_item *item)
struct session *s = target->s;
const char *errstr;
char *cause;
u_int adjust, sx, sy;
int xpixel = -1, ypixel = -1;
u_int adjust, sx, sy, xpixel = 0, ypixel = 0;
if (args_count(args) == 0)
adjust = 1;

View File

@ -98,7 +98,11 @@ cmd_select_pane_exec(struct cmd *self, struct cmdq_item *item)
struct options_entry *o;
if (entry == &cmd_last_pane_entry || args_has(args, 'l')) {
lastwp = w->last;
/*
* Check for no last pane found in case the other pane was
* spawned without being visited (for example split-window -d).
*/
lastwp = TAILQ_FIRST(&w->last_panes);
if (lastwp == NULL && window_count_panes(w) == 2) {
lastwp = TAILQ_PREV(w->active, window_panes, entry);
if (lastwp == NULL)

View File

@ -128,10 +128,8 @@ cmd_swap_pane_exec(struct cmd *self, struct cmdq_item *item)
window_set_active_pane(dst_w, src_wp, 1);
}
if (src_w != dst_w) {
if (src_w->last == src_wp)
src_w->last = NULL;
if (dst_w->last == dst_wp)
dst_w->last = NULL;
window_pane_stack_remove(&src_w->last_panes, src_wp);
window_pane_stack_remove(&dst_w->last_panes, dst_wp);
colour_palette_from_option(&src_wp->palette, src_wp->options);
colour_palette_from_option(&dst_wp->palette, dst_wp->options);
}

View File

@ -315,7 +315,7 @@ fi
if test "x$found_ncurses" = xno; then
AC_SEARCH_LIBS(
setupterm,
[tinfo ncurses ncursesw],
[tinfo terminfo ncurses ncursesw],
found_ncurses=yes,
found_ncurses=no
)
@ -461,7 +461,7 @@ AM_CONDITIONAL(ENABLE_SIXEL, [test "x$enable_sixel" = xyes])
# Check for b64_ntop. If we have b64_ntop, we assume b64_pton as well.
AC_MSG_CHECKING(for b64_ntop)
AC_LINK_IFELSE([AC_LANG_PROGRAM(
AC_LINK_IFELSE([AC_LANG_PROGRAM(
[
#include <sys/types.h>
#include <netinet/in.h>

View File

@ -1902,7 +1902,7 @@ static void *
format_cb_pane_last(struct format_tree *ft)
{
if (ft->wp != NULL) {
if (ft->wp == ft->wp->window->last)
if (ft->wp == TAILQ_FIRST(&ft->wp->window->last_panes))
return (xstrdup("1"));
return (xstrdup("0"));
}
@ -3664,7 +3664,9 @@ format_skip(const char *s, const char *end)
for (; *s != '\0'; s++) {
if (*s == '#' && s[1] == '{')
brackets++;
if (*s == '#' && strchr(",#{}:", s[1]) != NULL) {
if (*s == '#' &&
s[1] != '\0' &&
strchr(",#{}:", s[1]) != NULL) {
s++;
continue;
}
@ -3813,7 +3815,7 @@ format_build_modifiers(struct format_expand_state *es, const char **s,
argc = 0;
/* Single argument with no wrapper character. */
if (!ispunct(cp[1]) || cp[1] == '-') {
if (!ispunct((u_char)cp[1]) || cp[1] == '-') {
end = format_skip(cp + 1, ":;");
if (end == NULL)
break;

13
grid.c
View File

@ -37,7 +37,7 @@
/* Default grid cell data. */
const struct grid_cell grid_default_cell = {
{ { ' ' }, 0, 1, 1 }, 0, 0, 8, 8, 0, 0
{ { ' ' }, 0, 1, 1 }, 0, 0, 8, 8, 8, 0
};
/*
@ -45,12 +45,12 @@ const struct grid_cell grid_default_cell = {
* appears in the grid - because of this, they are always extended cells.
*/
static const struct grid_cell grid_padding_cell = {
{ { '!' }, 0, 0, 0 }, 0, GRID_FLAG_PADDING, 8, 8, 0, 0
{ { '!' }, 0, 0, 0 }, 0, GRID_FLAG_PADDING, 8, 8, 8, 0
};
/* Cleared grid cell data. */
static const struct grid_cell grid_cleared_cell = {
{ { ' ' }, 0, 1, 1 }, 0, GRID_FLAG_CLEARED, 8, 8, 0, 0
{ { ' ' }, 0, 1, 1 }, 0, GRID_FLAG_CLEARED, 8, 8, 8, 0
};
static const struct grid_cell_entry grid_cleared_entry = {
{ .data = { 0, 8, 8, ' ' } }, GRID_FLAG_CLEARED
@ -528,7 +528,7 @@ grid_get_cell1(struct grid_line *gl, u_int px, struct grid_cell *gc)
gc->bg = gce->data.bg;
if (gce->flags & GRID_FLAG_BG256)
gc->bg |= COLOUR_FLAG_256;
gc->us = 0;
gc->us = 8;
utf8_set(&gc->data, gce->data.data);
gc->link = 0;
}
@ -956,7 +956,7 @@ grid_string_cells_code(const struct grid_cell *lastgc,
for (i = 0; i < nitems(attrs); i++) {
if (((~attr & attrs[i].mask) &&
(lastattr & attrs[i].mask)) ||
(lastgc->us != 0 && gc->us == 0)) {
(lastgc->us != 8 && gc->us == 8)) {
s[n++] = 0;
lastattr &= GRID_ATTR_CHARSET;
break;
@ -1044,7 +1044,8 @@ grid_string_cells(struct grid *gd, u_int px, u_int py, u_int nx,
const char *data;
char *buf, code[8192];
size_t len, off, size, codelen;
u_int xx, has_link = 0, end;
u_int xx, end;
int has_link = 0;
const struct grid_line *gl;
if (lastgc != NULL && *lastgc == NULL) {

View File

@ -42,7 +42,7 @@
#define MAX_HYPERLINKS 5000
static uint64_t hyperlinks_next_external_id = 1;
static long long hyperlinks_next_external_id = 1;
static u_int global_hyperlinks_count;
struct hyperlinks_uri {

32
input.c
View File

@ -144,6 +144,7 @@ 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 *);
static void input_osc_133(struct input_ctx *, const char *);
/* Transition entry/exit handlers. */
static void input_clear(struct input_ctx *);
@ -2069,7 +2070,7 @@ static void
input_csi_dispatch_sgr(struct input_ctx *ictx)
{
struct grid_cell *gc = &ictx->cell.cell;
u_int i;
u_int i, link;
int n;
if (ictx->param_list_len == 0) {
@ -2101,7 +2102,9 @@ input_csi_dispatch_sgr(struct input_ctx *ictx)
switch (n) {
case 0:
link = gc->link;
memcpy(gc, &grid_default_cell, sizeof *gc);
gc->link = link;
break;
case 1:
gc->attr |= GRID_ATTR_BRIGHT;
@ -2187,7 +2190,7 @@ input_csi_dispatch_sgr(struct input_ctx *ictx)
gc->attr &= ~GRID_ATTR_OVERLINE;
break;
case 59:
gc->us = 0;
gc->us = 8;
break;
case 90:
case 91:
@ -2363,6 +2366,9 @@ input_exit_osc(struct input_ctx *ictx)
case 112:
input_osc_112(ictx, p);
break;
case 133:
input_osc_133(ictx, p);
break;
default:
log_debug("%s: unknown '%u'", __func__, option);
break;
@ -2752,6 +2758,24 @@ input_osc_112(struct input_ctx *ictx, const char *p)
screen_set_cursor_colour(ictx->ctx.s, -1);
}
/* Handle the OSC 133 sequence. */
static void
input_osc_133(struct input_ctx *ictx, const char *p)
{
struct grid *gd = ictx->ctx.s->grid;
u_int line = ictx->ctx.s->cy + gd->hsize;
struct grid_line *gl;
if (line > gd->hsize + gd->sy - 1)
return;
gl = grid_get_line(gd, line);
switch (*p) {
case 'A':
gl->flags |= GRID_LINE_START_PROMPT;
break;
}
}
/* Handle the OSC 52 sequence for setting the clipboard. */
static void
@ -2858,9 +2882,11 @@ input_reply_clipboard(struct bufferevent *bev, const char *buf, size_t len,
const char *end)
{
char *out = NULL;
size_t outlen = 0;
int outlen = 0;
if (buf != NULL && len != 0) {
if (len >= ((size_t)INT_MAX * 3 / 4) - 1)
return;
outlen = 4 * ((len + 2) / 3) + 1;
out = xmalloc(outlen);
if ((outlen = b64_ntop(buf, len, out, outlen)) == -1) {

View File

@ -193,7 +193,7 @@ notify_add(const char *name, struct cmd_find_state *fs, struct client *c,
ne->client = c;
ne->session = s;
ne->window = w;
ne->pane = (wp != NULL ? wp->id : -1);
ne->pane = (wp != NULL ? (int)wp->id : -1);
ne->pbname = (pbname != NULL ? xstrdup(pbname) : NULL);
ne->formats = format_create(NULL, NULL, 0, FORMAT_NOJOBS);
@ -240,7 +240,7 @@ notify_hook(struct cmdq_item *item, const char *name)
ne.client = cmdq_get_client(item);
ne.session = target->s;
ne.window = target->w;
ne.pane = (target->wp != NULL ? target->wp->id : -1);
ne.pane = (target->wp != NULL ? (int)target->wp->id : -1);
ne.formats = format_create(NULL, NULL, 0, FORMAT_NOJOBS);
format_add(ne.formats, "hook", "%s", name);

View File

@ -787,6 +787,8 @@ popup_editor(struct client *c, const char *buf, size_t len,
if (fd == -1)
return (-1);
f = fdopen(fd, "w");
if (f == NULL)
return (-1);
if (fwrite(buf, len, 1, f) != 1) {
fclose(f);
return (-1);

View File

@ -24,7 +24,7 @@
#include "tmux.h"
static void
regsub_copy(char **buf, size_t *len, const char *text, size_t start, size_t end)
regsub_copy(char **buf, ssize_t *len, const char *text, size_t start, size_t end)
{
size_t add = end - start;
@ -34,7 +34,7 @@ regsub_copy(char **buf, size_t *len, const char *text, size_t start, size_t end)
}
static void
regsub_expand(char **buf, size_t *len, const char *with, const char *text,
regsub_expand(char **buf, ssize_t *len, const char *with, const char *text,
regmatch_t *m, u_int n)
{
const char *cp;

View File

@ -326,7 +326,9 @@ screen_write_reset(struct screen_write_ctx *ctx)
screen_reset_tabs(s);
screen_write_scrollregion(ctx, 0, screen_size_y(s) - 1);
s->mode = MODE_CURSOR | MODE_WRAP;
s->mode = MODE_CURSOR|MODE_WRAP;
if (options_get_number(global_options, "extended-keys") == 2)
s->mode |= MODE_KEXTENDED;
screen_write_clearscreen(ctx, 8);
screen_write_set_cursor(ctx, 0, 0);

View File

@ -642,7 +642,7 @@ screen_alternate_off(struct screen *s, struct grid_cell *gc, int cursor)
* before copying back.
*/
if (s->saved_grid != NULL)
screen_resize(s, s->saved_grid->sx, s->saved_grid->sy, 1);
screen_resize(s, s->saved_grid->sx, s->saved_grid->sy, 0);
/*
* Restore the cursor position and cell. This happens even if not

View File

@ -737,9 +737,12 @@ session_renumber_windows(struct session *s)
memcpy(&old_lastw, &s->lastw, sizeof old_lastw);
TAILQ_INIT(&s->lastw);
TAILQ_FOREACH(wl, &old_lastw, sentry) {
wl->flags &= ~WINLINK_VISITED;
wl_new = winlink_find_by_window(&s->windows, wl->window);
if (wl_new != NULL)
if (wl_new != NULL) {
TAILQ_INSERT_TAIL(&s->lastw, wl_new, sentry);
wl_new->flags |= WINLINK_VISITED;
}
}
/* Set the current window. */

View File

@ -113,6 +113,7 @@ spawn_window(struct spawn_context *sc, char **cause)
window_pane_resize(sc->wp0, w->sx, w->sy);
layout_init(w, sc->wp0);
w->active = NULL;
window_set_active_pane(w, sc->wp0, 0);
}
@ -428,8 +429,8 @@ spawn_pane(struct spawn_context *sc, char **cause)
_exit(1);
/* Clean up file descriptors and signals and update the environment. */
closefrom(STDERR_FILENO + 1);
proc_clear_signals(server_proc, 1);
closefrom(STDERR_FILENO + 1);
sigprocmask(SIG_SETMASK, &oldset, NULL);
log_close();
environ_push(child);

15
style.c
View File

@ -77,6 +77,7 @@ style_parse(struct style *sy, const struct grid_cell *base, const char *in)
if (strcasecmp(tmp, "default") == 0) {
sy->gc.fg = base->fg;
sy->gc.bg = base->bg;
sy->gc.us = base->us;
sy->gc.attr = base->attr;
sy->gc.flags = base->flags;
} else if (strcasecmp(tmp, "ignore") == 0)
@ -162,6 +163,13 @@ style_parse(struct style *sy, const struct grid_cell *base, const char *in)
sy->gc.bg = base->bg;
} else
goto error;
} else if (end > 3 && strncasecmp(tmp, "us=", 3) == 0) {
if ((value = colour_fromstring(tmp + 3)) == -1)
goto error;
if (value != 8)
sy->gc.us = value;
else
sy->gc.us = base->us;
} else if (strcasecmp(tmp, "none") == 0)
sy->gc.attr = 0;
else if (end > 2 && strncasecmp(tmp, "no", 2) == 0) {
@ -258,6 +266,11 @@ style_tostring(struct style *sy)
colour_tostring(gc->bg));
comma = ",";
}
if (gc->us != 8) {
off += xsnprintf(s + off, sizeof s - off, "%sus=%s", comma,
colour_tostring(gc->us));
comma = ",";
}
if (gc->attr != 0) {
xsnprintf(s + off, sizeof s - off, "%s%s", comma,
attributes_tostring(gc->attr));
@ -287,6 +300,8 @@ style_add(struct grid_cell *gc, struct options *oo, const char *name,
gc->fg = sy->gc.fg;
if (sy->gc.bg != 8)
gc->bg = sy->gc.bg;
if (sy->gc.us != 8)
gc->us = sy->gc.us;
gc->attr |= sy->gc.attr;
if (ft0 != NULL)

357
tmux.1
View File

@ -1745,91 +1745,266 @@ Key tables may be viewed with the
command.
.Pp
The following commands are supported in copy mode:
.Bl -column "CommandXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" "viXXXXXXXXXX" "emacs" -offset indent
.It Sy "Command" Ta Sy "vi" Ta Sy "emacs"
.It Li "append-selection" Ta "" Ta ""
.It Li "append-selection-and-cancel" Ta "A" Ta ""
.It Li "back-to-indentation" Ta "^" Ta "M-m"
.It Li "begin-selection" Ta "Space" Ta "C-Space"
.It Li "bottom-line" Ta "L" Ta ""
.It Li "cancel" Ta "q" Ta "Escape"
.It Li "clear-selection" Ta "Escape" Ta "C-g"
.It Li "copy-end-of-line [<prefix>]" Ta "" Ta ""
.It Li "copy-end-of-line-and-cancel [<prefix>]" Ta "" Ta ""
.It Li "copy-pipe-end-of-line [<command>] [<prefix>]" Ta "" Ta ""
.It Li "copy-pipe-end-of-line-and-cancel [<command>] [<prefix>]" Ta "D" Ta "C-k"
.It Li "copy-line [<prefix>]" Ta "" Ta ""
.It Li "copy-line-and-cancel [<prefix>]" Ta "" Ta ""
.It Li "copy-pipe-line [<command>] [<prefix>]" Ta "" Ta ""
.It Li "copy-pipe-line-and-cancel [<command>] [<prefix>]" Ta "" Ta ""
.It Li "copy-pipe [<command>] [<prefix>]" Ta "" Ta ""
.It Li "copy-pipe-no-clear [<command>] [<prefix>]" Ta "" Ta ""
.It Li "copy-pipe-and-cancel [<command>] [<prefix>]" Ta "" Ta ""
.It Li "copy-selection [<prefix>]" Ta "" Ta ""
.It Li "copy-selection-no-clear [<prefix>]" Ta "" Ta ""
.It Li "copy-selection-and-cancel [<prefix>]" Ta "Enter" Ta "M-w"
.It Li "cursor-down" Ta "j" Ta "Down"
.It Li "cursor-down-and-cancel" Ta "" Ta ""
.It Li "cursor-left" Ta "h" Ta "Left"
.It Li "cursor-right" Ta "l" Ta "Right"
.It Li "cursor-up" Ta "k" Ta "Up"
.It Li "end-of-line" Ta "$" Ta "C-e"
.It Li "goto-line <line>" Ta ":" Ta "g"
.It Li "halfpage-down" Ta "C-d" Ta "M-Down"
.It Li "halfpage-down-and-cancel" Ta "" Ta ""
.It Li "halfpage-up" Ta "C-u" Ta "M-Up"
.It Li "history-bottom" Ta "G" Ta "M->"
.It Li "history-top" Ta "g" Ta "M-<"
.It Li "jump-again" Ta ";" Ta ";"
.It Li "jump-backward <to>" Ta "F" Ta "F"
.It Li "jump-forward <to>" Ta "f" Ta "f"
.It Li "jump-reverse" Ta "," Ta ","
.It Li "jump-to-backward <to>" Ta "T" Ta ""
.It Li "jump-to-forward <to>" Ta "t" Ta ""
.It Li "jump-to-mark" Ta "M-x" Ta "M-x"
.It Li "middle-line" Ta "M" Ta "M-r"
.It Li "next-matching-bracket" Ta "%" Ta "M-C-f"
.It Li "next-paragraph" Ta "}" Ta "M-}"
.It Li "next-space" Ta "W" Ta ""
.It Li "next-space-end" Ta "E" Ta ""
.It Li "next-word" Ta "w" Ta ""
.It Li "next-word-end" Ta "e" Ta "M-f"
.It Li "other-end" Ta "o" Ta ""
.It Li "page-down" Ta "C-f" Ta "PageDown"
.It Li "page-down-and-cancel" Ta "" Ta ""
.It Li "page-up" Ta "C-b" Ta "PageUp"
.It Li "pipe [<command>] [<prefix>]" Ta "" Ta ""
.It Li "pipe-no-clear [<command>] [<prefix>]" Ta "" Ta ""
.It Li "pipe-and-cancel [<command>] [<prefix>]" Ta "" Ta ""
.It Li "previous-matching-bracket" Ta "" Ta "M-C-b"
.It Li "previous-paragraph" Ta "{" Ta "M-{"
.It Li "previous-space" Ta "B" Ta ""
.It Li "previous-word" Ta "b" Ta "M-b"
.It Li "rectangle-on" Ta "" Ta ""
.It Li "rectangle-off" Ta "" Ta ""
.It Li "rectangle-toggle" Ta "v" Ta "R"
.It Li "refresh-from-pane" Ta "r" Ta "r"
.It Li "scroll-down" Ta "C-e" Ta "C-Down"
.It Li "scroll-down-and-cancel" Ta "" Ta ""
.It Li "scroll-up" Ta "C-y" Ta "C-Up"
.It Li "search-again" Ta "n" Ta "n"
.It Li "search-backward <for>" Ta "?" Ta ""
.It Li "search-backward-incremental <for>" Ta "" Ta "C-r"
.It Li "search-backward-text <for>" Ta "" Ta ""
.It Li "search-forward <for>" Ta "/" Ta ""
.It Li "search-forward-incremental <for>" Ta "" Ta "C-s"
.It Li "search-forward-text <for>" Ta "" Ta ""
.It Li "scroll-bottom" Ta "" Ta ""
.It Li "scroll-middle" Ta "z" Ta ""
.It Li "scroll-top" Ta "" Ta ""
.It Li "search-reverse" Ta "N" Ta "N"
.It Li "select-line" Ta "V" Ta ""
.It Li "select-word" Ta "" Ta ""
.It Li "set-mark" Ta "X" Ta "X"
.It Li "start-of-line" Ta "0" Ta "C-a"
.It Li "stop-selection" Ta "" Ta ""
.It Li "toggle-position" Ta "P" Ta "P"
.It Li "top-line" Ta "H" Ta "M-R"
.Bl -tag -width Ds
.It Xo
.Ic append-selection
.Xc
Append the selection to the top paste buffer.
.It Xo
.Ic append-selection-and-cancel
(vi: A)
.Xc
Append the selection to the top paste buffer and exit copy mode.
.It Xo
.Ic back-to-indentation
(vi: ^)
(emacs: M-m)
.Xc
Move the cursor back to the indentation.
.It Xo
.Ic begin-selection
(vi: Space)
(emacs: C-Space)
.Xc
Begin selection.
.It Xo
.Ic bottom-line
(vi: L)
.Xc
Move to the bottom line.
.It Xo
.Ic cancel
(vi: q)
(emacs: Escape)
.Xc
Exit copy mode.
.It Xo
.Ic clear-selection
(vi: Escape)
(emacs: C-g)
.Xc
Clear the current selection.
.It Xo
.Ic copy-end-of-line [<prefix>]
.Xc
Copy from the cursor position to the end of the line.
.Ar prefix
is used to name the new paste buffer.
.It Xo
.Ic copy-end-of-line-and-cancel [<prefix>]
.Xc
Copy from the cursor position and exit copy mode.
.It Xo
.Ic copy-line [<prefix>]
.Xc
Copy the entire line.
.It Xo
.Ic copy-line-and-cancel [<prefix>]
.Xc
Copy the entire line and exit copy mode.
.It Xo
.Ic copy-selection [<prefix>]
.Xc
Copies the current selection.
.It Xo
.Ic copy-selection-and-cancel [<prefix>]
(vi: Enter)
(emacs: M-w)
.Xc
Copy the current selection and exit copy mode.
.It Xo
.Ic cursor-down
(vi: j)
(emacs: Down)
.Xc
Move the cursor down.
.It Xo
.Ic cursor-left
(vi: h)
(emacs: Left)
.Xc
Move the cursor left.
.It Xo
.Ic cursor-right
(vi: l)
(emacs: Right)
.Xc
Move the cursor right.
.It Xo
.Ic cursor-up
(vi: k)
(emacs: Up)
.Xc
Move the cursor up.
.It Xo
.Ic end-of-line
(vi: $)
(emacs: C-e)
.Xc
Move the cursor to the end of the line.
.It Xo
.Ic goto-line <line>
(vi: :)
(emacs: g)
.Xc
Move the cursor to a specific line.
.It Xo
.Ic history-bottom
(vi: G)
(emacs: M->)
.Xc
Scroll to the bottom of the history.
.It Xo
.Ic history-top
(vi: g)
(emacs: M-<)
.Xc
Scroll to the top of the history.
.It Xo
.Ic jump-again
(vi: ;)
(emacs: ;)
.Xc
Repeat the last jump.
.It Xo
.Ic jump-backward <to>
(vi: F)
(emacs: F)
.Xc
Jump backwards to the specified text.
.It Xo
.Ic jump-forward <to>
(vi: f)
(emacs: f)
.Xc
Jump forward to the specified text.
.It Xo
.Ic jump-to-mark
(vi: M-x)
(emacs: M-x)
.Xc
Jump to the last mark.
.It Xo
.Ic middle-line
(vi: M)
(emacs: M-r)
.Xc
Move to the middle line.
.It Xo
.Ic next-matching-bracket
(vi: %)
(emacs: M-C-f)
.Xc
Move to the next matching bracket.
.It Xo
.Ic next-paragraph
(vi: })
(emacs: M-})
.Xc
Move to the next paragraph.
.It Xo
.Ic next-prompt
.Xc
Move to the next prompt.
.It Xo
.Ic next-word
(vi: w)
.Xc
Move to the next word.
.It Xo
.Ic page-down
(vi: C-f)
(emacs: PageDown)
.Xc
Scroll down by one page.
.It Xo
.Ic page-up
(vi: C-b)
(emacs: PageUp)
.Xc
Scroll up by one page.
.It Xo
.Ic previous-matching-bracket
(emacs: M-C-b)
.Xc
Move to the previous matching bracket.
.It Xo
.Ic previous-paragraph
(vi: {)
(emacs: M-{)
.Xc
Move to the previous paragraph.
.It Xo
.Ic previous-prompt
.Xc
Move to the previous prompt.
.It Xo
.Ic previous-word
(vi: b)
(emacs: M-b)
.Xc
Move to the previous word.
.It Xo
.Ic rectangle-toggle
(vi: v)
(emacs: R)
.Xc
Toggle rectangle selection mode.
.It Xo
.Ic refresh-from-pane
(vi: r)
(emacs: r)
.Xc
Refresh the content from the pane.
.It Xo
.Ic search-again
(vi: n)
(emacs: n)
.Xc
Repeat the last search.
.It Xo
.Ic search-backward <for>
(vi: ?)
.Xc
Search backwards for the specified text.
.It Xo
.Ic search-forward <for>
(vi: /)
.Xc
Search forward for the specified text.
.It Xo
.Ic select-line
(vi: V)
.Xc
Select the current line.
.It Xo
.Ic select-word
.Xc
Select the current word.
.It Xo
.Ic start-of-line
(vi: 0)
(emacs: C-a)
.Xc
Move the cursor to the start of the line.
.It Xo
.Ic top-line
(vi: H)
(emacs: M-R)
.Xc
Move to the top line.
.It Xo
.Ic next-prompt
(vi: C-n)
(emacs: C-n)
.Xc
Move to the next prompt.
.It Xo
.Ic previous-prompt
(vi: C-p)
(emacs: C-p)
.Xc
Move to the previous prompt.
.El
.Pp
The search commands come in several varieties:
@ -1852,6 +2027,16 @@ repeats the last search and
does the same but reverses the direction (forward becomes backward and backward
becomes forward).
.Pp
The
.Ql next-prompt
and
.Ql previous-prompt
move between shell prompts, but require the shell to emit an escape sequence
(\e033]133;A\e033\e\e) to tell
.Nm
where the prompts are located; if the shell does not do this, these commands
will do nothing.
.Pp
Copy commands may take an optional buffer prefix argument which is used
to generate the buffer name (the default is
.Ql buffer
@ -5387,6 +5572,8 @@ for the terminal default colour; or a hexadecimal RGB string such as
.Ql #ffffff .
.It Ic bg=colour
Set the background colour.
.It Ic us=colour
Set the underscore colour.
.It Ic none
Set no attributes (turn off any active attributes).
.It Xo Ic acs ,

13
tmux.h
View File

@ -680,6 +680,7 @@ struct colour_palette {
#define GRID_LINE_WRAPPED 0x1
#define GRID_LINE_EXTENDED 0x2
#define GRID_LINE_DEAD 0x4
#define GRID_LINE_START_PROMPT 0x8
/* Grid string flags. */
#define GRID_STRING_WITH_SEQUENCES 0x1
@ -1068,7 +1069,7 @@ struct window_pane {
#define PANE_REDRAW 0x1
#define PANE_DROP 0x2
#define PANE_FOCUSED 0x4
/* 0x8 unused */
#define PANE_VISITED 0x8
/* 0x10 unused */
/* 0x20 unused */
#define PANE_INPUTOFF 0x40
@ -1123,7 +1124,8 @@ struct window_pane {
int border_gc_set;
struct grid_cell border_gc;
TAILQ_ENTRY(window_pane) entry;
TAILQ_ENTRY(window_pane) entry; /* link in list of all panes */
TAILQ_ENTRY(window_pane) sentry; /* link in list of last visited */
RB_ENTRY(window_pane) tree_entry;
};
TAILQ_HEAD(window_panes, window_pane);
@ -1144,7 +1146,7 @@ struct window {
struct timeval activity_time;
struct window_pane *active;
struct window_pane *last;
struct window_panes last_panes;
struct window_panes panes;
int lastlayout;
@ -1197,6 +1199,7 @@ struct winlink {
#define WINLINK_ACTIVITY 0x2
#define WINLINK_SILENCE 0x4
#define WINLINK_ALERTFLAGS (WINLINK_BELL|WINLINK_ACTIVITY|WINLINK_SILENCE)
#define WINLINK_VISITED 0x8
RB_ENTRY(winlink) entry;
TAILQ_ENTRY(winlink) wentry;
@ -3090,6 +3093,10 @@ struct window_pane *window_pane_find_up(struct window_pane *);
struct window_pane *window_pane_find_down(struct window_pane *);
struct window_pane *window_pane_find_left(struct window_pane *);
struct window_pane *window_pane_find_right(struct window_pane *);
void window_pane_stack_push(struct window_panes *,
struct window_pane *);
void window_pane_stack_remove(struct window_panes *,
struct window_pane *);
void window_set_name(struct window *, const char *);
void window_add_ref(struct window *, const char *);
void window_remove_ref(struct window *, const char *);

View File

@ -1160,7 +1160,7 @@ tty_keys_clipboard(struct tty *tty, const char *buf, size_t len, size_t *size)
{
struct client *c = tty->client;
struct window_pane *wp;
size_t end, terminator, needed;
size_t end, terminator = 0, needed;
char *copy, *out;
int outlen;
u_int i;

View File

@ -718,7 +718,7 @@ tty_term_read_list(const char *name, int fd, char ***caps, u_int *ncaps,
s = tmp;
break;
case TTYCODE_FLAG:
n = tigetflag((char *) ent->name);
n = tigetflag((char *)ent->name);
if (n == -1)
continue;
if (n)
@ -726,6 +726,8 @@ tty_term_read_list(const char *name, int fd, char ***caps, u_int *ncaps,
else
s = "0";
break;
default:
fatalx("unknown capability type");
}
*caps = xreallocarray(*caps, (*ncaps) + 1, sizeof **caps);
xasprintf(&(*caps)[*ncaps], "%s=%s", ent->name, s);

17
tty.c
View File

@ -488,10 +488,11 @@ tty_update_features(struct tty *tty)
if (tty->term->flags & TERM_VT100LIKE)
tty_puts(tty, "\033[?7727h");
/* tty features might have changed since the first draw during attach.
* For example, this happens when DA responses are received.
/*
* Features might have changed since the first draw during attach. For
* example, this happens when DA responses are received.
*/
c->flags |= CLIENT_REDRAWWINDOW;
server_redraw_client(c);
tty_invalidate(tty);
}
@ -2935,9 +2936,11 @@ tty_check_us(__unused struct tty *tty, struct colour_palette *palette,
gc->us = c;
}
/* Underscore colour is set as RGB so convert a 256 colour to RGB. */
if (gc->us & COLOUR_FLAG_256)
gc->us = colour_256toRGB (gc->us);
/* Underscore colour is set as RGB so convert. */
if ((c = colour_force_rgb (gc->us)) == -1)
gc->us = 8;
else
gc->us = c;
}
static void
@ -3012,7 +3015,7 @@ tty_colours_us(struct tty *tty, const struct grid_cell *gc)
u_char r, g, b;
/* Clear underline colour. */
if (gc->us == 0) {
if (COLOUR_DEFAULT(gc->us)) {
tty_putcode(tty, TTYC_OL);
goto save;
}

4
utf8.c
View File

@ -71,7 +71,7 @@ static u_int utf8_next_index;
/* Get a UTF-8 item from data. */
static struct utf8_item *
utf8_item_by_data(const char *data, size_t size)
utf8_item_by_data(const u_char *data, size_t size)
{
struct utf8_item ui;
@ -94,7 +94,7 @@ utf8_item_by_index(u_int index)
/* Add a UTF-8 item. */
static int
utf8_put_item(const char *data, size_t size, u_int *index)
utf8_put_item(const u_char *data, size_t size, u_int *index)
{
struct utf8_item *ui;

View File

@ -131,6 +131,7 @@ static void window_copy_cursor_previous_word_pos(struct window_mode_entry *,
const char *, u_int *, u_int *);
static void window_copy_cursor_previous_word(struct window_mode_entry *,
const char *, int);
static void window_copy_cursor_prompt(struct window_mode_entry *, int);
static void window_copy_scroll_up(struct window_mode_entry *, u_int);
static void window_copy_scroll_down(struct window_mode_entry *, u_int);
static void window_copy_rectangle_set(struct window_mode_entry *, int);
@ -2240,6 +2241,24 @@ window_copy_cmd_jump_to_mark(struct window_copy_cmd_state *cs)
return (WINDOW_COPY_CMD_NOTHING);
}
static enum window_copy_cmd_action
window_copy_cmd_next_prompt(struct window_copy_cmd_state *cs)
{
struct window_mode_entry *wme = cs->wme;
window_copy_cursor_prompt(wme, 1);
return (WINDOW_COPY_CMD_NOTHING);
}
static enum window_copy_cmd_action
window_copy_cmd_previous_prompt(struct window_copy_cmd_state *cs)
{
struct window_mode_entry *wme = cs->wme;
window_copy_cursor_prompt(wme, 0);
return (WINDOW_COPY_CMD_NOTHING);
}
static enum window_copy_cmd_action
window_copy_cmd_search_backward(struct window_copy_cmd_state *cs)
{
@ -2694,6 +2713,18 @@ static const struct {
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
.f = window_copy_cmd_jump_to_mark
},
{ .command = "next-prompt",
.minargs = 0,
.maxargs = 0,
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
.f = window_copy_cmd_next_prompt
},
{ .command = "previous-prompt",
.minargs = 0,
.maxargs = 0,
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
.f = window_copy_cmd_previous_prompt
},
{ .command = "middle-line",
.minargs = 0,
.maxargs = 0,
@ -5357,6 +5388,48 @@ window_copy_cursor_previous_word(struct window_mode_entry *wme,
window_copy_acquire_cursor_up(wme, hsize, data->oy, oldy, px, py);
}
static void
window_copy_cursor_prompt(struct window_mode_entry *wme, int direction)
{
struct window_copy_mode_data *data = wme->data;
struct screen *s = data->backing;
struct grid *gd = s->grid;
u_int end_line;
u_int line = gd->hsize - data->oy + data->cy;
int add;
if (direction == 0) { /* up */
add = -1;
end_line = 0;
} else { /* down */
add = 1;
end_line = gd->hsize + gd->sy - 1;
}
if (line == end_line)
return;
for (;;) {
if (line == end_line)
return;
line += add;
if (grid_get_line(gd, line)->flags & GRID_LINE_START_PROMPT)
break;
}
data->cx = 0;
if (line > gd->hsize) {
data->cy = line - gd->hsize;
data->oy = 0;
} else {
data->cy = 0;
data->oy = gd->hsize - line;
}
window_copy_update_selection(wme, 1, 0);
window_copy_redraw_screen(wme);
}
static void
window_copy_scroll_up(struct window_mode_entry *wme, u_int ny)
{

View File

@ -671,9 +671,9 @@ window_tree_draw_window(struct window_tree_modedata *data, struct session *s,
struct window_pane *wp;
u_int cx = ctx->s->cx, cy = ctx->s->cy;
u_int loop, total, visible, each, width, offset;
u_int current, start, end, remaining, i;
u_int current, start, end, remaining, i, pane_idx;
struct grid_cell gc;
int colour, active_colour, left, right, pane_idx;
int colour, active_colour, left, right;
char *label;
total = window_count_panes(w);

View File

@ -246,21 +246,15 @@ winlink_stack_push(struct winlink_stack *stack, struct winlink *wl)
winlink_stack_remove(stack, wl);
TAILQ_INSERT_HEAD(stack, wl, sentry);
wl->flags |= WINLINK_VISITED;
}
void
winlink_stack_remove(struct winlink_stack *stack, struct winlink *wl)
{
struct winlink *wl2;
if (wl == NULL)
return;
TAILQ_FOREACH(wl2, stack, sentry) {
if (wl2 == wl) {
TAILQ_REMOVE(stack, wl, sentry);
return;
}
if (wl != NULL && (wl->flags & WINLINK_VISITED)) {
TAILQ_REMOVE(stack, wl, sentry);
wl->flags &= ~WINLINK_VISITED;
}
}
@ -310,6 +304,7 @@ window_create(u_int sx, u_int sy, u_int xpixel, u_int ypixel)
w->flags = 0;
TAILQ_INIT(&w->panes);
TAILQ_INIT(&w->last_panes);
w->active = NULL;
w->lastlayout = -1;
@ -519,18 +514,23 @@ window_pane_update_focus(struct window_pane *wp)
int
window_set_active_pane(struct window *w, struct window_pane *wp, int notify)
{
struct window_pane *lastwp;
log_debug("%s: pane %%%u", __func__, wp->id);
if (wp == w->active)
return (0);
w->last = w->active;
lastwp = w->active;
window_pane_stack_remove(&w->last_panes, wp);
window_pane_stack_push(&w->last_panes, lastwp);
w->active = wp;
w->active->active_point = next_active_point++;
w->active->flags |= PANE_CHANGED;
if (options_get_number(global_options, "focus-events")) {
window_pane_update_focus(w->last);
window_pane_update_focus(lastwp);
window_pane_update_focus(w->active);
}
@ -753,21 +753,21 @@ window_lost_pane(struct window *w, struct window_pane *wp)
if (wp == marked_pane.wp)
server_clear_marked();
window_pane_stack_remove(&w->last_panes, wp);
if (wp == w->active) {
w->active = w->last;
w->last = NULL;
w->active = TAILQ_FIRST(&w->last_panes);
if (w->active == NULL) {
w->active = TAILQ_PREV(wp, window_panes, entry);
if (w->active == NULL)
w->active = TAILQ_NEXT(wp, entry);
}
if (w->active != NULL) {
window_pane_stack_remove(&w->last_panes, w->active);
w->active->flags |= PANE_CHANGED;
notify_window("window-pane-changed", w);
window_update_focus(w);
}
} else if (wp == w->last)
w->last = NULL;
}
}
void
@ -851,6 +851,11 @@ window_destroy_panes(struct window *w)
{
struct window_pane *wp;
while (!TAILQ_EMPTY(&w->last_panes)) {
wp = TAILQ_FIRST(&w->last_panes);
window_pane_stack_remove(&w->last_panes, wp);
}
while (!TAILQ_EMPTY(&w->panes)) {
wp = TAILQ_FIRST(&w->panes);
TAILQ_REMOVE(&w->panes, wp, entry);
@ -1488,6 +1493,25 @@ window_pane_find_right(struct window_pane *wp)
return (best);
}
void
window_pane_stack_push(struct window_panes *stack, struct window_pane *wp)
{
if (wp != NULL) {
window_pane_stack_remove(stack, wp);
TAILQ_INSERT_HEAD(stack, wp, sentry);
wp->flags |= PANE_VISITED;
}
}
void
window_pane_stack_remove(struct window_panes *stack, struct window_pane *wp)
{
if (wp != NULL && (wp->flags & PANE_VISITED)) {
TAILQ_REMOVE(stack, wp, sentry);
wp->flags &= ~PANE_VISITED;
}
}
/* Clear alert flags for a winlink */
void
winlink_clear_flags(struct winlink *wl)