summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile4
-rw-r--r--grid-reader.c303
-rw-r--r--tmux.h23
-rw-r--r--window-copy.c333
4 files changed, 517 insertions, 146 deletions
diff --git a/Makefile b/Makefile
index 7fb664ad..21141317 100644
--- a/Makefile
+++ b/Makefile
@@ -76,6 +76,7 @@ SRCS= alerts.c \
file.c \
format.c \
format-draw.c \
+ grid-reader.c \
grid-view.c \
grid.c \
input-keys.c \
@@ -123,8 +124,7 @@ SRCS= alerts.c \
window-customize.c \
window-tree.c \
window.c \
- xmalloc.c \
- xterm-keys.c
+ xmalloc.c
CDIAGFLAGS+= -Wno-long-long -Wall -W -Wnested-externs -Wformat=2
CDIAGFLAGS+= -Wmissing-prototypes -Wstrict-prototypes -Wmissing-declarations
diff --git a/grid-reader.c b/grid-reader.c
new file mode 100644
index 00000000..a1af3aaa
--- /dev/null
+++ b/grid-reader.c
@@ -0,0 +1,303 @@
+/* $OpenBSD$ */
+
+/*
+ * Copyright (c) 2020 Anindya Mukherjee <anindya49@hotmail.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
+ * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "tmux.h"
+
+/* Initialise virtual cursor. */
+void
+grid_reader_start(struct grid_reader *gr, struct grid *gd, u_int cx, u_int cy)
+{
+ gr->gd = gd;
+ gr->cx = cx;
+ gr->cy = cy;
+}
+
+/* Get cursor position from reader. */
+void
+grid_reader_get_cursor(struct grid_reader *gr, u_int *cx, u_int *cy)
+{
+ *cx = gr->cx;
+ *cy = gr->cy;
+}
+
+/* Get length of line containing the cursor. */
+u_int
+grid_reader_line_length(struct grid_reader *gr)
+{
+ return (grid_line_length(gr->gd, gr->cy));
+}
+
+/* Move cursor forward one position. */
+void
+grid_reader_cursor_right(struct grid_reader *gr, int wrap, int all)
+{
+ u_int px;
+ struct grid_cell gc;
+
+ if (all)
+ px = gr->gd->sx;
+ else
+ px = grid_reader_line_length(gr);
+
+ if (wrap && gr->cx >= px && gr->cy < gr->gd->hsize + gr->gd->sy - 1) {
+ grid_reader_cursor_start_of_line(gr, 0);
+ grid_reader_cursor_down(gr);
+ } else if (gr->cx < px) {
+ gr->cx++;
+ while (gr->cx < px) {
+ grid_get_cell(gr->gd, gr->cx, gr->cy, &gc);
+ if (~gc.flags & GRID_FLAG_PADDING)
+ break;
+ gr->cx++;
+ }
+ }
+}
+
+/* Move cursor back one position. */
+void
+grid_reader_cursor_left(struct grid_reader *gr)
+{
+ struct grid_cell gc;
+
+ while (gr->cx > 0) {
+ grid_get_cell(gr->gd, gr->cx, gr->cy, &gc);
+ if (~gc.flags & GRID_FLAG_PADDING)
+ break;
+ gr->cx--;
+ }
+ if (gr->cx == 0 && gr->cy > 0) {
+ grid_reader_cursor_up(gr);
+ grid_reader_cursor_end_of_line(gr, 0, 0);
+ } else if (gr->cx > 0)
+ gr->cx--;
+}
+
+/* Move cursor down one line. */
+void
+grid_reader_cursor_down(struct grid_reader *gr)
+{
+ struct grid_cell gc;
+
+ if (gr->cy < gr->gd->hsize + gr->gd->sy - 1)
+ gr->cy++;
+ while (gr->cx > 0) {
+ grid_get_cell(gr->gd, gr->cx, gr->cy, &gc);
+ if (~gc.flags & GRID_FLAG_PADDING)
+ break;
+ gr->cx--;
+ }
+}
+
+/* Move cursor up one line. */
+void
+grid_reader_cursor_up(struct grid_reader *gr)
+{
+ struct grid_cell gc;
+
+ if (gr->cy > 0)
+ gr->cy--;
+ while (gr->cx > 0) {
+ grid_get_cell(gr->gd, gr->cx, gr->cy, &gc);
+ if (~gc.flags & GRID_FLAG_PADDING)
+ break;
+ gr->cx--;
+ }
+}
+
+/* Move cursor to the start of the line. */
+void
+grid_reader_cursor_start_of_line(struct grid_reader *gr, int wrap)
+{
+ if (wrap) {
+ while (gr->cy > 0 &&
+ grid_get_line(gr->gd, gr->cy - 1)->flags &
+ GRID_LINE_WRAPPED)
+ gr->cy--;
+ }
+ gr->cx = 0;
+}
+
+/* Move cursor to the end of the line. */
+void
+grid_reader_cursor_end_of_line(struct grid_reader *gr, int wrap, int all)
+{
+ u_int yy;
+
+ if (wrap) {
+ yy = gr->gd->hsize + gr->gd->sy - 1;
+ while (gr->cy < yy && grid_get_line(gr->gd, gr->cy)->flags &
+ GRID_LINE_WRAPPED)
+ gr->cy++;
+ }
+ if (all)
+ gr->cx = gr->gd->sx;
+ else
+ gr->cx = grid_reader_line_length(gr);
+}
+
+/* Check if character under cursor is in set. */
+int
+grid_reader_in_set(struct grid_reader *gr, const char *set)
+{
+ struct grid_cell gc;
+
+ grid_get_cell(gr->gd, gr->cx, gr->cy, &gc);
+ if (gc.flags & GRID_FLAG_PADDING)
+ return (0);
+ return (utf8_cstrhas(set, &gc.data));
+}
+
+/* Move cursor to the start of the next word. */
+void
+grid_reader_cursor_next_word(struct grid_reader *gr, const char *separators)
+{
+ u_int xx, yy;
+ int expected = 0;
+
+ /* Do not break up wrapped words. */
+ if (grid_get_line(gr->gd, gr->cy)->flags & GRID_LINE_WRAPPED)
+ xx = grid_reader_line_length(gr) - 1;
+ else
+ xx = grid_reader_line_length(gr);
+ yy = gr->gd->hsize + gr->gd->sy - 1;
+
+ /*
+ * If we started inside a word, skip over word characters. Then skip
+ * over separators till the next word.
+ *
+ * expected is initially set to 0 for the former and then 1 for the
+ * latter. It is finally set to 0 when the beginning of the next word is
+ * found.
+ */
+ do {
+ while (gr->cx > xx ||
+ grid_reader_in_set(gr, separators) == expected) {
+ /* Move down if we are past the end of the line. */
+ if (gr->cx > xx) {
+ if (gr->cy == yy)
+ return;
+ grid_reader_cursor_start_of_line(gr, 0);
+ grid_reader_cursor_down(gr);
+
+ if (grid_get_line(gr->gd, gr->cy)->flags &
+ GRID_LINE_WRAPPED)
+ xx = grid_reader_line_length(gr) - 1;
+ else
+ xx = grid_reader_line_length(gr);
+ } else
+ gr->cx++;
+ }
+ expected = !expected;
+ } while (expected == 1);
+}
+
+/* Move cursor to the end of the next word. */
+void
+grid_reader_cursor_next_word_end(struct grid_reader *gr, const char *separators)
+{
+ u_int xx, yy;
+ int expected = 1;
+
+ /* Do not break up wrapped words. */
+ if (grid_get_line(gr->gd, gr->cy)->flags & GRID_LINE_WRAPPED)
+ xx = grid_reader_line_length(gr) - 1;
+ else
+ xx = grid_reader_line_length(gr);
+ yy = gr->gd->hsize + gr->gd->sy - 1;
+
+ /*
+ * If we started on a separator, skip over separators. Then skip over
+ * word characters till the next separator.
+ *
+ * expected is initially set to 1 for the former and then 1 for the
+ * latter. It is finally set to 1 when the end of the next word is
+ * found.
+ */
+ do {
+ while (gr->cx > xx ||
+ grid_reader_in_set(gr, separators) == expected) {
+ /* Move down if we are past the end of the line. */
+ if (gr->cx > xx) {
+ if (gr->cy == yy)
+ return;
+ grid_reader_cursor_start_of_line(gr, 0);
+ grid_reader_cursor_down(gr);
+
+ if (grid_get_line(gr->gd, gr->cy)->flags &
+ GRID_LINE_WRAPPED)
+ xx = grid_reader_line_length(gr) - 1;
+ else
+ xx = grid_reader_line_length(gr);
+ } else
+ gr->cx++;
+ }
+ expected = !expected;
+ } while (expected == 0);
+}
+
+/* Move to the previous place where a word begins. */
+void
+grid_reader_cursor_previous_word(struct grid_reader *gr, const char *separators,
+ int already)
+{
+ int oldx, oldy, r;
+
+ /* Move back to the previous word character. */
+ if (already || grid_reader_in_set(gr, separators)) {
+ for (;;) {
+ if (gr->cx > 0) {
+ gr->cx--;
+ if (!grid_reader_in_set(gr, separators))
+ break;
+ } else {
+ if (gr->cy == 0)
+ return;
+ grid_reader_cursor_up(gr);
+ grid_reader_cursor_end_of_line(gr, 0, 0);
+
+ /* Stop if separator at EOL. */
+ if (gr->cx > 0) {
+ oldx = gr->cx;
+ gr->cx--;
+ r = grid_reader_in_set(gr, separators);
+ gr->cx = oldx;
+ if (r)
+ break;
+ }
+ }
+ }
+ }
+
+ /* Move back to the beginning of this word. */
+ do {
+ oldx = gr->cx;
+ oldy = gr->cy;
+ if (gr->cx == 0) {
+ if (gr->cy == 0 ||
+ ~grid_get_line(gr->gd, gr->cy - 1)->flags &
+ GRID_LINE_WRAPPED)
+ break;
+ grid_reader_cursor_up(gr);
+ grid_reader_cursor_end_of_line(gr, 0, 0);
+ }
+ if (gr->cx > 0)
+ gr->cx--;
+ } while (!grid_reader_in_set(gr, separators));
+ gr->cx = oldx;
+ gr->cy = oldy;
+}
diff --git a/tmux.h b/tmux.h
index 986eed00..0defff34 100644
--- a/tmux.h
+++ b/tmux.h
@@ -726,6 +726,13 @@ struct grid {
struct grid_line *linedata;
};
+/* Virtual cursor in a grid. */
+struct grid_reader {
+ struct grid *gd;
+ u_int cx;
+ u_int cy;
+};
+
/* Style alignment. */
enum style_align {
STYLE_ALIGN_DEFAULT,
@@ -2548,6 +2555,22 @@ void grid_wrap_position(struct grid *, u_int, u_int, u_int *, u_int *);
void grid_unwrap_position(struct grid *, u_int *, u_int *, u_int, u_int);
u_int grid_line_length(struct grid *, u_int);
+/* grid-reader.c */
+void grid_reader_start(struct grid_reader *, struct grid *, u_int, u_int);
+void grid_reader_get_cursor(struct grid_reader *, u_int *, u_int *);
+u_int grid_reader_line_length(struct grid_reader *);
+int grid_reader_in_set(struct grid_reader *, const char *);
+void grid_reader_cursor_right(struct grid_reader *, int, int);
+void grid_reader_cursor_left(struct grid_reader *);
+void grid_reader_cursor_down(struct grid_reader *);
+void grid_reader_cursor_up(struct grid_reader *);
+void grid_reader_cursor_start_of_line(struct grid_reader *, int);
+void grid_reader_cursor_end_of_line(struct grid_reader *, int, int);
+void grid_reader_cursor_next_word(struct grid_reader *, const char *);
+void grid_reader_cursor_next_word_end(struct grid_reader *, const char *);
+void grid_reader_cursor_previous_word(struct grid_reader *, const char *,
+ int);
+
/* grid-view.c */
void grid_view_get_cell(struct grid *, u_int, u_int, struct grid_cell *);
void grid_view_set_cell(struct grid *, u_int, u_int,
diff --git a/window-copy.c b/window-copy.c
index 6dc03b34..764f6b5b 100644
--- a/window-copy.c
+++ b/window-copy.c
@@ -3993,18 +3993,31 @@ window_copy_cursor_start_of_line(struct window_mode_entry *wme)
{
struct window_copy_mode_data *data = wme->data;
struct screen *back_s = data->backing;
- struct grid *gd = back_s->grid;
- u_int py;
-
- 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) {
- window_copy_cursor_up(wme, 0);
- py = screen_hsize(back_s) + data->cy - data->oy;
- }
+ struct grid_reader gr;
+ u_int px, py, cy, yy, ny, hsize;
+
+ px = data->cx;
+ hsize = screen_hsize(back_s);
+ py = hsize + data->cy - data->oy;
+
+ 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;
+ } else {
+ ny = 0;
+ cy = py - yy;
+ }
+ while (ny > 0) {
+ window_copy_cursor_up(wme, 1);
+ ny--;
}
- window_copy_update_cursor(wme, 0, data->cy);
+ window_copy_update_cursor(wme, px, cy);
if (window_copy_update_selection(wme, 1, 0))
window_copy_redraw_lines(wme, data->cy, 1);
}
@@ -4037,30 +4050,35 @@ window_copy_cursor_end_of_line(struct window_mode_entry *wme)
{
struct window_copy_mode_data *data = wme->data;
struct screen *back_s = data->backing;
- struct grid *gd = back_s->grid;
- struct grid_line *gl;
- u_int px, py;
+ struct grid_reader gr;
+ u_int px, py, cy, yy, ny, hsize;
- py = screen_hsize(back_s) + data->cy - data->oy;
- px = window_copy_find_length(wme, py);
+ px = data->cx;
+ hsize = screen_hsize(back_s);
+ py = hsize + data->cy - data->oy;
- 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) {
- while (py < gd->sy + gd->hsize) {
- gl = grid_get_line(gd, py);
- if (~gl->flags & GRID_LINE_WRAPPED)
- break;
- window_copy_cursor_down(wme, 0);
- py = screen_hsize(back_s) + data->cy - data->oy;
- }
- px = window_copy_find_length(wme, py);
- }
+ grid_reader_start(&gr, back_s->grid, px, py);
+ if (data->screen.sel != NULL && data->rectflag)
+ grid_reader_cursor_end_of_line(&gr, 1, 1);
+ 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;
+ else
+ ny = 0;
+ while (ny > 0) {
+ window_copy_cursor_down(wme, 1);
+ ny--;
}
- window_copy_update_cursor(wme, px, data->cy);
-
+ 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);
}
@@ -4120,57 +4138,69 @@ static void
window_copy_cursor_left(struct window_mode_entry *wme)
{
struct window_copy_mode_data *data = wme->data;
- u_int py, cx;
- struct grid_cell gc;
+ struct screen *back_s = data->backing;
+ struct grid_reader gr;
+ u_int px, py, cy, yy, ny, hsize;
- py = screen_hsize(data->backing) + data->cy - data->oy;
- cx = data->cx;
- while (cx > 0) {
- grid_get_cell(data->backing->grid, cx, py, &gc);
- if (~gc.flags & GRID_FLAG_PADDING)
- break;
- cx--;
+ px = data->cx;
+ hsize = screen_hsize(back_s);
+ py = hsize + data->cy - data->oy;
+
+ 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;
}
- if (cx == 0 && py > 0) {
- window_copy_cursor_up(wme, 0);
- window_copy_cursor_end_of_line(wme);
- } else if (cx > 0) {
- window_copy_update_cursor(wme, cx - 1, data->cy);
- if (window_copy_update_selection(wme, 1, 0))
- window_copy_redraw_lines(wme, data->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, 1);
}
static void
window_copy_cursor_right(struct window_mode_entry *wme, int all)
{
struct window_copy_mode_data *data = wme->data;
- u_int px, py, yy, cx, cy;
- struct grid_cell gc;
+ struct screen *back_s = data->backing;
+ struct grid_reader gr;
+ u_int px, py, cy, yy, ny, hsize;
- py = screen_hsize(data->backing) + data->cy - data->oy;
- yy = screen_hsize(data->backing) + screen_size_y(data->backing) - 1;
- if (all || (data->screen.sel != NULL && data->rectflag))
- px = screen_size_x(&data->screen);
- else
- px = window_copy_find_length(wme, py);
+ px = data->cx;
+ hsize = screen_hsize(back_s);
+ py = hsize + data->cy - data->oy;
- if (data->cx >= px && py < yy) {
- window_copy_cursor_start_of_line(wme);
- window_copy_cursor_down(wme, 0);
- } else if (data->cx < px) {
- cx = data->cx + 1;
- cy = screen_hsize(data->backing) + data->cy - data->oy;
- while (cx < px) {
- grid_get_cell(data->backing->grid, cx, cy, &gc);
- if (~gc.flags & GRID_FLAG_PADDING)
- break;
- cx++;
- }
- window_copy_update_cursor(wme, cx, data->cy);
- if (window_copy_update_selection(wme, 1, 0))
- window_copy_redraw_lines(wme, data->cy, 1);
+ 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);
}
static void
@@ -4214,13 +4244,30 @@ window_copy_cursor_up(struct window_mode_entry *wme, int scroll_only)
px = window_copy_find_length(wme, py);
if ((data->cx >= data->lastsx && data->cx != px) ||
data->cx > px)
- window_copy_cursor_end_of_line(wme);
+ {
+ window_copy_update_cursor(wme, px, data->cy);
+ if (window_copy_update_selection(wme, 1, 0))
+ window_copy_redraw_lines(wme, data->cy, 1);
+ }
}
if (data->lineflag == LINE_SEL_LEFT_RIGHT)
- window_copy_cursor_end_of_line(wme);
+ {
+ py = screen_hsize(data->backing) + data->cy - data->oy;
+ if (data->rectflag)
+ px = screen_size_x(data->backing);
+ else
+ px = window_copy_find_length(wme, py);
+ window_copy_update_cursor(wme, px, data->cy);
+ if (window_copy_update_selection(wme, 1, 0))
+ window_copy_redraw_lines(wme, data->cy, 1);
+ }
else if (data->lineflag == LINE_SEL_RIGHT_LEFT)
- window_copy_cursor_start_of_line(wme);
+ {
+ window_copy_update_cursor(wme, 0, data->cy);
+ if (window_copy_update_selection(wme, 1, 0))
+ window_copy_redraw_lines(wme, data->cy, 1);
+ }
}
static void
@@ -4256,13 +4303,30 @@ window_copy_cursor_down(struct window_mode_entry *wme, int scroll_only)
px = window_copy_find_length(wme, py);
if ((data->cx >= data->lastsx && data->cx != px) ||
data->cx > px)
- window_copy_cursor_end_of_line(wme);
+ {
+ window_copy_update_cursor(wme, px, data->cy);
+ if (window_copy_update_selection(wme, 1, 0))
+ window_copy_redraw_lines(wme, data->cy, 1);
+ }
}
if (data->lineflag == LINE_SEL_LEFT_RIGHT)
- window_copy_cursor_end_of_line(wme);
+ {
+ py = screen_hsize(data->backing) + data->cy - data->oy;
+ if (data->rectflag)
+ px = screen_size_x(data->backing);
+ else
+ px = window_copy_find_length(wme, py);
+ window_copy_update_cursor(wme, px, data->cy);
+ if (window_copy_update_selection(wme, 1, 0))
+ window_copy_redraw_lines(wme, data->cy, 1);
+ }
else if (data->lineflag == LINE_SEL_RIGHT_LEFT)
- window_copy_cursor_start_of_line(wme);
+ {
+ window_copy_update_cursor(wme, 0, data->cy);
+ if (window_copy_update_selection(wme, 1, 0))
+ window_copy_redraw_lines(wme, data->cy, 1);
+ }
}
static void
@@ -4476,46 +4540,38 @@ window_copy_cursor_next_word_end(struct window_mode_entry *wme,
struct window_copy_mode_data *data = wme->data;
struct options *oo = wp->window->options;
struct screen *back_s = data->backing;
- u_int px, py, xx, yy;
- int keys, expected = 1;
+ struct grid_reader gr;
+ u_int px, py, cy, yy, ny, hsize;
+ int keys;
px = data->cx;
- py = screen_hsize(back_s) + data->cy - data->oy;
- xx = window_copy_find_length(wme, py);
- yy = screen_hsize(back_s) + screen_size_y(back_s) - 1;
+ hsize = screen_hsize(back_s);
+ py = hsize + data->cy - data->oy;
+ grid_reader_start(&gr, back_s->grid, px, py);
keys = options_get_number(oo, "mode-keys");
- if (keys == MODEKEY_VI && !window_copy_in_set(wme, px, py, separators))
- px++;
-
- /*
- * First skip past any word characters, then any nonword characters.
- *
- * expected is initially set to 1 for the former and then 0 for the
- * latter.
- */
- do {
- while (px > xx ||
- window_copy_in_set(wme, px, py, separators) == expected) {
- /* Move down if we're past the end of the line. */
- if (px > xx) {
- if (py == yy)
- return;
- window_copy_cursor_down(wme, 0);
- px = 0;
-
- py = screen_hsize(back_s) + data->cy - data->oy;
- xx = window_copy_find_length(wme, py);
- } else
- px++;
- }
- expected = !expected;
- } while (expected == 0);
-
- if (keys == MODEKEY_VI && px != 0)
- px--;
-
- window_copy_update_cursor(wme, px, data->cy);
+ if (keys == MODEKEY_VI && !grid_reader_in_set(&gr, separators))
+ grid_reader_cursor_right(&gr, 0, 0);
+ grid_reader_cursor_next_word_end(&gr, separators);
+ 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;
+ 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, no_reset))
window_copy_redraw_lines(wme, data->cy, 1);
}
@@ -4572,43 +4628,32 @@ window_copy_cursor_previous_word(struct window_mode_entry *wme,
const char *separators, int already)
{
struct window_copy_mode_data *data = wme->data;
- u_int px, py, hsize;
+ struct screen *back_s = data->backing;
+ struct grid_reader gr;
+ u_int px, py, cy, yy, ny, hsize;
- hsize = screen_hsize(data->backing);
px = data->cx;
+ hsize = screen_hsize(back_s);
py = hsize + data->cy - data->oy;
- /* Move back to the previous word character. */
- if (already || window_copy_in_set(wme, px, py, separators)) {
- for (;;) {
- if (px > 0) {
- px--;
- if (!window_copy_in_set(wme, px, py,
- separators))
- break;
- } else {
- if (data->cy == 0 &&
- (hsize == 0 || data->oy > hsize - 1))
- goto out;
- window_copy_cursor_up(wme, 0);
-
- py = hsize + data->cy - data->oy;
- px = window_copy_find_length(wme, py);
+ grid_reader_start(&gr, back_s->grid, px, py);
+ grid_reader_cursor_previous_word(&gr, separators, already);
+ grid_reader_get_cursor(&gr, &px, &py);
- /* Stop if separator at EOL. */
- if (px > 0 && window_copy_in_set(wme, px - 1,
- py, separators))
- break;
- }
- }
+ /* 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;
}
-
- /* Move back to the beginning of this word. */
- while (px > 0 && !window_copy_in_set(wme, px - 1, py, separators))
- px--;
-
-out:
- window_copy_update_cursor(wme, px, data->cy);
+ 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);
}