-/* $OpenBSD: window-copy.c,v 1.314 2021/02/08 14:46:53 nicm Exp $ */
+/* $OpenBSD: window-copy.c,v 1.315 2021/02/22 06:53:04 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
static void window_copy_drag_update(struct client *, struct mouse_event *);
static void window_copy_drag_release(struct client *, struct mouse_event *);
static void window_copy_jump_to_mark(struct window_mode_entry *);
+static void window_copy_acquire_cursor_up(struct window_mode_entry *,
+ u_int, u_int, u_int, u_int, u_int);
+static void window_copy_acquire_cursor_down(struct window_mode_entry *,
+ u_int, u_int, u_int, u_int, u_int, u_int, int);
const struct window_mode window_copy_mode = {
.name = "copy-mode",
#define WINDOW_COPY_SEARCH_TIMEOUT 10000
#define WINDOW_COPY_SEARCH_ALL_TIMEOUT 200
- int jumptype;
- char jumpchar;
+ int jumptype;
+ struct utf8_data *jumpchar;
struct event dragtimer;
#define WINDOW_COPY_DRAG_REPEAT_TIME 50000
data->searchall = 1;
data->jumptype = WINDOW_COPY_OFF;
- data->jumpchar = '\0';
+ data->jumpchar = NULL;
screen_init(&data->screen, screen_size_x(base), screen_size_y(base), 0);
data->modekeys = options_get_number(wp->window->options, "mode-keys");
free(data->searchmark);
free(data->searchstr);
+ free(data->jumpchar);
screen_free(data->backing);
free(data->backing);
if (*argument != '\0') {
data->jumptype = WINDOW_COPY_JUMPBACKWARD;
- data->jumpchar = *argument;
+ free(data->jumpchar);
+ data->jumpchar = utf8_fromcstr(argument);
for (; np != 0; np--)
window_copy_cursor_jump_back(wme);
}
if (*argument != '\0') {
data->jumptype = WINDOW_COPY_JUMPFORWARD;
- data->jumpchar = *argument;
+ free(data->jumpchar);
+ data->jumpchar = utf8_fromcstr(argument);
for (; np != 0; np--)
window_copy_cursor_jump(wme);
}
if (*argument != '\0') {
data->jumptype = WINDOW_COPY_JUMPTOBACKWARD;
- data->jumpchar = *argument;
+ free(data->jumpchar);
+ data->jumpchar = utf8_fromcstr(argument);
for (; np != 0; np--)
window_copy_cursor_jump_to_back(wme);
}
if (*argument != '\0') {
data->jumptype = WINDOW_COPY_JUMPTOFORWARD;
- data->jumpchar = *argument;
+ free(data->jumpchar);
+ data->jumpchar = utf8_fromcstr(argument);
for (; np != 0; np--)
window_copy_cursor_jump_to(wme);
}
struct window_copy_mode_data *data = wme->data;
struct screen *back_s = data->backing;
struct grid_reader gr;
- u_int px, py, cy, oldy, yy, ny, nd, hsize;
+ u_int px, py, oldy, hsize;
px = data->cx;
hsize = screen_hsize(back_s);
grid_reader_start(&gr, back_s->grid, px, py);
grid_reader_cursor_start_of_line(&gr, 1);
grid_reader_get_cursor(&gr, &px, &py);
-
- /* Scroll up if we went off the visible screen. */
- yy = hsize - data->oy;
- if (py < yy) {
- ny = yy - py;
- cy = 0;
- nd = 1;
- } else {
- ny = 0;
- cy = py - yy;
- nd = oldy - cy + 1;
- }
- while (ny > 0) {
- window_copy_cursor_up(wme, 1);
- ny--;
- }
- window_copy_update_cursor(wme, px, cy);
- if (window_copy_update_selection(wme, 1, 0))
- window_copy_redraw_lines(wme, data->cy, nd);
+ window_copy_acquire_cursor_up(wme, hsize, data->oy, oldy, px, py);
}
static void
struct window_copy_mode_data *data = wme->data;
struct screen *back_s = data->backing;
struct grid_reader gr;
- u_int px, py, cy, oldy, yy, ny, nd, hsize;
+ u_int px, py, oldy, hsize;
px = data->cx;
hsize = screen_hsize(back_s);
else
grid_reader_cursor_end_of_line(&gr, 1, 0);
grid_reader_get_cursor(&gr, &px, &py);
-
- /* Scroll down if we went off the visible screen. */
- cy = py - hsize + data->oy;
- yy = screen_size_y(back_s) - 1;
- if (cy > yy) {
- ny = cy - yy;
- oldy = yy;
- nd = 1;
- } else {
- ny = 0;
- nd = cy - oldy + 1;
- }
- while (ny > 0) {
- window_copy_cursor_down(wme, 1);
- ny--;
- }
- if (cy > yy)
- window_copy_update_cursor(wme, px, yy);
- else
- window_copy_update_cursor(wme, px, cy);
- if (window_copy_update_selection(wme, 1, 0))
- window_copy_redraw_lines(wme, oldy, nd);
+ window_copy_acquire_cursor_down(wme, hsize, screen_size_y(back_s),
+ data->oy, oldy, px, py, 0);
}
static void
struct window_copy_mode_data *data = wme->data;
struct screen *back_s = data->backing;
struct grid_reader gr;
- u_int px, py, cy, yy, ny, hsize;
+ u_int px, py, oldy, hsize;
px = data->cx;
hsize = screen_hsize(back_s);
py = hsize + data->cy - data->oy;
+ oldy = data->cy;
grid_reader_start(&gr, back_s->grid, px, py);
grid_reader_cursor_left(&gr);
grid_reader_get_cursor(&gr, &px, &py);
-
- /* Scroll up if we went off the visible screen. */
- yy = hsize - data->oy;
- if (py < yy) {
- ny = yy - py;
- cy = 0;
- } else {
- ny = 0;
- cy = py - yy;
- }
- while (ny > 0) {
- window_copy_cursor_up(wme, 1);
- ny--;
- }
- window_copy_update_cursor(wme, px, cy);
- if (window_copy_update_selection(wme, 1, 0))
- window_copy_redraw_lines(wme, data->cy, 1);
+ window_copy_acquire_cursor_up(wme, hsize, data->oy, oldy, px, py);
}
static void
struct window_copy_mode_data *data = wme->data;
struct screen *back_s = data->backing;
struct grid_reader gr;
- u_int px, py, cy, yy, ny, hsize;
+ u_int px, py, oldy, hsize;
px = data->cx;
hsize = screen_hsize(back_s);
py = hsize + data->cy - data->oy;
+ oldy = data->cy;
grid_reader_start(&gr, back_s->grid, px, py);
grid_reader_cursor_right(&gr, 1, all);
grid_reader_get_cursor(&gr, &px, &py);
-
- /* Scroll down if we went off the visible screen. */
- cy = py - hsize + data->oy;
- yy = screen_size_y(back_s) - 1;
- if (cy > yy)
- ny = cy - yy;
- else
- ny = 0;
- while (ny > 0) {
- window_copy_cursor_down(wme, 1);
- ny--;
- }
- if (cy > yy)
- window_copy_update_cursor(wme, px, yy);
- else
- window_copy_update_cursor(wme, px, cy);
- if (window_copy_update_selection(wme, 1, 0))
- window_copy_redraw_lines(wme, data->cy, 1);
+ window_copy_acquire_cursor_down(wme, hsize, screen_size_y(back_s),
+ data->oy, oldy, px, py, 0);
}
static void
{
struct window_copy_mode_data *data = wme->data;
struct screen *back_s = data->backing;
- struct grid_cell gc;
- u_int px, py, xx;
+ struct grid_reader gr;
+ u_int px, py, oldy, hsize;
px = data->cx + 1;
- py = screen_hsize(back_s) + data->cy - data->oy;
- xx = window_copy_find_length(wme, py);
+ hsize = screen_hsize(back_s);
+ py = hsize + data->cy - data->oy;
+ oldy = data->cy;
- while (px < xx) {
- grid_get_cell(back_s->grid, px, py, &gc);
- if (!(gc.flags & GRID_FLAG_PADDING) &&
- gc.data.size == 1 && *gc.data.data == data->jumpchar) {
- window_copy_update_cursor(wme, px, data->cy);
- if (window_copy_update_selection(wme, 1, 0))
- window_copy_redraw_lines(wme, data->cy, 1);
- return;
- }
- px++;
+ grid_reader_start(&gr, back_s->grid, px, py);
+ if (grid_reader_cursor_jump(&gr, data->jumpchar)) {
+ grid_reader_get_cursor(&gr, &px, &py);
+ window_copy_acquire_cursor_down(wme, hsize,
+ screen_size_y(back_s), data->oy, oldy, px, py, 0);
}
}
{
struct window_copy_mode_data *data = wme->data;
struct screen *back_s = data->backing;
- struct grid_cell gc;
- u_int px, py;
+ struct grid_reader gr;
+ u_int px, py, oldy, hsize;
px = data->cx;
- py = screen_hsize(back_s) + data->cy - data->oy;
+ hsize = screen_hsize(back_s);
+ py = hsize + data->cy - data->oy;
+ oldy = data->cy;
if (px > 0)
px--;
- for (;;) {
- grid_get_cell(back_s->grid, px, py, &gc);
- if (!(gc.flags & GRID_FLAG_PADDING) &&
- gc.data.size == 1 && *gc.data.data == data->jumpchar) {
- window_copy_update_cursor(wme, px, data->cy);
- if (window_copy_update_selection(wme, 1, 0))
- window_copy_redraw_lines(wme, data->cy, 1);
- return;
- }
- if (px == 0)
- break;
- px--;
+ grid_reader_start(&gr, back_s->grid, px, py);
+ if (grid_reader_cursor_jump_back(&gr, data->jumpchar)) {
+ grid_reader_get_cursor(&gr, &px, &py);
+ window_copy_acquire_cursor_up(wme, hsize, data->oy, oldy, px,
+ py);
}
}
{
struct window_copy_mode_data *data = wme->data;
struct screen *back_s = data->backing;
- struct grid_cell gc;
- u_int px, py, xx;
+ struct grid_reader gr;
+ u_int px, py, oldy, hsize;
px = data->cx + 2;
- py = screen_hsize(back_s) + data->cy - data->oy;
- xx = window_copy_find_length(wme, py);
+ hsize = screen_hsize(back_s);
+ py = hsize + data->cy - data->oy;
+ oldy = data->cy;
- while (px < xx) {
- grid_get_cell(back_s->grid, px, py, &gc);
- if (!(gc.flags & GRID_FLAG_PADDING) &&
- gc.data.size == 1 && *gc.data.data == data->jumpchar) {
- window_copy_update_cursor(wme, px - 1, data->cy);
- if (window_copy_update_selection(wme, 1, 0))
- window_copy_redraw_lines(wme, data->cy, 1);
- return;
- }
- px++;
+ grid_reader_start(&gr, back_s->grid, px, py);
+ if (grid_reader_cursor_jump(&gr, data->jumpchar)) {
+ grid_reader_cursor_left(&gr);
+ grid_reader_get_cursor(&gr, &px, &py);
+ window_copy_acquire_cursor_down(wme, hsize,
+ screen_size_y(back_s), data->oy, oldy, px, py, 0);
}
}
{
struct window_copy_mode_data *data = wme->data;
struct screen *back_s = data->backing;
- struct grid_cell gc;
- u_int px, py;
+ struct grid_reader gr;
+ u_int px, py, oldy, hsize;
px = data->cx;
- py = screen_hsize(back_s) + data->cy - data->oy;
+ hsize = screen_hsize(back_s);
+ py = hsize + data->cy - data->oy;
+ oldy = data->cy;
if (px > 0)
px--;
if (px > 0)
px--;
- for (;;) {
- grid_get_cell(back_s->grid, px, py, &gc);
- if (!(gc.flags & GRID_FLAG_PADDING) &&
- gc.data.size == 1 && *gc.data.data == data->jumpchar) {
- window_copy_update_cursor(wme, px + 1, data->cy);
- if (window_copy_update_selection(wme, 1, 0))
- window_copy_redraw_lines(wme, data->cy, 1);
- return;
- }
- if (px == 0)
- break;
- px--;
+ grid_reader_start(&gr, back_s->grid, px, py);
+ if (grid_reader_cursor_jump_back(&gr, data->jumpchar)) {
+ grid_reader_cursor_right(&gr, 1, 0);
+ grid_reader_get_cursor(&gr, &px, &py);
+ window_copy_acquire_cursor_up(wme, hsize, data->oy, oldy, px,
+ py);
}
}
struct window_copy_mode_data *data = wme->data;
struct screen *back_s = data->backing;
struct grid_reader gr;
- u_int px, py, cy, oldy, yy, ny, nd, hsize;
+ u_int px, py, oldy, hsize;
px = data->cx;
hsize = screen_hsize(back_s);
grid_reader_start(&gr, back_s->grid, px, py);
grid_reader_cursor_next_word(&gr, separators);
grid_reader_get_cursor(&gr, &px, &py);
-
- /* Scroll down if we went off the visible screen. */
- cy = py - hsize + data->oy;
- yy = screen_size_y(back_s) - 1;
- if (cy > yy) {
- ny = cy - yy;
- oldy = yy;
- nd = 1;
- } else {
- ny = 0;
- nd = cy - oldy + 1;
- }
- while (ny > 0) {
- window_copy_cursor_down(wme, 1);
- ny--;
- }
- if (cy > yy)
- window_copy_update_cursor(wme, px, yy);
- else
- window_copy_update_cursor(wme, px, cy);
- if (window_copy_update_selection(wme, 1, 0))
- window_copy_redraw_lines(wme, oldy, nd);
+ window_copy_acquire_cursor_down(wme, hsize, screen_size_y(back_s),
+ data->oy, oldy, px, py, 0);
}
static void
struct options *oo = wp->window->options;
struct screen *back_s = data->backing;
struct grid_reader gr;
- u_int px, py, cy, oldy, yy, ny, nd, hsize;
+ u_int px, py, oldy, hsize;
int keys;
px = data->cx;
if (keys == MODEKEY_VI)
grid_reader_cursor_left(&gr);
grid_reader_get_cursor(&gr, &px, &py);
-
- /* Scroll down if we went off the visible screen. */
- cy = py - hsize + data->oy;
- yy = screen_size_y(back_s) - 1;
- if (cy > yy) {
- ny = cy - yy;
- oldy = yy;
- nd = 1;
- } else {
- ny = 0;
- nd = cy - oldy + 1;
- }
- while (ny > 0) {
- window_copy_cursor_down(wme, 1);
- ny--;
- }
- if (cy > yy)
- window_copy_update_cursor(wme, px, yy);
- else
- window_copy_update_cursor(wme, px, cy);
- if (window_copy_update_selection(wme, 1, no_reset))
- window_copy_redraw_lines(wme, oldy, nd);
+ window_copy_acquire_cursor_down(wme, hsize, screen_size_y(back_s),
+ data->oy, oldy, px, py, no_reset);
}
/* Compute the previous place where a word begins. */
struct window_copy_mode_data *data = wme->data;
struct screen *back_s = data->backing;
struct grid_reader gr;
- u_int px, py, cy, oldy, yy, ny, nd, hsize;
+ u_int px, py, oldy, hsize;
px = data->cx;
hsize = screen_hsize(back_s);
grid_reader_start(&gr, back_s->grid, px, py);
grid_reader_cursor_previous_word(&gr, separators, already);
grid_reader_get_cursor(&gr, &px, &py);
-
- /* Scroll up if we went off the visible screen. */
- yy = hsize - data->oy;
- if (py < yy) {
- ny = yy - py;
- cy = 0;
- nd = 1;
- } else {
- ny = 0;
- cy = py - yy;
- nd = oldy - cy + 1;
- }
- while (ny > 0) {
- window_copy_cursor_up(wme, 1);
- ny--;
- }
- window_copy_update_cursor(wme, px, cy);
- if (window_copy_update_selection(wme, 1, 0))
- window_copy_redraw_lines(wme, data->cy, nd);
+ window_copy_acquire_cursor_up(wme, hsize, data->oy, oldy, px, py);
}
static void
window_copy_update_selection(wme, 0, 0);
window_copy_redraw_screen(wme);
}
+
+/* Scroll up if the cursor went off the visible screen. */
+static void
+window_copy_acquire_cursor_up(struct window_mode_entry *wme, u_int hsize,
+ u_int oy, u_int oldy, u_int px, u_int py)
+{
+ u_int cy, yy, ny, nd;
+
+ yy = hsize - oy;
+ if (py < yy) {
+ ny = yy - py;
+ cy = 0;
+ nd = 1;
+ } else {
+ ny = 0;
+ cy = py - yy;
+ nd = oldy - cy + 1;
+ }
+ while (ny > 0) {
+ window_copy_cursor_up(wme, 1);
+ ny--;
+ }
+ window_copy_update_cursor(wme, px, cy);
+ if (window_copy_update_selection(wme, 1, 0))
+ window_copy_redraw_lines(wme, cy, nd);
+}
+
+/* Scroll down if the cursor went off the visible screen. */
+static void
+window_copy_acquire_cursor_down(struct window_mode_entry *wme, u_int hsize,
+ u_int sy, u_int oy, u_int oldy, u_int px, u_int py, int no_reset)
+{
+ u_int cy, yy, ny, nd;
+
+ cy = py - hsize + oy;
+ yy = sy - 1;
+ if (cy > yy) {
+ ny = cy - yy;
+ oldy = yy;
+ nd = 1;
+ } else {
+ ny = 0;
+ nd = cy - oldy + 1;
+ }
+ while (ny > 0) {
+ window_copy_cursor_down(wme, 1);
+ ny--;
+ }
+ if (cy > yy)
+ window_copy_update_cursor(wme, px, yy);
+ else
+ window_copy_update_cursor(wme, px, cy);
+ if (window_copy_update_selection(wme, 1, no_reset))
+ window_copy_redraw_lines(wme, oldy, nd);
+}