mirror of https://github.com/tmux/tmux.git
Add (naive) searching and goto line in copy mode. Searching is C-r and C-s with
emacs keys, / and ? with vi; n repeats the search again with either key set. All searching wraps the top/bottom. Goto line is g for both emacs and vi. The search prompts don't have full line editing, just simple append and delete characters. Also sort the mode keys list in tmux.1.pull/1/head
parent
e7cd547457
commit
c828c2f366
14
mode-key.c
14
mode-key.c
|
@ -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 },
|
||||
|
|
16
tmux.1
16
tmux.1
|
@ -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:
|
||||
|
|
4
tmux.h
4
tmux.h
|
@ -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,
|
||||
|
|
404
window-copy.c
404
window-copy.c
|
@ -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
|
||||
|
@ -274,6 +421,229 @@ window_copy_mouse(struct window_pane *wp,
|
|||
window_copy_redraw_screen(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)) {
|
||||
|
|
Loading…
Reference in New Issue