summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--usr.bin/tmux/mode-key.c16
-rw-r--r--usr.bin/tmux/tmux.120
-rw-r--r--usr.bin/tmux/tmux.h6
-rw-r--r--usr.bin/tmux/window-copy.c406
4 files changed, 422 insertions, 26 deletions
diff --git a/usr.bin/tmux/mode-key.c b/usr.bin/tmux/mode-key.c
index a9f3e5dec9c..ac0cdaa8214 100644
--- a/usr.bin/tmux/mode-key.c
+++ b/usr.bin/tmux/mode-key.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: mode-key.c,v 1.14 2009/08/13 23:44:18 nicm Exp $ */
+/* $OpenBSD: mode-key.c,v 1.15 2009/08/18 07:08:26 nicm Exp $ */
/*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -74,18 +74,22 @@ struct mode_key_cmdstr mode_key_cmdstr_choice[] = {
/* Copy keys command strings. */
struct mode_key_cmdstr mode_key_cmdstr_copy[] = {
- { MODEKEYCOPY_CANCEL, "cancel" },
{ MODEKEYCOPY_BACKTOINDENTATION, "back-to-indentation" },
+ { MODEKEYCOPY_CANCEL, "cancel" },
{ MODEKEYCOPY_CLEARSELECTION, "clear-selection" },
{ MODEKEYCOPY_COPYSELECTION, "copy-selection" },
{ MODEKEYCOPY_DOWN, "cursor-down" },
{ MODEKEYCOPY_ENDOFLINE, "end-of-line" },
+ { MODEKEYCOPY_GOTOLINE, "goto-line" },
{ MODEKEYCOPY_LEFT, "cursor-left" },
{ MODEKEYCOPY_NEXTPAGE, "page-down" },
{ MODEKEYCOPY_NEXTWORD, "next-word" },
{ MODEKEYCOPY_PREVIOUSPAGE, "page-up" },
{ MODEKEYCOPY_PREVIOUSWORD, "previous-word" },
{ MODEKEYCOPY_RIGHT, "cursor-right" },
+ { MODEKEYCOPY_SEARCHAGAIN, "search-again" },
+ { MODEKEYCOPY_SEARCHDOWN, "search-forward" },
+ { MODEKEYCOPY_SEARCHUP, "search-backward" },
{ MODEKEYCOPY_STARTOFLINE, "start-of-line" },
{ MODEKEYCOPY_STARTSELECTION, "begin-selection" },
{ MODEKEYCOPY_UP, "cursor-up" },
@@ -148,7 +152,9 @@ struct mode_key_tree mode_key_tree_vi_choice;
const struct mode_key_entry mode_key_vi_copy[] = {
{ ' ', 0, MODEKEYCOPY_STARTSELECTION },
{ '$', 0, MODEKEYCOPY_ENDOFLINE },
+ { '/', 0, MODEKEYCOPY_SEARCHUP },
{ '0', 0, MODEKEYCOPY_STARTOFLINE },
+ { '?', 0, MODEKEYCOPY_SEARCHDOWN },
{ '\002' /* C-b */, 0, MODEKEYCOPY_PREVIOUSPAGE },
{ '\003' /* C-c */, 0, MODEKEYCOPY_CANCEL },
{ '\004' /* C-d */, 0, MODEKEYCOPY_HALFPAGEDOWN },
@@ -159,10 +165,12 @@ const struct mode_key_entry mode_key_vi_copy[] = {
{ '\r', 0, MODEKEYCOPY_COPYSELECTION },
{ '^', 0, MODEKEYCOPY_BACKTOINDENTATION },
{ 'b', 0, MODEKEYCOPY_PREVIOUSWORD },
+ { 'g', 0, MODEKEYCOPY_GOTOLINE },
{ 'h', 0, MODEKEYCOPY_LEFT },
{ 'j', 0, MODEKEYCOPY_DOWN },
{ 'k', 0, MODEKEYCOPY_UP },
{ 'l', 0, MODEKEYCOPY_RIGHT },
+ { 'n', 0, MODEKEYCOPY_SEARCHAGAIN },
{ 'q', 0, MODEKEYCOPY_CANCEL },
{ 'w', 0, MODEKEYCOPY_NEXTWORD },
{ KEYC_BSPACE, 0, MODEKEYCOPY_LEFT },
@@ -232,12 +240,16 @@ const struct mode_key_entry mode_key_emacs_copy[] = {
{ '\007' /* C-g */, 0, MODEKEYCOPY_CLEARSELECTION },
{ '\016' /* C-n */, 0, MODEKEYCOPY_DOWN },
{ '\020' /* C-p */, 0, MODEKEYCOPY_UP },
+ { '\022' /* C-r */, 0, MODEKEYCOPY_SEARCHUP },
+ { '\023' /* C-s */, 0, MODEKEYCOPY_SEARCHDOWN },
{ '\026' /* C-v */, 0, MODEKEYCOPY_NEXTPAGE },
{ '\027' /* C-w */, 0, MODEKEYCOPY_COPYSELECTION },
{ '\033' /* Escape */, 0, MODEKEYCOPY_CANCEL },
{ 'b' | KEYC_ESCAPE, 0, MODEKEYCOPY_PREVIOUSWORD },
{ 'f' | KEYC_ESCAPE, 0, MODEKEYCOPY_NEXTWORD },
+ { 'g', 0, MODEKEYCOPY_GOTOLINE },
{ 'm' | KEYC_ESCAPE, 0, MODEKEYCOPY_BACKTOINDENTATION },
+ { 'n', 0, MODEKEYCOPY_SEARCHAGAIN },
{ 'q', 0, MODEKEYCOPY_CANCEL },
{ 'v' | KEYC_ESCAPE, 0, MODEKEYCOPY_PREVIOUSPAGE },
{ 'w' | KEYC_ESCAPE, 0, MODEKEYCOPY_COPYSELECTION },
diff --git a/usr.bin/tmux/tmux.1 b/usr.bin/tmux/tmux.1
index f83e4e51ab0..7c1b395a828 100644
--- a/usr.bin/tmux/tmux.1
+++ b/usr.bin/tmux/tmux.1
@@ -1,4 +1,4 @@
-.\" $OpenBSD: tmux.1,v 1.69 2009/08/13 20:11:58 nicm Exp $
+.\" $OpenBSD: tmux.1,v 1.70 2009/08/18 07:08:26 nicm Exp $
.\"
.\" Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
.\"
@@ -14,7 +14,7 @@
.\" IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
.\" OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
-.Dd $Mdocdate: August 13 2009 $
+.Dd $Mdocdate: August 18 2009 $
.Dt TMUX 1
.Os
.Sh NAME
@@ -475,23 +475,27 @@ option).
The following keys are supported as appropriate for the mode:
.Bl -column "FunctionXXXXXXXXXXXX" "viXXXXXX" "emacs" -offset indent
.It Sy "Function" Ta Sy "vi" Ta Sy "emacs"
-.It Li "Start of line" Ta "0" Ta "C-a"
.It Li "Back to indentation" Ta "^" Ta "M-m"
.It Li "Clear selection" Ta "Escape" Ta "C-g"
.It Li "Copy selection" Ta "Enter" Ta "M-w"
.It Li "Cursor down" Ta "j" Ta "Down"
-.It Li "End of line" Ta "$" Ta "C-e"
.It Li "Cursor left" Ta "h" Ta "Left"
+.It Li "Cursor right" Ta "l" Ta "Right"
+.It Li "Cursor up" Ta "k" Ta "Up"
+.It Li "Delete to end of line" Ta "D" Ta "C-k"
+.It Li "End of line" Ta "$" Ta "C-e"
+.It Li "Goto line" Ta "g" Ta "g"
.It Li "Next page" Ta "C-f" Ta "Page down"
.It Li "Next word" Ta "w" Ta "M-f"
+.It Li "Paste buffer" Ta "p" Ta "C-y"
.It Li "Previous page" Ta "C-u" Ta "Page up"
.It Li "Previous word" Ta "b" Ta "M-b"
.It Li "Quit mode" Ta "q" Ta "Escape"
-.It Li "Cursor right" Ta "l" Ta "Right"
+.It Li "Search again" Ta "n" Ta "n"
+.It Li "Search backward" Ta "?" Ta "C-r"
+.It Li "Search forward" Ta "/" Ta "C-s"
+.It Li "Start of line" Ta "0" Ta "C-a"
.It Li "Start selection" Ta "Space" Ta "C-Space"
-.It Li "Cursor up" Ta "k" Ta "Up"
-.It Li "Delete to end of line" Ta "D" Ta "C-k"
-.It Li "Paste buffer" Ta "p" Ta "C-y"
.El
.Pp
These key bindings are defined in a set of named tables:
diff --git a/usr.bin/tmux/tmux.h b/usr.bin/tmux/tmux.h
index a3b5d71f05e..c1bc9df1923 100644
--- a/usr.bin/tmux/tmux.h
+++ b/usr.bin/tmux/tmux.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: tmux.h,v 1.82 2009/08/13 22:32:18 nicm Exp $ */
+/* $OpenBSD: tmux.h,v 1.83 2009/08/18 07:08:26 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -394,6 +394,7 @@ enum mode_key_cmd {
MODEKEYCOPY_COPYSELECTION,
MODEKEYCOPY_DOWN,
MODEKEYCOPY_ENDOFLINE,
+ MODEKEYCOPY_GOTOLINE,
MODEKEYCOPY_HALFPAGEDOWN,
MODEKEYCOPY_HALFPAGEUP,
MODEKEYCOPY_LEFT,
@@ -402,6 +403,9 @@ enum mode_key_cmd {
MODEKEYCOPY_PREVIOUSPAGE,
MODEKEYCOPY_PREVIOUSWORD,
MODEKEYCOPY_RIGHT,
+ MODEKEYCOPY_SEARCHAGAIN,
+ MODEKEYCOPY_SEARCHDOWN,
+ MODEKEYCOPY_SEARCHUP,
MODEKEYCOPY_STARTOFLINE,
MODEKEYCOPY_STARTSELECTION,
MODEKEYCOPY_UP,
diff --git a/usr.bin/tmux/window-copy.c b/usr.bin/tmux/window-copy.c
index 96fb55ce871..9e1fc1629fb 100644
--- a/usr.bin/tmux/window-copy.c
+++ b/usr.bin/tmux/window-copy.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: window-copy.c,v 1.20 2009/08/13 22:32:18 nicm Exp $ */
+/* $OpenBSD: window-copy.c,v 1.21 2009/08/18 07:08:26 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -18,6 +18,7 @@
#include <sys/types.h>
+#include <stdlib.h>
#include <string.h>
#include "tmux.h"
@@ -26,6 +27,7 @@ struct screen *window_copy_init(struct window_pane *);
void window_copy_free(struct window_pane *);
void window_copy_resize(struct window_pane *, u_int, u_int);
void window_copy_key(struct window_pane *, struct client *, int);
+int window_copy_key_input(struct window_pane *, int);
void window_copy_mouse(
struct window_pane *, struct client *, u_char, u_char, u_char);
@@ -36,6 +38,16 @@ void window_copy_write_line(
void window_copy_write_lines(
struct window_pane *, struct screen_write_ctx *, u_int, u_int);
+void window_copy_scroll_to(struct window_pane *, u_int, u_int);
+int window_copy_search_compare(
+ struct grid *, u_int, u_int, struct grid *, u_int);
+int window_copy_search_lr(
+ struct grid *, struct grid *, u_int *, u_int, u_int, u_int);
+int window_copy_search_rl(
+ struct grid *, struct grid *, u_int *, u_int, u_int, u_int);
+void window_copy_search_up(struct window_pane *, const char *);
+void window_copy_search_down(struct window_pane *, const char *);
+void window_copy_goto_line(struct window_pane *, const char *);
void window_copy_update_cursor(struct window_pane *, u_int, u_int);
void window_copy_start_selection(struct window_pane *);
int window_copy_update_selection(struct window_pane *);
@@ -65,18 +77,32 @@ const struct window_mode window_copy_mode = {
NULL,
};
+enum window_copy_input_type {
+ WINDOW_COPY_OFF,
+ WINDOW_COPY_SEARCHUP,
+ WINDOW_COPY_SEARCHDOWN,
+ WINDOW_COPY_GOTOLINE,
+};
+
struct window_copy_mode_data {
struct screen screen;
- struct mode_key_data mdata;
+ struct mode_key_data mdata;
+
+ u_int oy;
- u_int oy;
+ u_int selx;
+ u_int sely;
- u_int selx;
- u_int sely;
+ u_int cx;
+ u_int cy;
- u_int cx;
- u_int cy;
+ enum window_copy_input_type inputtype;
+ const char *inputprompt;
+ char *inputstr;
+
+ enum window_copy_input_type searchtype;
+ char *searchstr;
};
struct screen *
@@ -93,6 +119,13 @@ window_copy_init(struct window_pane *wp)
data->cx = wp->base.cx;
data->cy = wp->base.cy;
+ data->inputtype = WINDOW_COPY_OFF;
+ data->inputprompt = NULL;
+ data->inputstr = xstrdup("");
+
+ data->searchtype = WINDOW_COPY_OFF;
+ data->searchstr = NULL;
+
s = &data->screen;
screen_init(s, screen_size_x(&wp->base), screen_size_y(&wp->base), 0);
if (options_get_number(&wp->window->options, "mode-mouse"))
@@ -121,7 +154,12 @@ window_copy_free(struct window_pane *wp)
{
struct window_copy_mode_data *data = wp->modedata;
+ if (data->searchstr != NULL)
+ xfree(data->searchstr);
+ xfree(data->inputstr);
+
screen_free(&data->screen);
+
xfree(data);
}
@@ -172,6 +210,13 @@ window_copy_key(struct window_pane *wp, struct client *c, int key)
struct window_copy_mode_data *data = wp->modedata;
struct screen *s = &data->screen;
u_int n;
+ int keys;
+
+ if (data->inputtype != WINDOW_COPY_OFF) {
+ if (window_copy_key_input(wp, key) != 0)
+ goto input_off;
+ return;
+ }
switch (mode_key_lookup(&data->mdata, key)) {
case MODEKEYCOPY_CANCEL:
@@ -250,9 +295,111 @@ window_copy_key(struct window_pane *wp, struct client *c, int key)
case MODEKEYCOPY_PREVIOUSWORD:
window_copy_cursor_previous_word(wp);
break;
+ case MODEKEYCOPY_SEARCHUP:
+ data->inputtype = WINDOW_COPY_SEARCHUP;
+ data->inputprompt = "Search Up";
+ goto input_on;
+ case MODEKEYCOPY_SEARCHDOWN:
+ data->inputtype = WINDOW_COPY_SEARCHDOWN;
+ data->inputprompt = "Search Down";
+ goto input_on;
+ case MODEKEYCOPY_SEARCHAGAIN:
+ switch (data->searchtype) {
+ case WINDOW_COPY_OFF:
+ case WINDOW_COPY_GOTOLINE:
+ break;
+ case WINDOW_COPY_SEARCHUP:
+ window_copy_search_up(wp, data->searchstr);
+ break;
+ case WINDOW_COPY_SEARCHDOWN:
+ window_copy_search_down(wp, data->searchstr);
+ break;
+ }
+ break;
+ case MODEKEYCOPY_GOTOLINE:
+ data->inputtype = WINDOW_COPY_GOTOLINE;
+ data->inputprompt = "Goto Line";
+ *data->inputstr = '\0';
+ goto input_on;
default:
break;
}
+
+ return;
+
+input_on:
+ keys = options_get_number(&wp->window->options, "mode-keys");
+ if (keys == MODEKEY_EMACS)
+ mode_key_init(&data->mdata, &mode_key_tree_emacs_edit);
+ else
+ mode_key_init(&data->mdata, &mode_key_tree_vi_edit);
+
+ window_copy_redraw_lines(wp, screen_size_y(s) - 1, 1);
+ return;
+
+input_off:
+ keys = options_get_number(&wp->window->options, "mode-keys");
+ if (keys == MODEKEY_EMACS)
+ mode_key_init(&data->mdata, &mode_key_tree_emacs_copy);
+ else
+ mode_key_init(&data->mdata, &mode_key_tree_vi_copy);
+
+ data->inputtype = WINDOW_COPY_OFF;
+ data->inputprompt = NULL;
+
+ window_copy_redraw_lines(wp, screen_size_y(s) - 1, 1);
+}
+
+int
+window_copy_key_input(struct window_pane *wp, int key)
+{
+ struct window_copy_mode_data *data = wp->modedata;
+ struct screen *s = &data->screen;
+ size_t inputlen;
+
+ switch (mode_key_lookup(&data->mdata, key)) {
+ case MODEKEYEDIT_CANCEL:
+ return (-1);
+ case MODEKEYEDIT_BACKSPACE:
+ inputlen = strlen(data->inputstr);
+ if (inputlen > 0)
+ data->inputstr[inputlen - 1] = '\0';
+ break;
+ case MODEKEYEDIT_ENTER:
+ switch (data->inputtype) {
+ case WINDOW_COPY_OFF:
+ break;
+ case WINDOW_COPY_SEARCHUP:
+ window_copy_search_up(wp, data->inputstr);
+ data->searchtype = data->inputtype;
+ data->searchstr = xstrdup(data->inputstr);
+ break;
+ case WINDOW_COPY_SEARCHDOWN:
+ window_copy_search_down(wp, data->inputstr);
+ data->searchtype = data->inputtype;
+ data->searchstr = xstrdup(data->inputstr);
+ break;
+ case WINDOW_COPY_GOTOLINE:
+ window_copy_goto_line(wp, data->inputstr);
+ *data->inputstr = '\0';
+ break;
+ }
+ return (1);
+ case MODEKEY_OTHER:
+ if (key < 32 || key > 126)
+ break;
+ inputlen = strlen(data->inputstr) + 2;
+
+ data->inputstr = xrealloc(data->inputstr, 1, inputlen);
+ data->inputstr[inputlen - 2] = key;
+ data->inputstr[inputlen - 1] = '\0';
+ break;
+ default:
+ break;
+ }
+
+ window_copy_redraw_lines(wp, screen_size_y(s) - 1, 1);
+ return (0);
}
void
@@ -275,6 +422,229 @@ window_copy_mouse(struct window_pane *wp,
}
void
+window_copy_scroll_to(struct window_pane *wp, u_int px, u_int py)
+{
+ struct window_copy_mode_data *data = wp->modedata;
+ struct screen *s = &wp->base;
+ struct grid *gd = s->grid;
+ u_int offset, gap;
+
+ data->cx = px;
+
+ gap = gd->sy / 4;
+ if (py < gd->sy) {
+ offset = 0;
+ data->cy = py;
+ } else if (py > gd->hsize + gd->sy - gap) {
+ offset = gd->hsize;
+ data->cy = py - gd->hsize;
+ } else {
+ offset = py + gap - gd->sy;
+ data->cy = py - offset;
+ }
+ data->oy = gd->hsize - offset;
+
+ window_copy_redraw_screen(wp);
+}
+
+int
+window_copy_search_compare(
+ struct grid *gd, u_int px, u_int py, struct grid *sgd, u_int spx)
+{
+ const struct grid_cell *gc, *sgc;
+ const struct grid_utf8 *gu, *sgu;
+
+ gc = grid_peek_cell(gd, px, py);
+ sgc = grid_peek_cell(sgd, spx, 0);
+
+ if ((gc->flags & GRID_FLAG_UTF8) != (sgc->flags & GRID_FLAG_UTF8))
+ return (0);
+
+ if (gc->flags & GRID_FLAG_UTF8) {
+ gu = grid_peek_utf8(gd, px, py);
+ sgu = grid_peek_utf8(sgd, spx, 0);
+ if (memcmp(gu->data, sgu->data, UTF8_SIZE) == 0)
+ return (1);
+ } else {
+ if (gc->data == sgc->data)
+ return (1);
+ }
+ return (0);
+}
+
+int
+window_copy_search_lr(struct grid *gd,
+ struct grid *sgd, u_int *ppx, u_int py, u_int first, u_int last)
+{
+ u_int ax, bx, px;
+
+ for (ax = first; ax < last; ax++) {
+ if (ax + sgd->sx >= gd->sx)
+ break;
+ for (bx = 0; bx < sgd->sx; bx++) {
+ px = ax + bx;
+ if (!window_copy_search_compare(gd, px, py, sgd, bx))
+ break;
+ }
+ if (bx == sgd->sx) {
+ *ppx = ax;
+ return (1);
+ }
+ }
+ return (0);
+}
+
+int
+window_copy_search_rl(struct grid *gd,
+ struct grid *sgd, u_int *ppx, u_int py, u_int first, u_int last)
+{
+ u_int ax, bx, px;
+
+ for (ax = last + 1; ax > first; ax--) {
+ for (bx = 0; bx < sgd->sx; bx++) {
+ px = ax - 1 + bx;
+ if (!window_copy_search_compare(gd, px, py, sgd, bx))
+ break;
+ }
+ if (bx == sgd->sx) {
+ *ppx = ax - 1;
+ return (1);
+ }
+ }
+ return (0);
+}
+
+void
+window_copy_search_up(struct window_pane *wp, const char *searchstr)
+{
+ struct window_copy_mode_data *data = wp->modedata;
+ struct screen *s = &wp->base, ss;
+ struct screen_write_ctx ctx;
+ struct grid *gd = s->grid, *sgd;
+ struct grid_cell gc;
+ size_t searchlen;
+ u_int i, last, fx, fy, px;
+ int utf8flag, n, wrapped;
+
+ if (*searchstr == '\0')
+ return;
+ utf8flag = options_get_number(&wp->window->options, "utf8");
+ searchlen = screen_write_strlen(utf8flag, "%s", searchstr);
+
+ screen_init(&ss, searchlen, 1, 0);
+ screen_write_start(&ctx, NULL, &ss);
+ memcpy(&gc, &grid_default_cell, sizeof gc);
+ screen_write_nputs(&ctx, -1, &gc, utf8flag, "%s", searchstr);
+ screen_write_stop(&ctx);
+
+ fx = data->cx;
+ fy = gd->hsize - data->oy + data->cy;
+
+ if (fx == 0) {
+ if (fy == 0)
+ return;
+ fx = gd->sx - 1;
+ fy--;
+ } else
+ fx--;
+ n = wrapped = 0;
+
+retry:
+ sgd = ss.grid;
+ for (i = fy + 1; i > 0; i--) {
+ last = screen_size_x(s);
+ if (i == fy + 1)
+ last = fx;
+ n = window_copy_search_rl(gd, sgd, &px, i - 1, 0, last);
+ if (n) {
+ window_copy_scroll_to(wp, px, i - 1);
+ break;
+ }
+ }
+ if (!n && !wrapped) {
+ fx = gd->sx - 1;
+ fy = gd->hsize + gd->sy - 1;
+ wrapped = 1;
+ goto retry;
+ }
+
+ screen_free(&ss);
+}
+
+void
+window_copy_search_down(struct window_pane *wp, const char *searchstr)
+{
+ struct window_copy_mode_data *data = wp->modedata;
+ struct screen *s = &wp->base, ss;
+ struct screen_write_ctx ctx;
+ struct grid *gd = s->grid, *sgd;
+ struct grid_cell gc;
+ size_t searchlen;
+ u_int i, first, fx, fy, px;
+ int utf8flag, n, wrapped;
+
+ if (*searchstr == '\0')
+ return;
+ utf8flag = options_get_number(&wp->window->options, "utf8");
+ searchlen = screen_write_strlen(utf8flag, "%s", searchstr);
+
+ screen_init(&ss, searchlen, 1, 0);
+ screen_write_start(&ctx, NULL, &ss);
+ memcpy(&gc, &grid_default_cell, sizeof gc);
+ screen_write_nputs(&ctx, -1, &gc, utf8flag, "%s", searchstr);
+ screen_write_stop(&ctx);
+ searchlen = strlen(searchstr);
+
+ fx = data->cx;
+ fy = gd->hsize - data->oy + data->cy;
+
+ if (fx == gd->sx - 1) {
+ if (fy == gd->hsize + gd->sy)
+ return;
+ fx = 0;
+ fy++;
+ } else
+ fx++;
+ n = wrapped = 0;
+
+retry:
+ sgd = ss.grid;
+ for (i = fy + 1; i < gd->hsize + gd->sy; i++) {
+ first = 0;
+ if (i == fy + 1)
+ first = fx;
+ n = window_copy_search_lr(gd, sgd, &px, i - 1, first, gd->sx);
+ if (n) {
+ window_copy_scroll_to(wp, px, i - 1);
+ break;
+ }
+ }
+ if (!n && !wrapped) {
+ fx = 0;
+ fy = 0;
+ wrapped = 1;
+ goto retry;
+ }
+
+ screen_free(&ss);
+}
+
+void
+window_copy_goto_line(struct window_pane *wp, const char *linestr)
+{
+ struct window_copy_mode_data *data = wp->modedata;
+ const char *errstr;
+ u_int lineno;
+
+ lineno = strtonum(linestr, 0, screen_hsize(&wp->base), &errstr);
+ if (errstr != NULL)
+ return;
+
+ data->oy = lineno;
+ window_copy_redraw_screen(wp);
+}
+
+void
window_copy_write_line(
struct window_pane *wp, struct screen_write_ctx *ctx, u_int py)
{
@@ -282,23 +652,29 @@ window_copy_write_line(
struct screen *s = &data->screen;
struct grid_cell gc;
char hdr[32];
- size_t size;
+ size_t last, xoff = 0, size = 0;
+ memcpy(&gc, &grid_default_cell, sizeof gc);
+ gc.fg = options_get_number(&wp->window->options, "mode-fg");
+ gc.bg = options_get_number(&wp->window->options, "mode-bg");
+ gc.attr |= options_get_number(&wp->window->options, "mode-attr");
+
+ last = screen_size_y(s) - 1;
if (py == 0) {
- memcpy(&gc, &grid_default_cell, sizeof gc);
size = xsnprintf(hdr, sizeof hdr,
"[%u/%u]", data->oy, screen_hsize(&wp->base));
- gc.fg = options_get_number(&wp->window->options, "mode-fg");
- gc.bg = options_get_number(&wp->window->options, "mode-bg");
- gc.attr |= options_get_number(
- &wp->window->options, "mode-attr");
screen_write_cursormove(ctx, screen_size_x(s) - size, 0);
screen_write_puts(ctx, &gc, "%s", hdr);
+ } else if (py == last && data->inputtype != WINDOW_COPY_OFF) {
+ xoff = size = xsnprintf(hdr, sizeof hdr,
+ "%s: %s", data->inputprompt, data->inputstr);
+ screen_write_cursormove(ctx, 0, last);
+ screen_write_puts(ctx, &gc, "%s", hdr);
} else
size = 0;
- screen_write_cursormove(ctx, 0, py);
- screen_write_copy(ctx, &wp->base, 0, (screen_hsize(&wp->base) -
+ screen_write_cursormove(ctx, xoff, py);
+ screen_write_copy(ctx, &wp->base, xoff, (screen_hsize(&wp->base) -
data->oy) + py, screen_size_x(s) - size, 1);
if (py == data->cy && data->cx == screen_size_x(s)) {