diff --git a/screen-write.c b/screen-write.c index 842d27cf..fac5229e 100644 --- a/screen-write.c +++ b/screen-write.c @@ -1343,7 +1343,7 @@ screen_write_collect_add(struct screen_write_ctx *ctx, collect = 0; else if (s->mode & MODE_INSERT) collect = 0; - else if (s->sel.flag) + else if (s->sel != NULL) collect = 0; if (!collect) { screen_write_collect_end(ctx); diff --git a/screen.c b/screen.c index d2cf0724..6fbd86f4 100644 --- a/screen.c +++ b/screen.c @@ -25,6 +25,22 @@ #include "tmux.h" +/* Selected area in screen. */ +struct screen_sel { + int hidden; + int rectangle; + int modekeys; + + u_int sx; + u_int sy; + + u_int ex; + u_int ey; + + struct grid_cell cell; +}; + +/* Entry on title stack. */ struct screen_title_entry { char *text; @@ -67,6 +83,7 @@ screen_init(struct screen *s, u_int sx, u_int sy, u_int hlimit) s->cstyle = 0; s->ccolour = xstrdup(""); s->tabs = NULL; + s->sel = NULL; screen_reinit(s); } @@ -95,6 +112,7 @@ screen_reinit(struct screen *s) void screen_free(struct screen *s) { + free(s->sel); free(s->tabs); free(s->title); free(s->ccolour); @@ -317,51 +335,49 @@ screen_resize_y(struct screen *s, u_int sy) /* Set selection. */ void screen_set_selection(struct screen *s, u_int sx, u_int sy, - u_int ex, u_int ey, u_int rectflag, struct grid_cell *gc) + u_int ex, u_int ey, u_int rectangle, int modekeys, struct grid_cell *gc) { - struct screen_sel *sel = &s->sel; + if (s->sel == NULL) + s->sel = xcalloc(1, sizeof *s->sel); - memcpy(&sel->cell, gc, sizeof sel->cell); - sel->flag = 1; - sel->hidden = 0; + memcpy(&s->sel->cell, gc, sizeof s->sel->cell); + s->sel->hidden = 0; + s->sel->rectangle = rectangle; + s->sel->modekeys = modekeys; - sel->rectflag = rectflag; - - sel->sx = sx; sel->sy = sy; - sel->ex = ex; sel->ey = ey; + s->sel->sx = sx; + s->sel->sy = sy; + s->sel->ex = ex; + s->sel->ey = ey; } /* Clear selection. */ void screen_clear_selection(struct screen *s) { - struct screen_sel *sel = &s->sel; - - sel->flag = 0; - sel->hidden = 0; - sel->lineflag = LINE_SEL_NONE; + free(s->sel); + s->sel = NULL; } /* Hide selection. */ void screen_hide_selection(struct screen *s) { - struct screen_sel *sel = &s->sel; - - sel->hidden = 1; + if (s->sel != NULL) + s->sel->hidden = 1; } /* Check if cell in selection. */ int screen_check_selection(struct screen *s, u_int px, u_int py) { - struct screen_sel *sel = &s->sel; + struct screen_sel *sel = s->sel; u_int xx; - if (!sel->flag || sel->hidden) + if (sel == NULL || sel->hidden) return (0); - if (sel->rectflag) { + if (sel->rectangle) { if (sel->sy < sel->ey) { /* start line < end line -- downward selection. */ if (py < sel->sy || py > sel->ey) @@ -454,10 +470,10 @@ void screen_select_cell(struct screen *s, struct grid_cell *dst, const struct grid_cell *src) { - if (!s->sel.flag || s->sel.hidden) + if (s->sel == NULL || s->sel->hidden) return; - memcpy(dst, &s->sel.cell, sizeof *dst); + memcpy(dst, &s->sel->cell, sizeof *dst); utf8_copy(&dst->data, &src->data); dst->attr = dst->attr & ~GRID_ATTR_CHARSET; diff --git a/tmux.h b/tmux.h index 76ea5a5a..af3dddb9 100644 --- a/tmux.h +++ b/tmux.h @@ -644,30 +644,8 @@ struct job { }; LIST_HEAD(joblist, job); -/* Screen selection. */ -struct screen_sel { - int flag; - int hidden; - - int rectflag; - enum { - LINE_SEL_NONE, - LINE_SEL_LEFT_RIGHT, - LINE_SEL_RIGHT_LEFT, - } lineflag; - - int modekeys; - - u_int sx; - u_int sy; - - u_int ex; - u_int ey; - - struct grid_cell cell; -}; - /* Virtual screen. */ +struct screen_sel; struct screen_titles; struct screen { char *title; @@ -688,7 +666,7 @@ struct screen { bitstr_t *tabs; - struct screen_sel sel; + struct screen_sel *sel; }; /* Screen write context. */ @@ -2086,8 +2064,8 @@ void screen_set_title(struct screen *, const char *); void screen_push_title(struct screen *); void screen_pop_title(struct screen *); void screen_resize(struct screen *, u_int, u_int, int); -void screen_set_selection(struct screen *, - u_int, u_int, u_int, u_int, u_int, struct grid_cell *); +void screen_set_selection(struct screen *, u_int, u_int, u_int, u_int, + u_int, int, struct grid_cell *); void screen_clear_selection(struct screen *); void screen_hide_selection(struct screen *); int screen_check_selection(struct screen *, u_int, u_int); diff --git a/window-copy.c b/window-copy.c index 59c70230..a36d2d48 100644 --- a/window-copy.c +++ b/window-copy.c @@ -65,8 +65,9 @@ static void window_copy_update_cursor(struct window_pane *, u_int, u_int); static void window_copy_start_selection(struct window_pane *); static int window_copy_adjust_selection(struct window_pane *, u_int *, u_int *); +static int window_copy_set_selection(struct window_pane *, int); static int window_copy_update_selection(struct window_pane *, int); -static void window_copy_synchronize_cursor(struct window_pane *wp); +static void window_copy_synchronize_cursor(struct window_pane *); static void *window_copy_get_selection(struct window_pane *, size_t *); static void window_copy_copy_buffer(struct window_pane *, const char *, void *, size_t); @@ -151,12 +152,12 @@ struct window_copy_mode_data { struct screen *backing; int backing_written; /* backing display started */ - u_int oy; /* number of lines scrolled up */ + u_int oy; /* number of lines scrolled up */ - u_int selx; /* beginning of selection */ + u_int selx; /* beginning of selection */ u_int sely; - u_int endselx; /* end of selection */ + u_int endselx; /* end of selection */ u_int endsely; enum { @@ -165,14 +166,20 @@ struct window_copy_mode_data { CURSORDRAG_SEL, /* start is synchronized with cursor */ } cursordrag; + int modekeys; + enum { + LINE_SEL_NONE, + LINE_SEL_LEFT_RIGHT, + LINE_SEL_RIGHT_LEFT, + } lineflag; /* line selection mode */ int rectflag; /* in rectangle copy mode? */ int scroll_exit; /* exit on scroll to end? */ u_int cx; u_int cy; - u_int lastcx; /* position in last line w/ content */ - u_int lastsx; /* size of last line w/ content */ + u_int lastcx; /* position in last line w/ content */ + u_int lastsx; /* size of last line w/ content */ int searchtype; char *searchstr; @@ -228,7 +235,7 @@ window_copy_init(struct window_pane *wp, __unused struct cmd_find_state *fs, s = &data->screen; screen_init(s, screen_size_x(&wp->base), screen_size_y(&wp->base), 0); - s->sel.modekeys = options_get_number(wp->window->options, "mode-keys"); + data->modekeys = options_get_number(wp->window->options, "mode-keys"); data->backing = NULL; @@ -357,7 +364,7 @@ window_copy_pageup(struct window_pane *wp, int half_page) oy = screen_hsize(data->backing) + data->cy - data->oy; ox = window_copy_find_length(wp, oy); - if (s->sel.lineflag == LINE_SEL_LEFT_RIGHT && oy == data->sely) + if (data->lineflag == LINE_SEL_LEFT_RIGHT && oy == data->sely) window_copy_other_end(wp); if (data->cx != ox) { @@ -379,7 +386,7 @@ window_copy_pageup(struct window_pane *wp, int half_page) else data->oy += n; - if (!data->screen.sel.flag || !data->rectflag) { + if (data->screen.sel == NULL || !data->rectflag) { py = screen_hsize(data->backing) + data->cy - data->oy; px = window_copy_find_length(wp, py); if ((data->cx >= data->lastsx && data->cx != px) || @@ -401,7 +408,7 @@ window_copy_pagedown(struct window_pane *wp, int half_page, int scroll_exit) oy = screen_hsize(data->backing) + data->cy - data->oy; ox = window_copy_find_length(wp, oy); - if (s->sel.lineflag == LINE_SEL_RIGHT_LEFT && oy == data->sely) + if (data->lineflag == LINE_SEL_RIGHT_LEFT && oy == data->sely) window_copy_other_end(wp); if (data->cx != ox) { @@ -423,7 +430,7 @@ window_copy_pagedown(struct window_pane *wp, int half_page, int scroll_exit) else data->oy -= n; - if (!data->screen.sel.flag || !data->rectflag) { + if (data->screen.sel == NULL || !data->rectflag) { py = screen_hsize(data->backing) + data->cy - data->oy; px = window_copy_find_length(wp, py); if ((data->cx >= data->lastsx && data->cx != px) || @@ -554,7 +561,7 @@ window_copy_command(struct window_pane *wp, struct client *c, struct session *s, if (m != NULL) window_copy_start_drag(c, m); else { - sn->sel.lineflag = LINE_SEL_NONE; + data->lineflag = LINE_SEL_NONE; window_copy_start_selection(wp); redraw = 1; } @@ -763,7 +770,7 @@ window_copy_command(struct window_pane *wp, struct client *c, struct session *s, window_copy_cursor_previous_word(wp, ws); } if (strcmp(command, "rectangle-toggle") == 0) { - sn->sel.lineflag = LINE_SEL_NONE; + data->lineflag = LINE_SEL_NONE; window_copy_rectangle_toggle(wp); } if (strcmp(command, "scroll-down") == 0 || @@ -800,7 +807,7 @@ window_copy_command(struct window_pane *wp, struct client *c, struct session *s, } } if (strcmp(command, "select-line") == 0) { - sn->sel.lineflag = LINE_SEL_LEFT_RIGHT; + data->lineflag = LINE_SEL_LEFT_RIGHT; data->rectflag = 0; window_copy_cursor_start_of_line(wp); window_copy_start_selection(wp); @@ -810,7 +817,7 @@ window_copy_command(struct window_pane *wp, struct client *c, struct session *s, redraw = 1; } if (strcmp(command, "select-word") == 0) { - sn->sel.lineflag = LINE_SEL_LEFT_RIGHT; + data->lineflag = LINE_SEL_LEFT_RIGHT; data->rectflag = 0; ws = options_get_string(s->options, "word-separators"); window_copy_cursor_previous_word(wp, ws); @@ -1434,7 +1441,6 @@ static void window_copy_start_selection(struct window_pane *wp) { struct window_copy_mode_data *data = wp->modedata; - struct screen *s = &data->screen; data->selx = data->cx; data->sely = screen_hsize(data->backing) + data->cy - data->oy; @@ -1444,8 +1450,7 @@ window_copy_start_selection(struct window_pane *wp) data->cursordrag = CURSORDRAG_ENDSEL; - s->sel.flag = 1; - window_copy_update_selection(wp, 1); + window_copy_set_selection(wp, 1); } static int @@ -1482,6 +1487,17 @@ window_copy_adjust_selection(struct window_pane *wp, u_int *selx, u_int *sely) static int window_copy_update_selection(struct window_pane *wp, int may_redraw) +{ + struct window_copy_mode_data *data = wp->modedata; + struct screen *s = &data->screen; + + if (s->sel == NULL && data->lineflag == LINE_SEL_NONE) + return (0); + return (window_copy_set_selection(wp, may_redraw)); +} + +static int +window_copy_set_selection(struct window_pane *wp, int may_redraw) { struct window_copy_mode_data *data = wp->modedata; struct screen *s = &data->screen; @@ -1490,9 +1506,6 @@ window_copy_update_selection(struct window_pane *wp, int may_redraw) u_int sx, sy, cy, endsx, endsy; int startrelpos, endrelpos; - if (!s->sel.flag && s->sel.lineflag == LINE_SEL_NONE) - return (0); - window_copy_synchronize_cursor(wp); /* Adjust the selection. */ @@ -1515,7 +1528,8 @@ window_copy_update_selection(struct window_pane *wp, int may_redraw) /* Set colours and selection. */ style_apply(&gc, oo, "mode-style"); gc.flags |= GRID_FLAG_NOPALETTE; - screen_set_selection(s, sx, sy, endsx, endsy, data->rectflag, &gc); + screen_set_selection(s, sx, sy, endsx, endsy, data->rectflag, + data->modekeys, &gc); if (data->rectflag && may_redraw) { /* @@ -1551,7 +1565,7 @@ window_copy_get_selection(struct window_pane *wp, size_t *len) u_int firstsx, lastex, restex, restsx, selx; int keys; - if (!s->sel.flag && s->sel.lineflag == LINE_SEL_NONE) + if (data->screen.sel == NULL && data->lineflag == LINE_SEL_NONE) return (NULL); buf = xmalloc(1); @@ -1860,11 +1874,10 @@ window_copy_cursor_start_of_line(struct window_pane *wp) { struct window_copy_mode_data *data = wp->modedata; struct screen *back_s = data->backing; - struct screen *s = &data->screen; struct grid *gd = back_s->grid; u_int py; - if (data->cx == 0 && s->sel.lineflag == LINE_SEL_NONE) { + if (data->cx == 0 && data->lineflag == LINE_SEL_NONE) { py = screen_hsize(back_s) + data->cy - data->oy; while (py > 0 && grid_get_line(gd, py - 1)->flags & GRID_LINE_WRAPPED) { @@ -1905,7 +1918,6 @@ window_copy_cursor_end_of_line(struct window_pane *wp) { struct window_copy_mode_data *data = wp->modedata; struct screen *back_s = data->backing; - struct screen *s = &data->screen; struct grid *gd = back_s->grid; struct grid_line *gl; u_int px, py; @@ -1913,8 +1925,8 @@ window_copy_cursor_end_of_line(struct window_pane *wp) py = screen_hsize(back_s) + data->cy - data->oy; px = window_copy_find_length(wp, py); - if (data->cx == px && s->sel.lineflag == LINE_SEL_NONE) { - if (data->screen.sel.flag && data->rectflag) + if (data->cx == px && data->lineflag == LINE_SEL_NONE) { + if (data->screen.sel != NULL && data->rectflag) px = screen_size_x(back_s); gl = grid_get_line(gd, py); if (gl->flags & GRID_LINE_WRAPPED) { @@ -1941,13 +1953,13 @@ window_copy_other_end(struct window_pane *wp) struct screen *s = &data->screen; u_int selx, sely, cy, yy, hsize; - if (!s->sel.flag && s->sel.lineflag == LINE_SEL_NONE) + if (s->sel == NULL && data->lineflag == LINE_SEL_NONE) return; - if (s->sel.lineflag == LINE_SEL_LEFT_RIGHT) - s->sel.lineflag = LINE_SEL_RIGHT_LEFT; - else if (s->sel.lineflag == LINE_SEL_RIGHT_LEFT) - s->sel.lineflag = LINE_SEL_LEFT_RIGHT; + if (data->lineflag == LINE_SEL_LEFT_RIGHT) + data->lineflag = LINE_SEL_RIGHT_LEFT; + else if (data->lineflag == LINE_SEL_RIGHT_LEFT) + data->lineflag = LINE_SEL_LEFT_RIGHT; switch (data->cursordrag) { case CURSORDRAG_NONE: @@ -2019,7 +2031,7 @@ window_copy_cursor_right(struct window_pane *wp) py = screen_hsize(data->backing) + data->cy - data->oy; yy = screen_hsize(data->backing) + screen_size_y(data->backing) - 1; - if (data->screen.sel.flag && data->rectflag) + if (data->screen.sel != NULL && data->rectflag) px = screen_size_x(&data->screen); else px = window_copy_find_length(wp, py); @@ -2056,7 +2068,7 @@ window_copy_cursor_up(struct window_pane *wp, int scroll_only) data->lastsx = ox; } - if (s->sel.lineflag == LINE_SEL_LEFT_RIGHT && oy == data->sely) + if (data->lineflag == LINE_SEL_LEFT_RIGHT && oy == data->sely) window_copy_other_end(wp); data->cx = data->lastcx; @@ -2078,7 +2090,7 @@ window_copy_cursor_up(struct window_pane *wp, int scroll_only) } } - if (!data->screen.sel.flag || !data->rectflag) { + if (data->screen.sel != NULL || !data->rectflag) { py = screen_hsize(data->backing) + data->cy - data->oy; px = window_copy_find_length(wp, py); if ((data->cx >= data->lastsx && data->cx != px) || @@ -2086,9 +2098,9 @@ window_copy_cursor_up(struct window_pane *wp, int scroll_only) window_copy_cursor_end_of_line(wp); } - if (s->sel.lineflag == LINE_SEL_LEFT_RIGHT) + if (data->lineflag == LINE_SEL_LEFT_RIGHT) window_copy_cursor_end_of_line(wp); - else if (s->sel.lineflag == LINE_SEL_RIGHT_LEFT) + else if (data->lineflag == LINE_SEL_RIGHT_LEFT) window_copy_cursor_start_of_line(wp); } @@ -2106,7 +2118,7 @@ window_copy_cursor_down(struct window_pane *wp, int scroll_only) data->lastsx = ox; } - if (s->sel.lineflag == LINE_SEL_RIGHT_LEFT && oy == data->endsely) + if (data->lineflag == LINE_SEL_RIGHT_LEFT && oy == data->endsely) window_copy_other_end(wp); data->cx = data->lastcx; @@ -2120,7 +2132,7 @@ window_copy_cursor_down(struct window_pane *wp, int scroll_only) window_copy_redraw_lines(wp, data->cy - 1, 2); } - if (!data->screen.sel.flag || !data->rectflag) { + if (data->screen.sel == NULL || !data->rectflag) { py = screen_hsize(data->backing) + data->cy - data->oy; px = window_copy_find_length(wp, py); if ((data->cx >= data->lastsx && data->cx != px) || @@ -2128,9 +2140,9 @@ window_copy_cursor_down(struct window_pane *wp, int scroll_only) window_copy_cursor_end_of_line(wp); } - if (s->sel.lineflag == LINE_SEL_LEFT_RIGHT) + if (data->lineflag == LINE_SEL_LEFT_RIGHT) window_copy_cursor_end_of_line(wp); - else if (s->sel.lineflag == LINE_SEL_RIGHT_LEFT) + else if (data->lineflag == LINE_SEL_RIGHT_LEFT) window_copy_cursor_start_of_line(wp); } @@ -2401,7 +2413,7 @@ window_copy_scroll_up(struct window_pane *wp, u_int ny) window_copy_write_line(wp, &ctx, 1); if (screen_size_y(s) > 3) window_copy_write_line(wp, &ctx, screen_size_y(s) - 2); - if (s->sel.flag && screen_size_y(s) > ny) + if (s->sel != NULL && screen_size_y(s) > ny) window_copy_write_line(wp, &ctx, screen_size_y(s) - ny - 1); screen_write_cursormove(&ctx, data->cx, data->cy); screen_write_stop(&ctx); @@ -2429,7 +2441,7 @@ window_copy_scroll_down(struct window_pane *wp, u_int ny) screen_write_cursormove(&ctx, 0, 0); screen_write_insertline(&ctx, ny, 8); window_copy_write_lines(wp, &ctx, 0, ny); - if (s->sel.flag && screen_size_y(s) > ny) + if (s->sel != NULL && screen_size_y(s) > ny) window_copy_write_line(wp, &ctx, ny); else if (ny == 1) /* nuke position */ window_copy_write_line(wp, &ctx, 1); @@ -2445,7 +2457,7 @@ window_copy_add_formats(struct window_pane *wp, struct format_tree *ft) if (wp->mode != &window_copy_mode) return; - format_add(ft, "selection_present", "%d", data->screen.sel.flag); + format_add(ft, "selection_present", "%d", data->screen.sel != NULL); format_add(ft, "scroll_position", "%d", data->oy); format_add(ft, "rectangle_toggle", "%d", data->rectflag); }