Merge branch 'obsd-master'

This commit is contained in:
Thomas Adam
2026-05-01 12:01:08 +01:00
7 changed files with 437 additions and 34 deletions

View File

@@ -63,6 +63,7 @@ cmd_copy_mode_exec(struct cmd *self, struct cmdq_item *item)
struct client *c = cmdq_get_client(item); struct client *c = cmdq_get_client(item);
struct session *s; struct session *s;
struct window_pane *wp = target->wp, *swp; struct window_pane *wp = target->wp, *swp;
int line_numbers;
if (args_has(args, 'q')) { if (args_has(args, 'q')) {
window_pane_reset_mode_all(wp); window_pane_reset_mode_all(wp);
@@ -85,10 +86,15 @@ cmd_copy_mode_exec(struct cmd *self, struct cmdq_item *item)
swp = source->wp; swp = source->wp;
else else
swp = wp; swp = wp;
line_numbers = 1;
if (event != NULL && KEYC_IS_MOUSE(event->key))
line_numbers = 0;
if (!window_pane_set_mode(wp, swp, &window_copy_mode, NULL, args)) { if (!window_pane_set_mode(wp, swp, &window_copy_mode, NULL, args)) {
window_copy_set_line_numbers(wp, line_numbers);
if (args_has(args, 'M')) if (args_has(args, 'M'))
window_copy_start_drag(c, &event->m); window_copy_start_drag(c, &event->m);
} } else
window_copy_set_line_numbers(wp, line_numbers);
if (args_has(args, 'u')) if (args_has(args, 'u'))
window_copy_pageup(wp, 0); window_copy_pageup(wp, 0);
if (args_has(args, 'd')) if (args_has(args, 'd'))

View File

@@ -2310,7 +2310,7 @@ format_cb_pane_pipe_pid(struct format_tree *ft)
static void * static void *
format_cb_pane_pb_progress(struct format_tree *ft) format_cb_pane_pb_progress(struct format_tree *ft)
{ {
char *value = NULL; char *value = NULL;
if (ft->wp != NULL) if (ft->wp != NULL)
xasprintf(&value, "%d", ft->wp->base.progress_bar.progress); xasprintf(&value, "%d", ft->wp->base.progress_bar.progress);
@@ -4243,6 +4243,20 @@ format_choose(struct format_expand_state *es, const char *s, char **left,
return (0); return (0);
} }
/* Check format has not taken too lon. */
static int
format_check_time(struct format_expand_state *es)
{
uint64_t t = get_timer();
if (t - es->start_time < FORMAT_TIME_LIMIT)
return (1);
t -= es->start_time;
format_log(es, "reached time limit (%llu)", (unsigned long long)t);
return (0);
}
/* Is this true? */ /* Is this true? */
int int
format_true(const char *s) format_true(const char *s)
@@ -5265,6 +5279,8 @@ format_replace(struct format_expand_state *es, const char *key, size_t keylen,
else { else {
value = xstrdup(""); value = xstrdup("");
for (i = 0; i < nrep; i++) { for (i = 0; i < nrep; i++) {
if (!format_check_time(es))
goto fail;
xasprintf(&new, "%s%s", value, left); xasprintf(&new, "%s%s", value, left);
free(value); free(value);
value = new; value = new;
@@ -5538,16 +5554,10 @@ format_expand1(struct format_expand_state *es, const char *fmt)
size_t off, len, n, outlen; size_t off, len, n, outlen;
int ch, brackets; int ch, brackets;
char expanded[8192]; char expanded[8192];
uint64_t t = get_timer();
if (fmt == NULL || *fmt == '\0') if (fmt == NULL || *fmt == '\0' || !format_check_time(es))
return (xstrdup("")); return (xstrdup(""));
if (t - es->start_time >= FORMAT_TIME_LIMIT) {
format_log(es, "reached time limit (%llu)",
(unsigned long long)(t - es->start_time));
return (xstrdup(""));
}
if (es->loop == FORMAT_LOOP_LIMIT) { if (es->loop == FORMAT_LOOP_LIMIT) {
format_log(es, "reached loop limit (%u)", FORMAT_LOOP_LIMIT); format_log(es, "reached loop limit (%u)", FORMAT_LOOP_LIMIT);
return (xstrdup("")); return (xstrdup(""));

View File

@@ -108,6 +108,9 @@ static const char *options_table_extended_keys_format_list[] = {
static const char *options_table_allow_passthrough_list[] = { static const char *options_table_allow_passthrough_list[] = {
"off", "on", "all", NULL "off", "on", "all", NULL
}; };
static const char *options_table_copy_mode_line_numbers_list[] = {
"off", "default", "absolute", "relative", "hybrid", NULL
};
/* Status line format. */ /* Status line format. */
#define OPTIONS_TABLE_STATUS_FORMAT1 \ #define OPTIONS_TABLE_STATUS_FORMAT1 \
@@ -1176,7 +1179,7 @@ const struct options_table_entry options_table[] = {
.scope = OPTIONS_TABLE_WINDOW|OPTIONS_TABLE_PANE, .scope = OPTIONS_TABLE_WINDOW|OPTIONS_TABLE_PANE,
.default_str = "#[align=right]" .default_str = "#[align=right]"
"#{t/p:top_line_time}#{?#{e|>:#{top_line_time},0}, ,}" "#{t/p:top_line_time}#{?#{e|>:#{top_line_time},0}, ,}"
"[#{scroll_position}/#{history_size}]" "[#{copy_position}/#{copy_position_limit}]"
"#{?search_timed_out, (timed out)," "#{?search_timed_out, (timed out),"
"#{?search_count, (#{search_count}" "#{?search_count, (#{search_count}"
"#{?search_count_partial,+,} results),}}", "#{?search_count_partial,+,} results),}}",
@@ -1201,6 +1204,32 @@ const struct options_table_entry options_table[] = {
.text = "Style of selection in copy mode." .text = "Style of selection in copy mode."
}, },
{ .name = "copy-mode-current-line-number-style",
.type = OPTIONS_TABLE_STRING,
.scope = OPTIONS_TABLE_WINDOW,
.default_str = "fg=yellow",
.flags = OPTIONS_TABLE_IS_STYLE,
.separator = ",",
.text = "Style of current line number in copy mode."
},
{ .name = "copy-mode-line-number-style",
.type = OPTIONS_TABLE_STRING,
.scope = OPTIONS_TABLE_WINDOW,
.default_str = "fg=white,dim",
.flags = OPTIONS_TABLE_IS_STYLE,
.separator = ",",
.text = "Style of line numbers in copy mode."
},
{ .name = "copy-mode-line-numbers",
.type = OPTIONS_TABLE_CHOICE,
.scope = OPTIONS_TABLE_WINDOW,
.choices = options_table_copy_mode_line_numbers_list,
.default_num = 0,
.text = "Line number mode in copy mode."
},
{ .name = "fill-character", { .name = "fill-character",
.type = OPTIONS_TABLE_STRING, .type = OPTIONS_TABLE_STRING,
.scope = OPTIONS_TABLE_WINDOW, .scope = OPTIONS_TABLE_WINDOW,

View File

@@ -36,6 +36,8 @@ struct screen_sel {
u_int ex; u_int ex;
u_int ey; u_int ey;
u_int clipx;
struct grid_cell cell; struct grid_cell cell;
}; };
@@ -465,7 +467,8 @@ screen_resize_y(struct screen *s, u_int sy, int eat_empty, u_int *cy)
/* Set selection. */ /* Set selection. */
void void
screen_set_selection(struct screen *s, u_int sx, u_int sy, screen_set_selection(struct screen *s, u_int sx, u_int sy,
u_int ex, u_int ey, u_int rectangle, int modekeys, struct grid_cell *gc) u_int ex, u_int ey, u_int rectangle, u_int clipx, int modekeys,
struct grid_cell *gc)
{ {
if (s->sel == NULL) if (s->sel == NULL)
s->sel = xcalloc(1, sizeof *s->sel); s->sel = xcalloc(1, sizeof *s->sel);
@@ -479,6 +482,7 @@ screen_set_selection(struct screen *s, u_int sx, u_int sy,
s->sel->sy = sy; s->sel->sy = sy;
s->sel->ex = ex; s->sel->ex = ex;
s->sel->ey = ey; s->sel->ey = ey;
s->sel->clipx = clipx;
} }
/* Clear selection. */ /* Clear selection. */
@@ -506,6 +510,8 @@ screen_check_selection(struct screen *s, u_int px, u_int py)
if (sel == NULL || sel->hidden) if (sel == NULL || sel->hidden)
return (0); return (0);
if (px < sel->clipx)
return (0);
if (sel->rectangle) { if (sel->rectangle) {
if (sel->sy < sel->ey) { if (sel->sy < sel->ey) {

48
tmux.1
View File

@@ -5175,6 +5175,52 @@ see the
.Sx STYLES .Sx STYLES
section. section.
.Pp .Pp
.It Ic copy\-mode\-current\-line\-number\-style Ar style
Set style of current line number in copy mode.
For how to specify
.Ar style ,
see the
.Sx STYLES
section.
.Pp
.It Ic copy\-mode\-line\-number\-style Ar style
Set style of line numbers in copy mode.
For how to specify
.Ar style ,
see the
.Sx STYLES
section.
.Pp
.It Xo Ic copy\-mode\-line\-numbers
.Op Ic off | default | absolute | relative | hybrid
.Xc
Show line numbers in copy mode.
.Ic off
hides line numbers,
.Ic default
shows line numbers matching the copy mode position indicator and
.Ic goto\-line ,
.Ic absolute
shows absolute line numbers,
.Ic relative
shows line numbers relative to the cursor, and
.Ic hybrid
shows the current line number as absolute and other line numbers as
relative.
With
.Ic off
or
.Ic default ,
the position indicator and
.Ic goto\-line
use the same numbering;
with
.Ic absolute ,
.Ic relative
and
.Ic hybrid ,
they use absolute line numbers.
.Pp
.It Ic mode\-style Ar style .It Ic mode\-style Ar style
Set window modes style. Set window modes style.
For how to specify For how to specify
@@ -6310,6 +6356,8 @@ The following variables are available, where appropriate:
.It Li "copy_cursor_word" Ta "" Ta "Word under cursor 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" .It Li "copy_cursor_x" Ta "" Ta "Cursor X position in copy mode"
.It Li "copy_cursor_y" Ta "" Ta "Cursor Y position in copy mode" .It Li "copy_cursor_y" Ta "" Ta "Cursor Y position in copy mode"
.It Li "copy_position" Ta "" Ta "Position shown in the copy mode indicator"
.It Li "copy_position_limit" Ta "" Ta "Limit shown in the copy mode indicator"
.It Li "current_file" Ta "" Ta "Current configuration file" .It Li "current_file" Ta "" Ta "Current configuration file"
.It Li "cursor_character" Ta "" Ta "Character at cursor in pane" .It Li "cursor_character" Ta "" Ta "Character at cursor in pane"
.It Li "cursor_colour" Ta "" Ta "Cursor colour in pane" .It Li "cursor_colour" Ta "" Ta "Cursor colour in pane"

3
tmux.h
View File

@@ -3343,7 +3343,7 @@ void screen_set_progress_bar(struct screen *, enum progress_bar_state, int);
void screen_resize(struct screen *, u_int, u_int, int); void screen_resize(struct screen *, u_int, u_int, int);
void screen_resize_cursor(struct screen *, u_int, u_int, int, int, int); void screen_resize_cursor(struct screen *, u_int, u_int, int, int, int);
void screen_set_selection(struct screen *, u_int, u_int, u_int, u_int, void screen_set_selection(struct screen *, u_int, u_int, u_int, u_int,
u_int, int, struct grid_cell *); u_int, u_int, int, struct grid_cell *);
void screen_clear_selection(struct screen *); void screen_clear_selection(struct screen *);
void screen_hide_selection(struct screen *); void screen_hide_selection(struct screen *);
int screen_check_selection(struct screen *, u_int, u_int); int screen_check_selection(struct screen *, u_int, u_int);
@@ -3581,6 +3581,7 @@ char *window_copy_get_line(struct window_pane *, u_int);
int window_copy_get_current_offset(struct window_pane *, u_int *, int window_copy_get_current_offset(struct window_pane *, u_int *,
u_int *); u_int *);
char *window_copy_get_hyperlink(struct window_pane *, u_int, u_int); char *window_copy_get_hyperlink(struct window_pane *, u_int, u_int);
void window_copy_set_line_numbers(struct window_pane *, int);
/* window-option.c */ /* window-option.c */
extern const struct window_mode window_customize_mode; extern const struct window_mode window_customize_mode;

View File

@@ -52,6 +52,12 @@ static void window_copy_redraw_lines(struct window_mode_entry *, u_int,
u_int); u_int);
static void window_copy_redraw_screen(struct window_mode_entry *); static void window_copy_redraw_screen(struct window_mode_entry *);
static void window_copy_style_changed(struct window_mode_entry *); static void window_copy_style_changed(struct window_mode_entry *);
static int window_copy_line_number_mode(struct window_mode_entry *);
static int window_copy_line_number_is_absolute(struct window_mode_entry *);
static int window_copy_line_numbers_active(struct window_mode_entry *);
static u_int window_copy_line_number_width(struct window_mode_entry *);
static u_int window_copy_cursor_offset(struct window_mode_entry *, u_int, u_int);
static u_int window_copy_cursor_unoffset(struct window_mode_entry *, u_int, u_int);
static void window_copy_write_line(struct window_mode_entry *, static void window_copy_write_line(struct window_mode_entry *,
struct screen_write_ctx *, u_int); struct screen_write_ctx *, u_int);
static void window_copy_write_lines(struct window_mode_entry *, static void window_copy_write_lines(struct window_mode_entry *,
@@ -207,6 +213,14 @@ enum window_copy_cmd_clear {
WINDOW_COPY_CMD_CLEAR_EMACS_ONLY, WINDOW_COPY_CMD_CLEAR_EMACS_ONLY,
}; };
enum window_copy_line_numbers {
WINDOW_COPY_LINE_NUMBERS_OFF,
WINDOW_COPY_LINE_NUMBERS_DEFAULT,
WINDOW_COPY_LINE_NUMBERS_ABSOLUTE,
WINDOW_COPY_LINE_NUMBERS_RELATIVE,
WINDOW_COPY_LINE_NUMBERS_HYBRID,
};
struct window_copy_cmd_state { struct window_copy_cmd_state {
struct window_mode_entry *wme; struct window_mode_entry *wme;
struct args *args; struct args *args;
@@ -264,6 +278,7 @@ struct window_copy_mode_data {
int rectflag; /* in rectangle copy mode? */ int rectflag; /* in rectangle copy mode? */
int scroll_exit; /* exit on scroll to end? */ int scroll_exit; /* exit on scroll to end? */
int hide_position; /* hide position marker */ int hide_position; /* hide position marker */
int line_numbers;
enum { enum {
SEL_CHAR, /* select one char at a time */ SEL_CHAR, /* select one char at a time */
@@ -427,6 +442,7 @@ window_copy_common_init(struct window_mode_entry *wme)
data->jumptype = WINDOW_COPY_OFF; data->jumptype = WINDOW_COPY_OFF;
data->jumpchar = NULL; data->jumpchar = NULL;
data->line_numbers = 1;
screen_init(&data->screen, screen_size_x(base), screen_size_y(base), 0); screen_init(&data->screen, screen_size_x(base), screen_size_y(base), 0);
screen_set_default_cursor(&data->screen, global_w_options); screen_set_default_cursor(&data->screen, global_w_options);
@@ -467,7 +483,8 @@ window_copy_init(struct window_mode_entry *wme,
hyperlinks_free(data->screen.hyperlinks); hyperlinks_free(data->screen.hyperlinks);
data->screen.hyperlinks = hyperlinks_copy(base->hyperlinks); data->screen.hyperlinks = hyperlinks_copy(base->hyperlinks);
} }
data->screen.cx = data->cx; data->screen.cx = window_copy_cursor_offset(wme, data->cx,
screen_size_x(&data->screen));
data->screen.cy = data->cy; data->screen.cy = data->cy;
data->mx = data->cx; data->mx = data->cx;
data->my = screen_hsize(data->backing) + data->cy - data->oy; data->my = screen_hsize(data->backing) + data->cy - data->oy;
@@ -476,7 +493,8 @@ window_copy_init(struct window_mode_entry *wme,
screen_write_start(&ctx, &data->screen); screen_write_start(&ctx, &data->screen);
for (i = 0; i < screen_size_y(&data->screen); i++) for (i = 0; i < screen_size_y(&data->screen); i++)
window_copy_write_line(wme, &ctx, i); window_copy_write_line(wme, &ctx, i);
screen_write_cursormove(&ctx, data->cx, data->cy, 0); screen_write_cursormove(&ctx, window_copy_cursor_offset(wme, data->cx,
screen_size_x(&data->screen)), data->cy, 0);
screen_write_stop(&ctx); screen_write_stop(&ctx);
return (&data->screen); return (&data->screen);
@@ -493,6 +511,7 @@ window_copy_view_init(struct window_mode_entry *wme,
data = window_copy_common_init(wme); data = window_copy_common_init(wme);
data->viewmode = 1; data->viewmode = 1;
data->line_numbers = 0;
data->backing = xmalloc(sizeof *data->backing); data->backing = xmalloc(sizeof *data->backing);
screen_init(data->backing, sx, screen_size_y(base), UINT_MAX); screen_init(data->backing, sx, screen_size_y(base), UINT_MAX);
@@ -931,12 +950,22 @@ window_copy_formats(struct window_mode_entry *wme, struct format_tree *ft)
{ {
struct window_copy_mode_data *data = wme->data; struct window_copy_mode_data *data = wme->data;
u_int hsize = screen_hsize(data->backing); u_int hsize = screen_hsize(data->backing);
u_int position, limit;
struct grid_line *gl; struct grid_line *gl;
gl = grid_get_line(data->backing->grid, hsize - data->oy); gl = grid_get_line(data->backing->grid, hsize - data->oy);
format_add(ft, "top_line_time", "%llu", (unsigned long long)gl->time); format_add(ft, "top_line_time", "%llu", (unsigned long long)gl->time);
format_add(ft, "scroll_position", "%d", data->oy); format_add(ft, "scroll_position", "%d", data->oy);
if (window_copy_line_number_is_absolute(wme)) {
position = hsize - data->oy + 1;
limit = hsize + screen_size_y(data->backing);
} else {
position = data->oy;
limit = hsize;
}
format_add(ft, "copy_position", "%u", position);
format_add(ft, "copy_position_limit", "%u", limit);
format_add(ft, "rectangle_toggle", "%d", data->rectflag); format_add(ft, "rectangle_toggle", "%d", data->rectflag);
format_add(ft, "copy_cursor_x", "%d", data->cx); format_add(ft, "copy_cursor_x", "%d", data->cx);
@@ -4462,15 +4491,28 @@ window_copy_goto_line(struct window_mode_entry *wme, const char *linestr)
{ {
struct window_copy_mode_data *data = wme->data; struct window_copy_mode_data *data = wme->data;
const char *errstr; const char *errstr;
u_int hsize = screen_hsize(data->backing);
u_int line;
int lineno; int lineno;
lineno = strtonum(linestr, -1, INT_MAX, &errstr); lineno = strtonum(linestr, -1, INT_MAX, &errstr);
if (errstr != NULL) if (errstr != NULL)
return; return;
if (lineno < 0 || (u_int)lineno > screen_hsize(data->backing))
lineno = screen_hsize(data->backing);
data->oy = lineno; if (window_copy_line_number_is_absolute(wme)) {
if (lineno <= 0)
line = 1;
else if ((u_int)lineno > hsize + 1)
line = hsize + 1;
else
line = lineno;
data->oy = hsize - (line - 1);
} else {
if (lineno < 0 || (u_int)lineno > hsize)
lineno = hsize;
data->oy = lineno;
}
window_copy_update_selection(wme, 1, 0); window_copy_update_selection(wme, 1, 0);
window_copy_redraw_screen(wme); window_copy_redraw_screen(wme);
} }
@@ -4619,7 +4661,7 @@ window_copy_update_style(struct window_mode_entry *wme, u_int fx, u_int fy,
static void static void
window_copy_write_one(struct window_mode_entry *wme, window_copy_write_one(struct window_mode_entry *wme,
struct screen_write_ctx *ctx, u_int py, u_int fy, u_int nx, struct screen_write_ctx *ctx, u_int px, u_int py, u_int fy, u_int nx,
const struct grid_cell *mgc, const struct grid_cell *cgc, const struct grid_cell *mgc, const struct grid_cell *cgc,
const struct grid_cell *mkgc) const struct grid_cell *mkgc)
{ {
@@ -4628,7 +4670,7 @@ window_copy_write_one(struct window_mode_entry *wme,
struct grid_cell gc; struct grid_cell gc;
u_int fx; u_int fx;
screen_write_cursormove(ctx, 0, py, 0); screen_write_cursormove(ctx, px, py, 0);
for (fx = 0; fx < nx; fx++) { for (fx = 0; fx < nx; fx++) {
grid_get_cell(gd, fx, fy, &gc); grid_get_cell(gd, fx, fy, &gc);
if (fx + gc.data.width <= nx) { if (fx + gc.data.width <= nx) {
@@ -4639,6 +4681,116 @@ window_copy_write_one(struct window_mode_entry *wme,
} }
} }
static int
window_copy_line_number_mode(struct window_mode_entry *wme)
{
struct window_pane *wp = wme->wp;
struct window_copy_mode_data *data = wme->data;
struct options *oo = wp->window->options;
if (!data->line_numbers)
return (WINDOW_COPY_LINE_NUMBERS_OFF);
return (options_get_number(oo, "copy-mode-line-numbers"));
}
static int
window_copy_line_number_is_absolute(struct window_mode_entry *wme)
{
switch (window_copy_line_number_mode(wme)) {
case WINDOW_COPY_LINE_NUMBERS_ABSOLUTE:
case WINDOW_COPY_LINE_NUMBERS_RELATIVE:
case WINDOW_COPY_LINE_NUMBERS_HYBRID:
return (1);
case WINDOW_COPY_LINE_NUMBERS_OFF:
case WINDOW_COPY_LINE_NUMBERS_DEFAULT:
return (0);
}
fatalx("bad line number mode");
}
static int
window_copy_line_numbers_active(struct window_mode_entry *wme)
{
return (window_copy_line_number_mode(wme) !=
WINDOW_COPY_LINE_NUMBERS_OFF);
}
static u_int
window_copy_line_number_width(struct window_mode_entry *wme)
{
struct window_copy_mode_data *data = wme->data;
u_int lines, digits;
if (!window_copy_line_numbers_active(wme))
return (0);
lines = screen_hsize(data->backing) + screen_size_y(data->backing) + 1;
digits = 1;
while (lines >= 10) {
lines /= 10;
digits++;
}
if (digits < 3)
digits = 3;
return (digits + 1);
}
static u_int
window_copy_cursor_offset(struct window_mode_entry *wme, u_int cx, u_int sx)
{
u_int width = window_copy_line_number_width(wme);
u_int content;
if (width == 0)
return (cx);
if (width >= sx)
content = 1;
else
content = sx - width;
if (cx >= content)
return (sx - 1);
return (width + cx);
}
static u_int
window_copy_cursor_unoffset(struct window_mode_entry *wme, u_int vx, u_int sx)
{
u_int width = window_copy_line_number_width(wme);
u_int content;
if (width == 0)
return (vx);
if (width >= sx)
content = 1;
else
content = sx - width;
if (vx < width)
return (0);
vx -= width;
if (vx >= content)
return (content - 1);
return (vx);
}
void
window_copy_set_line_numbers(struct window_pane *wp, int enabled)
{
struct window_mode_entry *wme = TAILQ_FIRST(&wp->modes);
struct window_copy_mode_data *data;
if (wme == NULL)
return;
if (wme->mode != &window_copy_mode)
return;
data = wme->data;
if (data == NULL)
return;
if (data->line_numbers == enabled)
return;
data->line_numbers = enabled;
window_copy_redraw_screen(wme);
}
int int
window_copy_get_current_offset(struct window_pane *wp, u_int *offset, window_copy_get_current_offset(struct window_pane *wp, u_int *offset,
u_int *size) u_int *size)
@@ -4664,12 +4816,23 @@ window_copy_write_line(struct window_mode_entry *wme,
struct window_copy_mode_data *data = wme->data; struct window_copy_mode_data *data = wme->data;
struct screen *s = &data->screen; struct screen *s = &data->screen;
struct options *oo = wp->window->options; struct options *oo = wp->window->options;
struct grid_cell gc, mgc, cgc, mkgc; struct grid_cell gc, mgc, cgc, mkgc, ln_gc, cur_ln_gc;
u_int sx = screen_size_x(s); u_int sx = screen_size_x(s);
u_int hsize = screen_hsize(data->backing); u_int hsize = screen_hsize(data->backing);
u_int width;
u_int absolute, line_number, content_sx;
const char *value; const char *value;
char *expanded; char *expanded;
struct format_tree *ft; struct format_tree *ft;
int current, mode;
width = window_copy_line_number_width(wme);
if (width >= sx)
content_sx = 1;
else if (width != 0)
content_sx = sx - width;
else
content_sx = sx;
ft = format_create_defaults(NULL, NULL, NULL, NULL, wp); ft = format_create_defaults(NULL, NULL, NULL, NULL, wp);
@@ -4681,24 +4844,52 @@ window_copy_write_line(struct window_mode_entry *wme,
cgc.flags |= GRID_FLAG_NOPALETTE; cgc.flags |= GRID_FLAG_NOPALETTE;
style_apply(&mkgc, oo, "copy-mode-mark-style", ft); style_apply(&mkgc, oo, "copy-mode-mark-style", ft);
mkgc.flags |= GRID_FLAG_NOPALETTE; mkgc.flags |= GRID_FLAG_NOPALETTE;
if (width != 0) {
style_apply(&ln_gc, oo, "copy-mode-line-number-style", ft);
ln_gc.flags |= GRID_FLAG_NOPALETTE;
style_apply(&cur_ln_gc, oo,
"copy-mode-current-line-number-style", ft);
cur_ln_gc.flags |= GRID_FLAG_NOPALETTE;
current = (py == data->cy);
absolute = hsize - data->oy + py + 1;
mode = window_copy_line_number_mode(wme);
if (mode == WINDOW_COPY_LINE_NUMBERS_DEFAULT) {
if (py < data->oy)
line_number = data->oy - py;
else
line_number = py - data->oy;
} else if (mode == WINDOW_COPY_LINE_NUMBERS_ABSOLUTE)
line_number = absolute;
else if (mode == WINDOW_COPY_LINE_NUMBERS_HYBRID && current)
line_number = absolute;
else if (py > data->cy)
line_number = py - data->cy;
else
line_number = data->cy - py;
screen_write_cursormove(ctx, 0, py, 0);
screen_write_nputs(ctx, width, current ? &cur_ln_gc : &ln_gc,
"%*u ", (int)width - 1, line_number);
}
window_copy_write_one(wme, ctx, py, hsize - data->oy + py, window_copy_write_one(wme, ctx, width, py, hsize - data->oy + py,
screen_size_x(s), &mgc, &cgc, &mkgc); content_sx, &mgc, &cgc, &mkgc);
if (py == 0 && s->rupper < s->rlower && !data->hide_position) { if (py == 0 && s->rupper < s->rlower && !data->hide_position) {
value = options_get_string(oo, "copy-mode-position-format"); value = options_get_string(oo, "copy-mode-position-format");
if (*value != '\0') { if (*value != '\0') {
expanded = format_expand(ft, value); expanded = format_expand(ft, value);
if (*expanded != '\0') { if (*expanded != '\0') {
screen_write_cursormove(ctx, 0, 0, 0); screen_write_cursormove(ctx, width, 0, 0);
format_draw(ctx, &gc, sx, expanded, NULL, 0); format_draw(ctx, &gc, content_sx, expanded,
NULL, 0);
} }
free(expanded); free(expanded);
} }
} }
if (py == data->cy && data->cx == screen_size_x(s)) { if (py == data->cy && data->cx >= content_sx) {
screen_write_cursormove(ctx, screen_size_x(s) - 1, py, 0); screen_write_cursormove(ctx, window_copy_cursor_offset(wme,
data->cx, screen_size_x(s)), py, 0);
screen_write_putc(ctx, &grid_default_cell, '$'); screen_write_putc(ctx, &grid_default_cell, '$');
} }
@@ -4748,13 +4939,28 @@ window_copy_redraw_lines(struct window_mode_entry *wme, u_int py, u_int ny)
{ {
struct window_pane *wp = wme->wp; struct window_pane *wp = wme->wp;
struct window_copy_mode_data *data = wme->data; struct window_copy_mode_data *data = wme->data;
struct screen_write_ctx ctx; struct screen *s = &data->screen;
struct screen_write_ctx ctx;
u_int i; u_int i;
if (window_copy_line_number_width(wme) != 0) {
screen_write_start(&ctx, &data->screen);
for (i = py; i < py + ny; i++)
window_copy_write_line(wme, &ctx, i);
screen_write_cursormove(&ctx,
window_copy_cursor_offset(wme, data->cx, screen_size_x(s)),
data->cy, 0);
screen_write_stop(&ctx);
wp->flags |= (PANE_REDRAW|PANE_REDRAWSCROLLBAR);
return;
}
screen_write_start_pane(&ctx, wp, NULL); screen_write_start_pane(&ctx, wp, NULL);
for (i = py; i < py + ny; i++) for (i = py; i < py + ny; i++)
window_copy_write_line(wme, &ctx, i); window_copy_write_line(wme, &ctx, i);
screen_write_cursormove(&ctx, data->cx, data->cy, 0); screen_write_cursormove(&ctx,
window_copy_cursor_offset(wme, data->cx, screen_size_x(s)), data->cy,
0);
screen_write_stop(&ctx); screen_write_stop(&ctx);
wp->flags |= PANE_REDRAWSCROLLBAR; wp->flags |= PANE_REDRAWSCROLLBAR;
@@ -4873,17 +5079,42 @@ window_copy_update_cursor(struct window_mode_entry *wme, u_int cx, u_int cy)
struct window_copy_mode_data *data = wme->data; struct window_copy_mode_data *data = wme->data;
struct screen *s = &data->screen; struct screen *s = &data->screen;
struct screen_write_ctx ctx; struct screen_write_ctx ctx;
u_int old_cx, old_cy; u_int old_cx, old_cy, width, content_sx;
old_cx = data->cx; old_cy = data->cy; old_cx = data->cx; old_cy = data->cy;
data->cx = cx; data->cy = cy; data->cx = cx; data->cy = cy;
if (window_copy_line_numbers_active(wme)) {
width = window_copy_line_number_width(wme);
if (s->sel != NULL || data->lineflag != LINE_SEL_NONE ||
old_cy != data->cy) {
window_copy_redraw_screen(wme);
return;
}
if (width >= screen_size_x(s))
content_sx = 1;
else
content_sx = screen_size_x(s) - width;
if (old_cx >= content_sx || data->cx >= content_sx) {
window_copy_redraw_screen(wme);
return;
}
screen_write_start_pane(&ctx, wp, NULL);
screen_write_cursormove(&ctx,
window_copy_cursor_offset(wme, data->cx, screen_size_x(s)),
data->cy, 0);
screen_write_stop(&ctx);
return;
}
if (old_cx == screen_size_x(s)) if (old_cx == screen_size_x(s))
window_copy_redraw_lines(wme, old_cy, 1); window_copy_redraw_lines(wme, old_cy, 1);
if (data->cx == screen_size_x(s)) if (data->cx == screen_size_x(s))
window_copy_redraw_lines(wme, data->cy, 1); window_copy_redraw_lines(wme, data->cy, 1);
else { else {
screen_write_start_pane(&ctx, wp, NULL); screen_write_start_pane(&ctx, wp, NULL);
screen_write_cursormove(&ctx, data->cx, data->cy, 0); screen_write_cursormove(&ctx,
window_copy_cursor_offset(wme, data->cx, screen_size_x(s)),
data->cy, 0);
screen_write_stop(&ctx); screen_write_stop(&ctx);
} }
} }
@@ -4958,7 +5189,7 @@ window_copy_set_selection(struct window_mode_entry *wme, int may_redraw,
struct screen *s = &data->screen; struct screen *s = &data->screen;
struct options *oo = wp->window->options; struct options *oo = wp->window->options;
struct grid_cell gc; struct grid_cell gc;
u_int sx, sy, cy, endsx, endsy; u_int sx, sy, cy, endsx, endsy, clipx;
int startrelpos, endrelpos; int startrelpos, endrelpos;
struct format_tree *ft; struct format_tree *ft;
@@ -4986,8 +5217,15 @@ window_copy_set_selection(struct window_mode_entry *wme, int may_redraw,
style_apply(&gc, oo, "copy-mode-selection-style", ft); style_apply(&gc, oo, "copy-mode-selection-style", ft);
gc.flags |= GRID_FLAG_NOPALETTE; gc.flags |= GRID_FLAG_NOPALETTE;
format_free(ft); format_free(ft);
clipx = window_copy_line_number_width(wme);
if (clipx >= screen_size_x(s))
clipx = screen_size_x(s) - 1;
if (window_copy_line_numbers_active(wme)) {
sx = window_copy_cursor_offset(wme, sx, screen_size_x(s));
endsx = window_copy_cursor_offset(wme, endsx, screen_size_x(s));
}
screen_set_selection(s, sx, sy, endsx, endsy, data->rectflag, screen_set_selection(s, sx, sy, endsx, endsy, data->rectflag,
data->modekeys, &gc); clipx, data->modekeys, &gc);
if (data->rectflag && may_redraw) { if (data->rectflag && may_redraw) {
/* /*
@@ -5143,12 +5381,20 @@ window_copy_copy_buffer(struct window_mode_entry *wme, const char *prefix,
{ {
struct window_pane *wp = wme->wp; struct window_pane *wp = wme->wp;
struct screen_write_ctx ctx; struct screen_write_ctx ctx;
int redraw = 0;
if (set_clip && if (set_clip &&
options_get_number(global_options, "set-clipboard") != 0) { options_get_number(global_options, "set-clipboard") != 0) {
if (window_copy_line_numbers_active(wme) &&
(wp->flags & PANE_REDRAW)) {
/* Clear PANE_REDRAW so clipboard write not skipped. */
redraw = PANE_REDRAW;
wp->flags &= ~PANE_REDRAW;
}
screen_write_start_pane(&ctx, wp, NULL); screen_write_start_pane(&ctx, wp, NULL);
screen_write_setselection(&ctx, "", buf, len); screen_write_setselection(&ctx, "", buf, len);
screen_write_stop(&ctx); screen_write_stop(&ctx);
wp->flags |= redraw;
notify_pane("pane-set-clipboard", wp); notify_pane("pane-set-clipboard", wp);
} }
@@ -5922,6 +6168,32 @@ window_copy_scroll_up(struct window_mode_entry *wme, u_int ny)
if (data->searchmark != NULL && !data->timeout) if (data->searchmark != NULL && !data->timeout)
window_copy_search_marks(wme, NULL, data->searchregex, 1); window_copy_search_marks(wme, NULL, data->searchregex, 1);
window_copy_update_selection(wme, 0, 0); window_copy_update_selection(wme, 0, 0);
if (window_copy_line_numbers_active(wme)) {
if (window_copy_line_number_mode(wme) !=
WINDOW_COPY_LINE_NUMBERS_ABSOLUTE) {
window_copy_redraw_screen(wme);
return;
}
screen_write_start(&ctx, &data->screen);
screen_write_cursormove(&ctx, 0, 0, 0);
screen_write_deleteline(&ctx, ny, 8);
window_copy_write_lines(wme, &ctx, screen_size_y(s) - ny, ny);
window_copy_write_line(wme, &ctx, 0);
if (screen_size_y(s) > 1)
window_copy_write_line(wme, &ctx, 1);
if (screen_size_y(s) > 3)
window_copy_write_line(wme, &ctx, screen_size_y(s) - 2);
if (s->sel != NULL && screen_size_y(s) > ny) {
window_copy_write_line(wme, &ctx,
screen_size_y(s) - ny - 1);
}
screen_write_cursormove(&ctx,
window_copy_cursor_offset(wme, data->cx, screen_size_x(s)),
data->cy, 0);
screen_write_stop(&ctx);
wp->flags |= (PANE_REDRAW|PANE_REDRAWSCROLLBAR);
return;
}
screen_write_start_pane(&ctx, wp, NULL); screen_write_start_pane(&ctx, wp, NULL);
screen_write_cursormove(&ctx, 0, 0, 0); screen_write_cursormove(&ctx, 0, 0, 0);
@@ -5934,7 +6206,9 @@ window_copy_scroll_up(struct window_mode_entry *wme, u_int ny)
window_copy_write_line(wme, &ctx, screen_size_y(s) - 2); window_copy_write_line(wme, &ctx, screen_size_y(s) - 2);
if (s->sel != NULL && screen_size_y(s) > ny) if (s->sel != NULL && screen_size_y(s) > ny)
window_copy_write_line(wme, &ctx, screen_size_y(s) - ny - 1); window_copy_write_line(wme, &ctx, screen_size_y(s) - ny - 1);
screen_write_cursormove(&ctx, data->cx, data->cy, 0); screen_write_cursormove(&ctx,
window_copy_cursor_offset(wme, data->cx, screen_size_x(s)), data->cy,
0);
screen_write_stop(&ctx); screen_write_stop(&ctx);
wp->flags |= PANE_REDRAWSCROLLBAR; wp->flags |= PANE_REDRAWSCROLLBAR;
} }
@@ -5959,6 +6233,27 @@ window_copy_scroll_down(struct window_mode_entry *wme, u_int ny)
if (data->searchmark != NULL && !data->timeout) if (data->searchmark != NULL && !data->timeout)
window_copy_search_marks(wme, NULL, data->searchregex, 1); window_copy_search_marks(wme, NULL, data->searchregex, 1);
window_copy_update_selection(wme, 0, 0); window_copy_update_selection(wme, 0, 0);
if (window_copy_line_numbers_active(wme)) {
if (window_copy_line_number_mode(wme) !=
WINDOW_COPY_LINE_NUMBERS_ABSOLUTE) {
window_copy_redraw_screen(wme);
return;
}
screen_write_start(&ctx, &data->screen);
screen_write_cursormove(&ctx, 0, 0, 0);
screen_write_insertline(&ctx, ny, 8);
window_copy_write_lines(wme, &ctx, 0, ny);
if (s->sel != NULL && screen_size_y(s) > ny)
window_copy_write_line(wme, &ctx, ny);
else if (ny == 1)
window_copy_write_line(wme, &ctx, 1);
screen_write_cursormove(&ctx,
window_copy_cursor_offset(wme, data->cx, screen_size_x(s)),
data->cy, 0);
screen_write_stop(&ctx);
wp->flags |= (PANE_REDRAW|PANE_REDRAWSCROLLBAR);
return;
}
screen_write_start_pane(&ctx, wp, NULL); screen_write_start_pane(&ctx, wp, NULL);
screen_write_cursormove(&ctx, 0, 0, 0); screen_write_cursormove(&ctx, 0, 0, 0);
@@ -5968,7 +6263,8 @@ window_copy_scroll_down(struct window_mode_entry *wme, u_int ny)
window_copy_write_line(wme, &ctx, ny); window_copy_write_line(wme, &ctx, ny);
else if (ny == 1) /* nuke position */ else if (ny == 1) /* nuke position */
window_copy_write_line(wme, &ctx, 1); window_copy_write_line(wme, &ctx, 1);
screen_write_cursormove(&ctx, data->cx, data->cy, 0); screen_write_cursormove(&ctx, window_copy_cursor_offset(wme, data->cx,
screen_size_x(s)), data->cy, 0);
screen_write_stop(&ctx); screen_write_stop(&ctx);
wp->flags |= PANE_REDRAWSCROLLBAR; wp->flags |= PANE_REDRAWSCROLLBAR;
} }
@@ -5996,6 +6292,7 @@ window_copy_move_mouse(struct mouse_event *m)
struct window_pane *wp; struct window_pane *wp;
struct window_mode_entry *wme; struct window_mode_entry *wme;
u_int x, y; u_int x, y;
struct window_copy_mode_data *data;
wp = cmd_mouse_pane(m, NULL, NULL); wp = cmd_mouse_pane(m, NULL, NULL);
if (wp == NULL) if (wp == NULL)
@@ -6009,6 +6306,8 @@ window_copy_move_mouse(struct mouse_event *m)
if (cmd_mouse_at(wp, m, &x, &y, 0) != 0) if (cmd_mouse_at(wp, m, &x, &y, 0) != 0)
return; return;
data = wme->data;
x = window_copy_cursor_unoffset(wme, x, screen_size_x(&data->screen));
window_copy_update_cursor(wme, x, y); window_copy_update_cursor(wme, x, y);
} }
@@ -6039,6 +6338,7 @@ window_copy_start_drag(struct client *c, struct mouse_event *m)
c->tty.mouse_drag_release = window_copy_drag_release; c->tty.mouse_drag_release = window_copy_drag_release;
data = wme->data; data = wme->data;
x = window_copy_cursor_unoffset(wme, x, screen_size_x(&data->screen));
yg = screen_hsize(data->backing) + y - data->oy; yg = screen_hsize(data->backing) + y - data->oy;
if (x < data->selrx || x > data->endselrx || yg != data->selry) if (x < data->selrx || x > data->endselrx || yg != data->selry)
data->selflag = SEL_CHAR; data->selflag = SEL_CHAR;
@@ -6093,6 +6393,7 @@ window_copy_drag_update(struct client *c, struct mouse_event *m)
if (cmd_mouse_at(wp, m, &x, &y, 0) != 0) if (cmd_mouse_at(wp, m, &x, &y, 0) != 0)
return; return;
x = window_copy_cursor_unoffset(wme, x, screen_size_x(&data->screen));
old_cx = data->cx; old_cx = data->cx;
old_cy = data->cy; old_cy = data->cy;
@@ -6130,6 +6431,8 @@ window_copy_drag_release(struct client *c, struct mouse_event *m)
return; return;
data = wme->data; data = wme->data;
if (window_copy_line_numbers_active(wme))
window_copy_drag_update(c, m);
evtimer_del(&data->dragtimer); evtimer_del(&data->dragtimer);
} }