diff --git a/client.c b/client.c index 4bec9f1d..26e48df3 100644 --- a/client.c +++ b/client.c @@ -452,11 +452,12 @@ client_send_identify(const char *ttynam, const char *termname, char **caps, { char **ss; size_t sslen; - int fd, flags = client_flags; + int fd; + uint64_t flags = client_flags; pid_t pid; u_int i; - proc_send(client_peer, MSG_IDENTIFY_FLAGS, -1, &flags, sizeof flags); + proc_send(client_peer, MSG_IDENTIFY_LONGFLAGS, -1, &flags, sizeof flags); proc_send(client_peer, MSG_IDENTIFY_LONGFLAGS, -1, &client_flags, sizeof client_flags); diff --git a/cmd-copy-mode.c b/cmd-copy-mode.c index 8f698ce8..5e9b444e 100644 --- a/cmd-copy-mode.c +++ b/cmd-copy-mode.c @@ -30,8 +30,8 @@ const struct cmd_entry cmd_copy_mode_entry = { .name = "copy-mode", .alias = NULL, - .args = { "eHMs:t:uq", 0, 0, NULL }, - .usage = "[-eHMuq] [-s src-pane] " CMD_TARGET_PANE_USAGE, + .args = { "deHMs:t:uq", 0, 0, NULL }, + .usage = "[-deHMuq] [-s src-pane] " CMD_TARGET_PANE_USAGE, .source = { 's', CMD_FIND_PANE, 0 }, .target = { 't', CMD_FIND_PANE, 0 }, @@ -91,6 +91,8 @@ cmd_copy_mode_exec(struct cmd *self, struct cmdq_item *item) } if (args_has(args, 'u')) window_copy_pageup(wp, 0); + if (args_has(args, 'd')) + window_copy_pagedown(wp, 0, args_has(args, 'e')); return (CMD_RETURN_NORMAL); } diff --git a/colour.c b/colour.c index 9bde646f..0b787acb 100644 --- a/colour.c +++ b/colour.c @@ -942,13 +942,17 @@ colour_byname(const char *name) { "yellow3", 0xcdcd00 }, { "yellow4", 0x8b8b00 } }; - u_int i; - int c; + u_int i; + int c; + const char *errstr; if (strncmp(name, "grey", 4) == 0 || strncmp(name, "gray", 4) == 0) { - if (!isdigit((u_char)name[4])) - return (0xbebebe|COLOUR_FLAG_RGB); - c = round(2.55 * atoi(name + 4)); + if (name[4] == '\0') + return (-1); + c = strtonum(name + 4, 0, 100, &errstr); + if (errstr != NULL) + return (-1); + c = round(2.55 * c); if (c < 0 || c > 255) return (-1); return (colour_join_rgb(c, c, c)); diff --git a/format.c b/format.c index 136360ae..aff72b7c 100644 --- a/format.c +++ b/format.c @@ -1136,8 +1136,7 @@ format_cb_mouse_word(struct format_tree *ft) return (NULL); if (!TAILQ_EMPTY(&wp->modes)) { - if (TAILQ_FIRST(&wp->modes)->mode == &window_copy_mode || - TAILQ_FIRST(&wp->modes)->mode == &window_view_mode) + if (window_pane_mode(wp) != WINDOW_PANE_NO_MODE) return (window_copy_get_word(wp, x, y)); return (NULL); } @@ -1181,8 +1180,7 @@ format_cb_mouse_line(struct format_tree *ft) return (NULL); if (!TAILQ_EMPTY(&wp->modes)) { - if (TAILQ_FIRST(&wp->modes)->mode == &window_copy_mode || - TAILQ_FIRST(&wp->modes)->mode == &window_view_mode) + if (window_pane_mode(wp) != WINDOW_PANE_NO_MODE) return (window_copy_get_line(wp, y)); return (NULL); } diff --git a/hyperlinks.c b/hyperlinks.c index 70c2f4e3..4850b4b8 100644 --- a/hyperlinks.c +++ b/hyperlinks.c @@ -68,6 +68,7 @@ struct hyperlinks { u_int next_inner; struct hyperlinks_by_inner_tree by_inner; struct hyperlinks_by_uri_tree by_uri; + u_int references; }; static int @@ -205,6 +206,15 @@ hyperlinks_init(void) hl->next_inner = 1; RB_INIT(&hl->by_uri); RB_INIT(&hl->by_inner); + hl->references = 1; + return (hl); +} + +/* Copy hyperlink set. */ +struct hyperlinks * +hyperlinks_copy(struct hyperlinks *hl) +{ + hl->references++; return (hl); } @@ -222,6 +232,8 @@ hyperlinks_reset(struct hyperlinks *hl) void hyperlinks_free(struct hyperlinks *hl) { - hyperlinks_reset(hl); - free(hl); + if (--hl->references == 0) { + hyperlinks_reset(hl); + free(hl); + } } diff --git a/input-keys.c b/input-keys.c index 096d356f..4dd42e1b 100644 --- a/input-keys.c +++ b/input-keys.c @@ -607,8 +607,9 @@ input_key(struct screen *s, struct bufferevent *bev, key_code key) * key and no modifiers. */ if (!(key & ~KEYC_MASK_KEY)) { - if (key == C0_BS || key == C0_HT || - key == C0_CR || key == C0_ESC || + if (key == C0_HT || + key == C0_CR || + key == C0_ESC || (key >= 0x20 && key <= 0x7f)) { ud.data[0] = key; input_key_write(__func__, bev, &ud.data[0], 1); diff --git a/screen-redraw.c b/screen-redraw.c index ce79b41f..ce83bdff 100644 --- a/screen-redraw.c +++ b/screen-redraw.c @@ -109,12 +109,13 @@ screen_redraw_two_panes(struct window *w, int direction) /* Check if cell is on the border of a pane. */ static enum screen_redraw_border_type -screen_redraw_pane_border(struct window_pane *wp, u_int px, u_int py, - int pane_status) +screen_redraw_pane_border(struct screen_redraw_ctx *ctx, struct window_pane *wp, + u_int px, u_int py) { struct options *oo = wp->window->options; int split = 0; - u_int ex = wp->xoff + wp->sx, ey = wp->yoff + wp->sy; + u_int ex = wp->xoff + wp->sx, ey = wp->yoff + wp->sy; + int pane_status = ctx->pane_status; /* Inside pane. */ if (px >= wp->xoff && px < ex && py >= wp->yoff && py < ey) @@ -189,8 +190,9 @@ screen_redraw_pane_border(struct window_pane *wp, u_int px, u_int py, /* Check if a cell is on a border. */ static int -screen_redraw_cell_border(struct client *c, u_int px, u_int py, int pane_status) +screen_redraw_cell_border(struct screen_redraw_ctx *ctx, u_int px, u_int py) { + struct client *c = ctx->c; struct window *w = c->session->curw->window; struct window_pane *wp; @@ -206,7 +208,7 @@ screen_redraw_cell_border(struct client *c, u_int px, u_int py, int pane_status) TAILQ_FOREACH(wp, &w->panes, entry) { if (!window_pane_visible(wp)) continue; - switch (screen_redraw_pane_border(wp, px, py, pane_status)) { + switch (screen_redraw_pane_border(ctx, wp, px, py)) { case SCREEN_REDRAW_INSIDE: return (0); case SCREEN_REDRAW_OUTSIDE: @@ -221,9 +223,10 @@ screen_redraw_cell_border(struct client *c, u_int px, u_int py, int pane_status) /* Work out type of border cell from surrounding cells. */ static int -screen_redraw_type_of_cell(struct client *c, u_int px, u_int py, - int pane_status) +screen_redraw_type_of_cell(struct screen_redraw_ctx *ctx, u_int px, u_int py) { + struct client *c = ctx->c; + int pane_status = ctx->pane_status; struct window *w = c->session->curw->window; u_int sx = w->sx, sy = w->sy; int borders = 0; @@ -236,28 +239,28 @@ screen_redraw_type_of_cell(struct client *c, u_int px, u_int py, * Construct a bitmask of whether the cells to the left (bit 4), right, * top, and bottom (bit 1) of this cell are borders. */ - if (px == 0 || screen_redraw_cell_border(c, px - 1, py, pane_status)) + if (px == 0 || screen_redraw_cell_border(ctx, px - 1, py)) borders |= 8; - if (px <= sx && screen_redraw_cell_border(c, px + 1, py, pane_status)) + if (px <= sx && screen_redraw_cell_border(ctx, px + 1, py)) borders |= 4; if (pane_status == PANE_STATUS_TOP) { if (py != 0 && - screen_redraw_cell_border(c, px, py - 1, pane_status)) + screen_redraw_cell_border(ctx, px, py - 1)) borders |= 2; - if (screen_redraw_cell_border(c, px, py + 1, pane_status)) + if (screen_redraw_cell_border(ctx, px, py + 1)) borders |= 1; } else if (pane_status == PANE_STATUS_BOTTOM) { if (py == 0 || - screen_redraw_cell_border(c, px, py - 1, pane_status)) + screen_redraw_cell_border(ctx, px, py - 1)) borders |= 2; if (py != sy - 1 && - screen_redraw_cell_border(c, px, py + 1, pane_status)) + screen_redraw_cell_border(ctx, px, py + 1)) borders |= 1; } else { if (py == 0 || - screen_redraw_cell_border(c, px, py - 1, pane_status)) + screen_redraw_cell_border(ctx, px, py - 1)) borders |= 2; - if (screen_redraw_cell_border(c, px, py + 1, pane_status)) + if (screen_redraw_cell_border(ctx, px, py + 1)) borders |= 1; } @@ -295,11 +298,13 @@ screen_redraw_type_of_cell(struct client *c, u_int px, u_int py, /* Check if cell inside a pane. */ static int -screen_redraw_check_cell(struct client *c, u_int px, u_int py, int pane_status, +screen_redraw_check_cell(struct screen_redraw_ctx *ctx, u_int px, u_int py, struct window_pane **wpp) { + struct client *c = ctx->c; struct window *w = c->session->curw->window; struct window_pane *wp, *active; + int pane_status = ctx->pane_status; int border; u_int right, line; @@ -308,7 +313,7 @@ screen_redraw_check_cell(struct client *c, u_int px, u_int py, int pane_status, if (px > w->sx || py > w->sy) return (CELL_OUTSIDE); if (px == w->sx || py == w->sy) /* window border */ - return (screen_redraw_type_of_cell(c, px, py, pane_status)); + return (screen_redraw_type_of_cell(ctx, px, py)); if (pane_status != PANE_STATUS_OFF) { active = wp = server_client_get_pane(c); @@ -342,12 +347,12 @@ screen_redraw_check_cell(struct client *c, u_int px, u_int py, int pane_status, * If definitely inside, return. If not on border, skip. * Otherwise work out the cell. */ - border = screen_redraw_pane_border(wp, px, py, pane_status); + border = screen_redraw_pane_border(ctx, wp, px, py); if (border == SCREEN_REDRAW_INSIDE) return (CELL_INSIDE); if (border == SCREEN_REDRAW_OUTSIDE) goto next2; - return (screen_redraw_type_of_cell(c, px, py, pane_status)); + return (screen_redraw_type_of_cell(ctx, px, py)); next2: wp = TAILQ_NEXT(wp, entry); @@ -360,12 +365,12 @@ screen_redraw_check_cell(struct client *c, u_int px, u_int py, int pane_status, /* Check if the border of a particular pane. */ static int -screen_redraw_check_is(u_int px, u_int py, int pane_status, +screen_redraw_check_is(struct screen_redraw_ctx *ctx, u_int px, u_int py, struct window_pane *wp) { enum screen_redraw_border_type border; - border = screen_redraw_pane_border(wp, px, py, pane_status); + border = screen_redraw_pane_border(ctx, wp, px, py); if (border != SCREEN_REDRAW_INSIDE && border != SCREEN_REDRAW_OUTSIDE) return (1); return (0); @@ -409,11 +414,11 @@ screen_redraw_make_pane_status(struct client *c, struct window_pane *wp, for (i = 0; i < width; i++) { px = wp->xoff + 2 + i; - if (rctx->pane_status == PANE_STATUS_TOP) + if (pane_status == PANE_STATUS_TOP) py = wp->yoff - 1; else py = wp->yoff + wp->sy; - cell_type = screen_redraw_type_of_cell(c, px, py, pane_status); + cell_type = screen_redraw_type_of_cell(rctx, px, py); screen_redraw_border_set(w, wp, pane_lines, cell_type, &gc); screen_write_cell(&ctx, &gc); } @@ -496,8 +501,8 @@ screen_redraw_draw_pane_status(struct screen_redraw_ctx *ctx) } /* Update status line and change flags if unchanged. */ -static int -screen_redraw_update(struct client *c, int flags) +static uint64_t +screen_redraw_update(struct client *c, uint64_t flags) { struct window *w = c->session->curw->window; struct window_pane *wp; @@ -567,7 +572,7 @@ void screen_redraw_screen(struct client *c) { struct screen_redraw_ctx ctx; - int flags; + uint64_t flags; if (c->flags & CLIENT_SUSPENDED) return; @@ -638,7 +643,7 @@ screen_redraw_draw_borders_style(struct screen_redraw_ctx *ctx, u_int x, wp->border_gc_set = 1; ft = format_create_defaults(NULL, c, s, s->curw, wp); - if (screen_redraw_check_is(x, y, ctx->pane_status, active)) + if (screen_redraw_check_is(ctx, x, y, active)) style_apply(&wp->border_gc, oo, "pane-active-border-style", ft); else style_apply(&wp->border_gc, oo, "pane-border-style", ft); @@ -663,7 +668,7 @@ screen_redraw_draw_borders_cell(struct screen_redraw_ctx *ctx, u_int i, u_int j) struct overlay_ranges r; u_int cell_type, x = ctx->ox + i, y = ctx->oy + j; int arrows = 0, border; - int pane_status = ctx->pane_status, isolates; + int isolates; if (c->overlay_check != NULL) { c->overlay_check(c, c->overlay_data, x, y, 1, &r); @@ -671,7 +676,7 @@ screen_redraw_draw_borders_cell(struct screen_redraw_ctx *ctx, u_int i, u_int j) return; } - cell_type = screen_redraw_check_cell(c, x, y, pane_status, &wp); + cell_type = screen_redraw_check_cell(ctx, x, y, &wp); if (cell_type == CELL_INSIDE) return; @@ -692,7 +697,7 @@ screen_redraw_draw_borders_cell(struct screen_redraw_ctx *ctx, u_int i, u_int j) memcpy(&gc, tmp, sizeof gc); if (server_is_marked(s, s->curw, marked_pane.wp) && - screen_redraw_check_is(x, y, pane_status, marked_pane.wp)) + screen_redraw_check_is(ctx, x, y, marked_pane.wp)) gc.attr ^= GRID_ATTR_REVERSE; } screen_redraw_border_set(w, wp, ctx->pane_lines, cell_type, &gc); @@ -719,7 +724,7 @@ screen_redraw_draw_borders_cell(struct screen_redraw_ctx *ctx, u_int i, u_int j) } if (wp != NULL && arrows) { - border = screen_redraw_pane_border(active, x, y, pane_status); + border = screen_redraw_pane_border(ctx, active, x, y); if (((i == wp->xoff + 1 && (cell_type == CELL_LEFTRIGHT || (cell_type == CELL_TOPJOIN && @@ -732,7 +737,7 @@ screen_redraw_draw_borders_cell(struct screen_redraw_ctx *ctx, u_int i, u_int j) border == SCREEN_REDRAW_BORDER_RIGHT) || (cell_type == CELL_RIGHTJOIN && border == SCREEN_REDRAW_BORDER_LEFT)))) && - screen_redraw_check_is(x, y, pane_status, active)) { + screen_redraw_check_is(ctx, x, y, active)) { gc.attr |= GRID_ATTR_CHARSET; utf8_set(&gc.data, BORDER_MARKERS[border]); } @@ -751,7 +756,7 @@ screen_redraw_draw_borders(struct screen_redraw_ctx *ctx) struct session *s = c->session; struct window *w = s->curw->window; struct window_pane *wp; - u_int i, j; + u_int i, j; log_debug("%s: %s @%u", __func__, c->name, w->id); diff --git a/server-client.c b/server-client.c index 449a9bcc..75c15459 100644 --- a/server-client.c +++ b/server-client.c @@ -779,8 +779,7 @@ have_event: log_debug("mouse on pane %%%u border", wp->id); m->wp = wp->id; m->w = wp->window->id; - } else - m->wp = -1; + } /* Stop dragging if needed. */ if (type != DRAG && type != WHEEL && c->tty.mouse_drag_flag != 0) { @@ -1866,7 +1865,8 @@ server_client_key_callback(struct cmdq_item *item, void *data) struct timeval tv; struct key_table *table, *first; struct key_binding *bd; - int xtimeout, flags; + int xtimeout; + uint64_t flags; struct cmd_find_state fs; key_code key0, prefix, prefix2; @@ -2565,7 +2565,8 @@ server_client_check_redraw(struct client *c) struct tty *tty = &c->tty; struct window *w = c->session->curw->window; struct window_pane *wp; - int needed, flags, mode = tty->mode, new_flags = 0; + int needed, tty_flags, mode = tty->mode; + uint64_t client_flags = 0; int redraw; u_int bit = 0; struct timeval tv = { .tv_usec = 1000 }; @@ -2599,7 +2600,7 @@ server_client_check_redraw(struct client *c) } } if (needed) - new_flags |= CLIENT_REDRAWPANES; + client_flags |= CLIENT_REDRAWPANES; } if (needed && (left = EVBUFFER_LENGTH(tty->out)) != 0) { log_debug("%s: redraw deferred (%zu left)", c->name, left); @@ -2622,20 +2623,20 @@ server_client_check_redraw(struct client *c) * If more that 64 panes, give up and * just redraw the window. */ - new_flags &= CLIENT_REDRAWPANES; - new_flags |= CLIENT_REDRAWWINDOW; + client_flags &= CLIENT_REDRAWPANES; + client_flags |= CLIENT_REDRAWWINDOW; break; } } if (c->redraw_panes != 0) c->flags |= CLIENT_REDRAWPANES; } - c->flags |= new_flags; + c->flags |= client_flags; return; } else if (needed) log_debug("%s: redraw needed", c->name); - flags = tty->flags & (TTY_BLOCK|TTY_FREEZE|TTY_NOCURSOR); + tty_flags = tty->flags & (TTY_BLOCK|TTY_FREEZE|TTY_NOCURSOR); tty->flags = (tty->flags & ~(TTY_BLOCK|TTY_FREEZE))|TTY_NOCURSOR; if (~c->flags & CLIENT_REDRAWWINDOW) { @@ -2667,9 +2668,10 @@ server_client_check_redraw(struct client *c) screen_redraw_screen(c); } - tty->flags = (tty->flags & ~TTY_NOCURSOR)|(flags & TTY_NOCURSOR); + tty->flags = (tty->flags & ~TTY_NOCURSOR)|(tty_flags & TTY_NOCURSOR); tty_update_mode(tty, mode, NULL); - tty->flags = (tty->flags & ~(TTY_BLOCK|TTY_FREEZE|TTY_NOCURSOR))|flags; + tty->flags = (tty->flags & ~(TTY_BLOCK|TTY_FREEZE|TTY_NOCURSOR))| + tty_flags; c->flags &= ~(CLIENT_ALLREDRAWFLAGS|CLIENT_STATUSFORCE); diff --git a/server.c b/server.c index 96a638cb..18d0df10 100644 --- a/server.c +++ b/server.c @@ -103,7 +103,7 @@ server_check_marked(void) /* Create server socket. */ int -server_create_socket(int flags, char **cause) +server_create_socket(uint64_t flags, char **cause) { struct sockaddr_un sa; size_t size; @@ -172,7 +172,7 @@ server_tidy_event(__unused int fd, __unused short events, __unused void *data) /* Fork new server. */ int -server_start(struct tmuxproc *client, int flags, struct event_base *base, +server_start(struct tmuxproc *client, uint64_t flags, struct event_base *base, int lockfd, char *lockfile) { int fd; diff --git a/style.c b/style.c index 35293a10..9d7c585d 100644 --- a/style.c +++ b/style.c @@ -58,10 +58,11 @@ int style_parse(struct style *sy, const struct grid_cell *base, const char *in) { struct style saved; - const char delimiters[] = " ,\n", *cp; + const char delimiters[] = " ,\n", *errstr; char tmp[256], *found; int value; size_t end; + u_int n; if (*in == '\0') return (0); @@ -137,34 +138,31 @@ style_parse(struct style *sy, const struct grid_cell *base, const char *in) goto error; if (*found != '%' || found[1] == '\0') goto error; - for (cp = found + 1; *cp != '\0'; cp++) { - if (!isdigit((u_char)*cp)) - goto error; - } + n = strtonum(found + 1, 0, UINT_MAX, &errstr); + if (errstr != NULL) + goto error; sy->range_type = STYLE_RANGE_PANE; - sy->range_argument = atoi(found + 1); + sy->range_argument = n; style_set_range_string(sy, ""); } else if (strcasecmp(tmp + 6, "window") == 0) { if (found == NULL) goto error; - for (cp = found; *cp != '\0'; cp++) { - if (!isdigit((u_char)*cp)) - goto error; - } + n = strtonum(found, 0, UINT_MAX, &errstr); + if (errstr != NULL) + goto error; sy->range_type = STYLE_RANGE_WINDOW; - sy->range_argument = atoi(found); + sy->range_argument = n; style_set_range_string(sy, ""); } else if (strcasecmp(tmp + 6, "session") == 0) { if (found == NULL) goto error; if (*found != '$' || found[1] == '\0') goto error; - for (cp = found + 1; *cp != '\0'; cp++) { - if (!isdigit((u_char)*cp)) - goto error; - } + n = strtonum(found + 1, 0, UINT_MAX, &errstr); + if (errstr != NULL) + goto error; sy->range_type = STYLE_RANGE_SESSION; - sy->range_argument = atoi(found + 1); + sy->range_argument = n; style_set_range_string(sy, ""); } else if (strcasecmp(tmp + 6, "user") == 0) { if (found == NULL) diff --git a/tmux.1 b/tmux.1 index 7efa00a8..db85fe5a 100644 --- a/tmux.1 +++ b/tmux.1 @@ -2110,14 +2110,15 @@ The synopsis for the command is: .Bl -tag -width Ds .It Xo Ic copy-mode -.Op Fl eHMqu +.Op Fl deHMqu .Op Fl s Ar src-pane .Op Fl t Ar target-pane .Xc Enter copy mode. -The .Fl u -option scrolls one page up. +also scrolls one page up after entering and +.Fl d +one page down if already in copy mode. .Fl M begins a mouse drag (only valid if bound to a mouse key binding, see .Sx MOUSE SUPPORT ) . @@ -2140,6 +2141,7 @@ This is intended to allow fast scrolling through a pane's history, for example with: .Bd -literal -offset indent bind PageUp copy-mode -eu +bind PageDown copy-mode -ed .Ed .El .Pp @@ -5498,6 +5500,7 @@ The following variables are available, where appropriate: .It Li "command_list_name" Ta "" Ta "Command name if listing commands" .It Li "command_list_usage" Ta "" Ta "Command usage if listing commands" .It Li "config_files" Ta "" Ta "List of configuration files loaded" +.It Li "copy_cursor_hyperlink" Ta "" Ta "Hyperlink under cursor in copy mode" .It Li "copy_cursor_line" Ta "" Ta "Line the cursor is on in copy mode" .It Li "copy_cursor_word" Ta "" Ta "Word under cursor in copy mode" .It Li "copy_cursor_x" Ta "" Ta "Cursor X position in copy mode" @@ -5584,6 +5587,8 @@ The following variables are available, where appropriate: .It Li "scroll_position" Ta "" Ta "Scroll position in copy mode" .It Li "scroll_region_lower" Ta "" Ta "Bottom of scroll region in pane" .It Li "scroll_region_upper" Ta "" Ta "Top of scroll region in pane" +.It Li "search_count" Ta "" Ta "Count of search results" +.It Li "search_count_partial" Ta "" Ta "1 if search count is partial count" .It Li "search_match" Ta "" Ta "Search match if any" .It Li "search_present" Ta "" Ta "1 if search started in copy mode" .It Li "selection_active" Ta "" Ta "1 if selection started and changes with the cursor in copy mode" diff --git a/tmux.h b/tmux.h index 197af2c6..514266c6 100644 --- a/tmux.h +++ b/tmux.h @@ -997,6 +997,11 @@ enum pane_lines { #define PANE_BORDER_ARROWS 2 #define PANE_BORDER_BOTH 3 +/* Mode returned by window_pane_mode function. */ +#define WINDOW_PANE_NO_MODE 0 +#define WINDOW_PANE_COPY_MODE 1 +#define WINDOW_PANE_VIEW_MODE 2 + /* Screen redraw context. */ struct screen_redraw_ctx { struct client *c; @@ -2742,11 +2747,12 @@ void server_clear_marked(void); int server_is_marked(struct session *, struct winlink *, struct window_pane *); int server_check_marked(void); -int server_start(struct tmuxproc *, int, struct event_base *, int, char *); +int server_start(struct tmuxproc *, uint64_t, struct event_base *, int, + char *); void server_update_socket(void); void server_add_accept(int); void printflike(1, 2) server_add_message(const char *, ...); -int server_create_socket(int, char **); +int server_create_socket(uint64_t, char **); /* server-client.c */ RB_PROTOTYPE(client_windows, client_window, entry, server_client_window_cmp); @@ -3161,6 +3167,7 @@ void window_pane_update_used_data(struct window_pane *, struct window_pane_offset *, size_t); void window_set_fill_character(struct window *); void window_pane_default_cursor(struct window_pane *); +int window_pane_mode(struct window_pane *); /* layout.c */ u_int layout_count_cells(struct layout_cell *); @@ -3267,6 +3274,7 @@ void printflike(3, 4) window_copy_add(struct window_pane *, int, const char *, void printflike(3, 0) window_copy_vadd(struct window_pane *, int, const char *, va_list); void window_copy_pageup(struct window_pane *, int); +void window_copy_pagedown(struct window_pane *, int, int); void window_copy_start_drag(struct client *, struct mouse_event *); char *window_copy_get_word(struct window_pane *, u_int, u_int); char *window_copy_get_line(struct window_pane *, u_int); @@ -3500,6 +3508,7 @@ u_int hyperlinks_put(struct hyperlinks *, const char *, int hyperlinks_get(struct hyperlinks *, u_int, const char **, const char **, const char **); struct hyperlinks *hyperlinks_init(void); +struct hyperlinks *hyperlinks_copy(struct hyperlinks *); void hyperlinks_reset(struct hyperlinks *); void hyperlinks_free(struct hyperlinks *); diff --git a/tty-keys.c b/tty-keys.c index 9555dc31..3debeea1 100644 --- a/tty-keys.c +++ b/tty-keys.c @@ -812,8 +812,9 @@ first_key: * lowercase, so ^A becomes a|CTRL. */ onlykey = key & KEYC_MASK_KEY; - if (onlykey < 0x20 && onlykey != C0_BS && - onlykey != C0_HT && onlykey != C0_CR && + if (onlykey < 0x20 && + onlykey != C0_HT && + onlykey != C0_CR && onlykey != C0_ESC) { onlykey |= 0x40; if (onlykey >= 'A' && onlykey <= 'Z') diff --git a/tty-term.c b/tty-term.c index 67face26..d4223497 100644 --- a/tty-term.c +++ b/tty-term.c @@ -531,9 +531,10 @@ tty_term_create(struct tty *tty, char *name, char **caps, u_int ncaps, struct options_array_item *a; union options_value *ov; u_int i, j; - const char *s, *value; + const char *s, *value, *errstr; size_t offset, namelen; char *first; + int n; log_debug("adding term %s", name); @@ -567,8 +568,13 @@ tty_term_create(struct tty *tty, char *name, char **caps, u_int ncaps, code->value.string = tty_term_strip(value); break; case TTYCODE_NUMBER: - code->type = TTYCODE_NUMBER; - code->value.number = atoi(value); + n = strtonum(value, 0, INT_MAX, &errstr); + if (errstr != NULL) + log_debug("%s: %s", ent->name, errstr); + else { + code->type = TTYCODE_NUMBER; + code->value.number = n; + } break; case TTYCODE_FLAG: code->type = TTYCODE_FLAG; diff --git a/window-copy.c b/window-copy.c index de124812..35818644 100644 --- a/window-copy.c +++ b/window-copy.c @@ -41,7 +41,7 @@ static void window_copy_resize(struct window_mode_entry *, u_int, u_int); static void window_copy_formats(struct window_mode_entry *, struct format_tree *); static void window_copy_pageup1(struct window_mode_entry *, int); -static int window_copy_pagedown(struct window_mode_entry *, int, int); +static int window_copy_pagedown1(struct window_mode_entry *, int, int); static void window_copy_next_paragraph(struct window_mode_entry *); static void window_copy_previous_paragraph(struct window_mode_entry *); static void window_copy_redraw_selection(struct window_mode_entry *, u_int); @@ -450,6 +450,8 @@ window_copy_init(struct window_mode_entry *wme, data->scroll_exit = args_has(args, 'e'); data->hide_position = args_has(args, 'H'); + if (base->hyperlinks != NULL) + data->screen.hyperlinks = hyperlinks_copy(base->hyperlinks); data->screen.cx = data->cx; data->screen.cy = data->cy; data->mx = data->cx; @@ -646,8 +648,18 @@ window_copy_pageup1(struct window_mode_entry *wme, int half_page) window_copy_redraw_screen(wme); } +void +window_copy_pagedown(struct window_pane *wp, int half_page, int scroll_exit) +{ + if (window_copy_pagedown1(TAILQ_FIRST(&wp->modes), half_page, + scroll_exit)) { + window_pane_reset_mode(wp); + return; + } +} + static int -window_copy_pagedown(struct window_mode_entry *wme, int half_page, +window_copy_pagedown1(struct window_mode_entry *wme, int half_page, int scroll_exit) { struct window_copy_mode_data *data = wme->data; @@ -754,6 +766,18 @@ window_copy_get_line(struct window_pane *wp, u_int y) return (format_grid_line(gd, gd->hsize + y)); } +static void * +window_copy_cursor_hyperlink_cb(struct format_tree *ft) +{ + struct window_pane *wp = format_get_pane(ft); + struct window_mode_entry *wme = TAILQ_FIRST(&wp->modes); + struct window_copy_mode_data *data = wme->data; + struct grid *gd = data->screen.grid; + + return (format_grid_hyperlink(gd, data->cx, gd->hsize + data->cy, + &data->screen)); +} + static void * window_copy_cursor_word_cb(struct format_tree *ft) { @@ -815,10 +839,16 @@ window_copy_formats(struct window_mode_entry *wme, struct format_tree *ft) } format_add(ft, "search_present", "%d", data->searchmark != NULL); + if (data->searchcount != -1) { + format_add(ft, "search_count", "%d", data->searchcount); + format_add(ft, "search_count_partial", "%d", data->searchmore); + } format_add_cb(ft, "search_match", window_copy_search_match_cb); format_add_cb(ft, "copy_cursor_word", window_copy_cursor_word_cb); format_add_cb(ft, "copy_cursor_line", window_copy_cursor_line_cb); + format_add_cb(ft, "copy_cursor_hyperlink", + window_copy_cursor_hyperlink_cb); } static void @@ -1347,7 +1377,7 @@ window_copy_cmd_halfpage_down(struct window_copy_cmd_state *cs) u_int np = wme->prefix; for (; np != 0; np--) { - if (window_copy_pagedown(wme, 1, data->scroll_exit)) + if (window_copy_pagedown1(wme, 1, data->scroll_exit)) return (WINDOW_COPY_CMD_CANCEL); } return (WINDOW_COPY_CMD_NOTHING); @@ -1361,7 +1391,7 @@ window_copy_cmd_halfpage_down_and_cancel(struct window_copy_cmd_state *cs) u_int np = wme->prefix; for (; np != 0; np--) { - if (window_copy_pagedown(wme, 1, 1)) + if (window_copy_pagedown1(wme, 1, 1)) return (WINDOW_COPY_CMD_CANCEL); } return (WINDOW_COPY_CMD_NOTHING); @@ -1789,7 +1819,7 @@ window_copy_cmd_page_down(struct window_copy_cmd_state *cs) u_int np = wme->prefix; for (; np != 0; np--) { - if (window_copy_pagedown(wme, 0, data->scroll_exit)) + if (window_copy_pagedown1(wme, 0, data->scroll_exit)) return (WINDOW_COPY_CMD_CANCEL); } return (WINDOW_COPY_CMD_NOTHING); @@ -1802,7 +1832,7 @@ window_copy_cmd_page_down_and_cancel(struct window_copy_cmd_state *cs) u_int np = wme->prefix; for (; np != 0; np--) { - if (window_copy_pagedown(wme, 0, 1)) + if (window_copy_pagedown1(wme, 0, 1)) return (WINDOW_COPY_CMD_CANCEL); } return (WINDOW_COPY_CMD_NOTHING); @@ -2472,7 +2502,8 @@ window_copy_cmd_refresh_from_pane(struct window_copy_cmd_state *cs) screen_free(data->backing); free(data->backing); - data->backing = window_copy_clone_screen(&wp->base, &data->screen, NULL, NULL, wme->swp != wme->wp); + data->backing = window_copy_clone_screen(&wp->base, &data->screen, NULL, + NULL, wme->swp != wme->wp); window_copy_size_changed(wme); return (WINDOW_COPY_CMD_REDRAW); diff --git a/window.c b/window.c index a115366c..5d68cec0 100644 --- a/window.c +++ b/window.c @@ -1672,3 +1672,15 @@ window_pane_default_cursor(struct window_pane *wp) s->default_mode = 0; screen_set_cursor_style(c, &s->default_cstyle, &s->default_mode); } + +int +window_pane_mode(struct window_pane *wp) +{ + if (TAILQ_FIRST(&wp->modes) != NULL) { + if (TAILQ_FIRST(&wp->modes)->mode == &window_copy_mode) + return (WINDOW_PANE_COPY_MODE); + if (TAILQ_FIRST(&wp->modes)->mode == &window_view_mode) + return (WINDOW_PANE_VIEW_MODE); + } + return (WINDOW_PANE_NO_MODE); +}