Merge output (more) and copy modes into one single mode (called copy).

This commit is contained in:
Micah Cowan 2010-04-05 05:11:44 +00:00
parent 5879e2a32b
commit 2d74ce1d3a
10 changed files with 235 additions and 150 deletions

View File

@ -1,4 +1,4 @@
/* $Id: cmd-copy-mode.c,v 1.26 2010-01-05 23:50:22 tcunha Exp $ */
/* $Id: cmd-copy-mode.c,v 1.27 2010-04-05 05:11:42 micahcowan Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -63,6 +63,7 @@ cmd_copy_mode_exec(struct cmd *self, struct cmd_ctx *ctx)
return (-1);
window_pane_set_mode(wp, &window_copy_mode);
window_copy_init_from_pane(wp);
if (wp->mode == &window_copy_mode && cmd_check_flag(data->chflags, 'u'))
window_copy_pageup(wp);

View File

@ -1,4 +1,4 @@
/* $Id: cmd-new-session.c,v 1.76 2010-02-26 13:28:15 tcunha Exp $ */
/* $Id: cmd-new-session.c,v 1.77 2010-04-05 05:11:43 micahcowan Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -287,10 +287,11 @@ cmd_new_session_exec(struct cmd *self, struct cmd_ctx *ctx)
*/
if (cfg_finished && !ARRAY_EMPTY(&cfg_causes)) {
wp = s->curw->window->active;
window_pane_set_mode(wp, &window_more_mode);
window_pane_set_mode(wp, &window_copy_mode);
window_copy_init_for_output(wp);
for (i = 0; i < ARRAY_LENGTH(&cfg_causes); i++) {
cause = ARRAY_ITEM(&cfg_causes, i);
window_more_add(wp, "%s", cause);
window_copy_add(wp, "%s", cause);
xfree(cause);
}
ARRAY_FREE(&cfg_causes);

43
grid.c
View File

@ -1,4 +1,4 @@
/* $Id: grid.c,v 1.36 2009-12-04 22:14:47 tcunha Exp $ */
/* $Id: grid.c,v 1.37 2010-04-05 05:11:43 micahcowan Exp $ */
/*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
@ -46,18 +46,9 @@ const struct grid_cell grid_default_cell = { 0, 0, 8, 8, ' ' };
gc, sizeof gd->linedata[py].utf8data[px]); \
} while (0)
int grid_check_x(struct grid *, u_int);
int grid_check_y(struct grid *, u_int);
#ifdef DEBUG
int
grid_check_x(struct grid *gd, u_int px)
{
if ((px) >= (gd)->sx)
log_fatalx("x out of range: %u", px);
return (0);
}
int
grid_check_y(struct grid *gd, u_int py)
{
@ -66,16 +57,6 @@ grid_check_y(struct grid *gd, u_int py)
return (0);
}
#else
int
grid_check_x(struct grid *gd, u_int px)
{
if ((px) >= (gd)->sx) {
log_debug("x out of range: %u", px);
return (-1);
}
return (0);
}
int
grid_check_y(struct grid *gd, u_int py)
{
@ -270,8 +251,6 @@ grid_expand_line_utf8(struct grid *gd, u_int py, u_int sx)
const struct grid_cell *
grid_peek_cell(struct grid *gd, u_int px, u_int py)
{
if (grid_check_x(gd, px) != 0)
return (&grid_default_cell);
if (grid_check_y(gd, py) != 0)
return (&grid_default_cell);
@ -284,8 +263,6 @@ grid_peek_cell(struct grid *gd, u_int px, u_int py)
struct grid_cell *
grid_get_cell(struct grid *gd, u_int px, u_int py)
{
if (grid_check_x(gd, px) != 0)
return (NULL);
if (grid_check_y(gd, py) != 0)
return (NULL);
@ -298,8 +275,6 @@ void
grid_set_cell(
struct grid *gd, u_int px, u_int py, const struct grid_cell *gc)
{
if (grid_check_x(gd, px) != 0)
return;
if (grid_check_y(gd, py) != 0)
return;
@ -311,8 +286,6 @@ grid_set_cell(
const struct grid_utf8 *
grid_peek_utf8(struct grid *gd, u_int px, u_int py)
{
if (grid_check_x(gd, px) != 0)
return (NULL);
if (grid_check_y(gd, py) != 0)
return (NULL);
@ -325,8 +298,6 @@ grid_peek_utf8(struct grid *gd, u_int px, u_int py)
struct grid_utf8 *
grid_get_utf8(struct grid *gd, u_int px, u_int py)
{
if (grid_check_x(gd, px) != 0)
return (NULL);
if (grid_check_y(gd, py) != 0)
return (NULL);
@ -339,8 +310,6 @@ void
grid_set_utf8(
struct grid *gd, u_int px, u_int py, const struct grid_utf8 *gc)
{
if (grid_check_x(gd, px) != 0)
return;
if (grid_check_y(gd, py) != 0)
return;
@ -364,10 +333,6 @@ grid_clear(struct grid *gd, u_int px, u_int py, u_int nx, u_int ny)
return;
}
if (grid_check_x(gd, px) != 0)
return;
if (grid_check_x(gd, px + nx - 1) != 0)
return;
if (grid_check_y(gd, py) != 0)
return;
if (grid_check_y(gd, py + ny - 1) != 0)
@ -465,12 +430,6 @@ grid_move_cells(struct grid *gd, u_int dx, u_int px, u_int py, u_int nx)
if (nx == 0 || px == dx)
return;
if (grid_check_x(gd, px) != 0)
return;
if (grid_check_x(gd, px + nx - 1) != 0)
return;
if (grid_check_x(gd, dx + nx - 1) != 0)
return;
if (grid_check_y(gd, py) != 0)
return;
gl = &gd->linedata[py];

View File

@ -1,4 +1,4 @@
/* $Id: key-bindings.c,v 1.89 2010-03-15 22:03:38 nicm Exp $ */
/* $Id: key-bindings.c,v 1.90 2010-04-05 05:11:43 micahcowan Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -211,12 +211,14 @@ key_bindings_print(struct cmd_ctx *ctx, const char *fmt, ...)
struct winlink *wl = ctx->curclient->session->curw;
va_list ap;
if (wl->window->active->mode != &window_more_mode)
if (wl->window->active->mode != &window_copy_mode) {
window_pane_reset_mode(wl->window->active);
window_pane_set_mode(wl->window->active, &window_more_mode);
window_pane_set_mode(wl->window->active, &window_copy_mode);
window_copy_init_for_output(wl->window->active);
}
va_start(ap, fmt);
window_more_vadd(wl->window->active, fmt, ap);
window_copy_vadd(wl->window->active, fmt, ap);
va_end(ap);
}

View File

@ -1,4 +1,4 @@
/* $Id: screen-write.c,v 1.88 2009-12-04 22:14:47 tcunha Exp $ */
/* $Id: screen-write.c,v 1.89 2010-04-05 05:11:43 micahcowan Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -1009,13 +1009,14 @@ screen_write_cell(struct screen_write_ctx *ctx,
}
/* Check this will fit on the current line and wrap if not. */
if (s->cx > screen_size_x(s) - width) {
if ((s->mode & MODE_WRAP) && s->cx > screen_size_x(s) - width) {
screen_write_linefeed(ctx, 1);
s->cx = 0; /* carriage return */
}
/* Sanity checks. */
if (s->cx > screen_size_x(s) - 1 || s->cy > screen_size_y(s) - 1)
if (((s->mode & MODE_WRAP) && s->cx > screen_size_x(s) - 1)
|| s->cy > screen_size_y(s) - 1)
return;
/* Handle overwriting of UTF-8 characters. */

View File

@ -1,4 +1,4 @@
/* $Id: screen.c,v 1.99 2010-02-08 18:13:17 tcunha Exp $ */
/* $Id: screen.c,v 1.100 2010-04-05 05:11:44 micahcowan Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -49,7 +49,7 @@ screen_reinit(struct screen *s)
s->rupper = 0;
s->rlower = screen_size_y(s) - 1;
s->mode = MODE_CURSOR;
s->mode = MODE_CURSOR | MODE_WRAP;
screen_reset_tabs(s);

View File

@ -1,4 +1,4 @@
/* $Id: server.c,v 1.236 2010-03-16 23:40:14 nicm Exp $ */
/* $Id: server.c,v 1.237 2010-04-05 05:11:44 micahcowan Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -200,10 +200,11 @@ server_start(char *path)
*/
if (!ARRAY_EMPTY(&sessions) && !ARRAY_EMPTY(&cfg_causes)) {
wp = ARRAY_FIRST(&sessions)->curw->window->active;
window_pane_set_mode(wp, &window_more_mode);
window_pane_set_mode(wp, &window_copy_mode);
window_copy_init_for_output(wp);
for (i = 0; i < ARRAY_LENGTH(&cfg_causes); i++) {
cause = ARRAY_ITEM(&cfg_causes, i);
window_more_add(wp, "%s", cause);
window_copy_add(wp, "%s", cause);
xfree(cause);
}
ARRAY_FREE(&cfg_causes);

28
tmux.1
View File

@ -1,4 +1,4 @@
.\" $Id: tmux.1,v 1.243 2010-03-27 15:12:56 nicm Exp $
.\" $Id: tmux.1,v 1.244 2010-04-05 05:11:44 micahcowan Exp $
.\"
.\" Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
.\"
@ -588,14 +588,8 @@ A
.Nm
window may be in one of several modes.
The default permits direct access to the terminal attached to the window.
The others are:
.Bl -tag -width Ds
.It Em output mode
This is entered when a command which produces output, such as
.Ic list-keys ,
is executed from a key binding.
.It Em copy mode
This permits a section of a window or its history to be copied to a
The other is copy mode, which permits a section of a window or its
history to be copied to a
.Em paste buffer
for later insertion into another window.
This mode is entered with the
@ -603,7 +597,9 @@ This mode is entered with the
command, bound to
.Ql \&[
by default.
.El
It is also entered when a command that produces output, such as
.Ic list-keys ,
is executed from a key binding.
.Pp
The keys available depend on whether emacs or vi mode is selected
(see the
@ -701,7 +697,7 @@ and
.Em emacs-choice
for keys used when choosing from lists (such as produced by the
.Ic choose-window
command) or in output mode; and
command); and
.Em vi-copy
and
.Em emacs-copy
@ -716,7 +712,9 @@ and
The paste buffer key pastes the first line from the top paste buffer on the
stack.
.Pp
The mode commands are as follows:
The synopsis for the
.Ic copy-mode
command is:
.Bl -tag -width Ds
.It Xo Ic copy-mode
.Op Fl u
@ -2021,8 +2019,8 @@ command.
.It Xo Ic synchronize-panes
.Op Ic on | off
.Xc
Duplicate input to any pane to all other panes in the same window, except
for panes that are not in output mode.
Duplicate input to any pane to all other panes in the same window (only
for panes that are not in any special mode).
.Pp
.It Xo Ic alternate-screen
.Op Ic on | off
@ -2432,7 +2430,7 @@ option.
Execute
.Ar shell-command
in the background without creating a window.
After it finishes, any output to stdout is displayed in output mode.
After it finishes, any output to stdout is displayed in copy mode.
If the command doesn't return success, the exit status is also displayed.
.It Ic server-info
.D1 (alias: Ic info )

13
tmux.h
View File

@ -1,4 +1,4 @@
/* $Id: tmux.h,v 1.551 2010-03-27 15:12:56 nicm Exp $ */
/* $Id: tmux.h,v 1.552 2010-04-05 05:11:44 micahcowan Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -540,6 +540,8 @@ struct mode_key_table {
#define MODE_KCURSOR 0x4
#define MODE_KKEYPAD 0x8 /* set = application, clear = number */
#define MODE_MOUSE 0x10
#define MODE_WRAP 0x20 /* whether lines wrap */
/*
* A single UTF-8 character.
@ -1879,13 +1881,12 @@ extern const struct window_mode window_clock_mode;
/* window-copy.c */
extern const struct window_mode window_copy_mode;
void window_copy_init_from_pane(struct window_pane *);
void window_copy_init_for_output(struct window_pane *);
void window_copy_add(struct window_pane *, const char *, ...);
void window_copy_vadd(struct window_pane *, const char *, va_list);
void window_copy_pageup(struct window_pane *);
/* window-more.c */
extern const struct window_mode window_more_mode;
void window_more_add(struct window_pane *, const char *, ...);
void window_more_vadd(struct window_pane *, const char *, va_list);
/* window-choose.c */
extern const struct window_mode window_choose_mode;
void window_choose_vadd(

View File

@ -1,4 +1,4 @@
/* $Id: window-copy.c,v 1.112 2010-03-16 17:51:32 nicm Exp $ */
/* $Id: window-copy.c,v 1.113 2010-04-05 05:11:44 micahcowan Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -93,8 +93,25 @@ enum window_copy_input_type {
WINDOW_COPY_GOTOLINE,
};
/*
* Copy-mode's visible screen (the "screen" field) is filled from one of
* two sources: the original contents of the pane (used when we
* actually enter via the "copy-mode" command, to copy the contents of
* the current pane), or else a series of lines containing the output
* from an output-writing tmux command (such as any of the "show-*" or
* "list-*" commands).
*
* In either case, the full content of the copy-mode grid is pointed at
* by the "backing" field, and is copied into "screen" as needed (that
* is, when scrolling occurs). When copy-mode is backed by a pane,
* backing points directly at that pane's screen structure (&wp->base);
* when backed by a list of output-lines from a command, it points at
* a newly-allocated screen structure (which is deallocated when the
* mode ends).
*/
struct window_copy_mode_data {
struct screen screen;
struct screen *backing;
struct mode_key_data mdata;
@ -111,6 +128,9 @@ struct window_copy_mode_data {
u_int lastcx; /* position in last line with content */
u_int lastsx; /* size of last line with content */
int backing_written; /* where to write next line
in backing */
enum window_copy_input_type inputtype;
const char *inputprompt;
char *inputstr;
@ -129,18 +149,18 @@ window_copy_init(struct window_pane *wp)
{
struct window_copy_mode_data *data;
struct screen *s;
struct screen_write_ctx ctx;
u_int i;
int keys;
wp->modedata = data = xmalloc(sizeof *data);
data->oy = 0;
data->cx = wp->base.cx;
data->cy = wp->base.cy;
data->cx = 0;
data->cy = 0;
data->lastcx = 0;
data->lastsx = 0;
data->backing_written = 0;
data->rectflag = 0;
data->inputtype = WINDOW_COPY_OFF;
@ -168,6 +188,29 @@ window_copy_init(struct window_pane *wp)
else
mode_key_init(&data->mdata, &mode_key_tree_vi_copy);
data->backing = NULL;
return (s);
}
void
window_copy_init_from_pane(struct window_pane *wp)
{
struct window_copy_mode_data *data;
struct screen *s;
struct screen_write_ctx ctx;
u_int i;
if (wp->mode != &window_copy_mode)
fatalx("not in copy mode");
data = wp->modedata;
s = &data->screen;
data->backing = &wp->base;
data->cx = data->backing->cx;
data->cy = data->backing->cy;
s->cx = data->cx;
s->cy = data->cy;
@ -176,8 +219,17 @@ window_copy_init(struct window_pane *wp)
window_copy_write_line(wp, &ctx, i);
screen_write_cursormove(&ctx, data->cx, data->cy);
screen_write_stop(&ctx);
}
return (s);
void
window_copy_init_for_output(struct window_pane *wp)
{
struct window_copy_mode_data *data = wp->modedata;
data->backing = xmalloc(sizeof *data->backing);
screen_init(data->backing, screen_size_x(&wp->base),
screen_size_y(&wp->base), UINT_MAX);
data->backing->mode &= ~MODE_WRAP;
}
void
@ -192,11 +244,73 @@ window_copy_free(struct window_pane *wp)
xfree(data->searchstr);
xfree(data->inputstr);
if (data->backing != &wp->base) {
screen_free(data->backing);
xfree(data->backing);
}
screen_free(&data->screen);
xfree(data);
}
void
window_copy_add(struct window_pane *wp, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
window_copy_vadd(wp, fmt, ap);
va_end(ap);
}
void
window_copy_vadd(struct window_pane *wp, const char *fmt, va_list ap)
{
struct window_copy_mode_data *data = wp->modedata;
struct screen *backing = data->backing;
struct screen_write_ctx back_ctx, ctx;
struct grid_cell gc;
int utf8flag;
u_int old_hsize;
if (backing == &wp->base)
return;
utf8flag = options_get_number(&wp->window->options, "utf8");
memcpy(&gc, &grid_default_cell, sizeof gc);
old_hsize = screen_hsize(data->backing);
screen_write_start(&back_ctx, NULL, backing);
if (data->backing_written) {
/*
* On the second or later line, do a CRLF before writing
* (so it's on a new line).
*/
screen_write_carriagereturn(&back_ctx);
screen_write_linefeed(&back_ctx, 0);
} else
data->backing_written++;
screen_write_vnputs(&back_ctx, 0, &gc, utf8flag, fmt, ap);
screen_write_stop(&back_ctx);
data->oy += screen_hsize(data->backing) - old_hsize;
screen_write_start(&ctx, wp, &data->screen);
/*
* If the history has changed, draw the top line.
* (If there's any history at all, it has changed.)
*/
if (screen_hsize(data->backing))
window_copy_redraw_lines(wp, 0, 1);
/* Write the line, if it's visible. */
if (backing->cy + data->oy < screen_size_y(backing))
window_copy_redraw_lines(wp, backing->cy, 1);
screen_write_stop(&ctx);
}
void
window_copy_pageup(struct window_pane *wp)
{
@ -207,8 +321,8 @@ window_copy_pageup(struct window_pane *wp)
n = 1;
if (screen_size_y(s) > 2)
n = screen_size_y(s) - 2;
if (data->oy + n > screen_hsize(&wp->base))
data->oy = screen_hsize(&wp->base);
if (data->oy + n > screen_hsize(data->backing))
data->oy = screen_hsize(data->backing);
else
data->oy += n;
window_copy_update_selection(wp);
@ -223,6 +337,8 @@ window_copy_resize(struct window_pane *wp, u_int sx, u_int sy)
struct screen_write_ctx ctx;
screen_resize(s, sx, sy);
if (data->backing != &wp->base)
screen_resize(data->backing, sx, sy);
if (data->cy > sy - 1)
data->cy = sy - 1;
@ -329,8 +445,8 @@ window_copy_key(struct window_pane *wp, struct client *c, int key)
case MODEKEYCOPY_HALFPAGEUP:
n = screen_size_y(s) / 2;
for (; np != 0; np--) {
if (data->oy + n > screen_hsize(&wp->base))
data->oy = screen_hsize(&wp->base);
if (data->oy + n > screen_hsize(data->backing))
data->oy = screen_hsize(data->backing);
else
data->oy += n;
}
@ -369,7 +485,7 @@ window_copy_key(struct window_pane *wp, struct client *c, int key)
case MODEKEYCOPY_HISTORYTOP:
data->cx = 0;
data->cy = 0;
data->oy = screen_hsize(&wp->base);
data->oy = screen_hsize(data->backing);
window_copy_update_selection(wp);
window_copy_redraw_screen(wp);
break;
@ -665,8 +781,7 @@ 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;
struct grid *gd = data->backing->grid;
u_int offset, gap;
data->cx = px;
@ -761,7 +876,7 @@ 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 *s = data->backing, ss;
struct screen_write_ctx ctx;
struct grid *gd = s->grid, *sgd;
struct grid_cell gc;
@ -818,7 +933,7 @@ 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 *s = data->backing, ss;
struct screen_write_ctx ctx;
struct grid *gd = s->grid, *sgd;
struct grid_cell gc;
@ -878,7 +993,7 @@ window_copy_goto_line(struct window_pane *wp, const char *linestr)
const char *errstr;
u_int lineno;
lineno = strtonum(linestr, 0, screen_hsize(&wp->base), &errstr);
lineno = strtonum(linestr, 0, screen_hsize(data->backing), &errstr);
if (errstr != NULL)
return;
@ -906,7 +1021,7 @@ window_copy_write_line(
last = screen_size_y(s) - 1;
if (py == 0) {
size = xsnprintf(hdr, sizeof hdr,
"[%u/%u]", data->oy, screen_hsize(&wp->base));
"[%u/%u]", data->oy, screen_hsize(data->backing));
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) {
@ -923,8 +1038,9 @@ window_copy_write_line(
size = 0;
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);
screen_write_copy(ctx, data->backing, xoff,
(screen_hsize(data->backing) - data->oy) + py,
screen_size_x(s) - size, 1);
if (py == data->cy && data->cx == screen_size_x(s)) {
memcpy(&gc, &grid_default_cell, sizeof gc);
@ -993,7 +1109,7 @@ window_copy_start_selection(struct window_pane *wp)
struct screen *s = &data->screen;
data->selx = data->cx;
data->sely = screen_hsize(&wp->base) + data->cy - data->oy;
data->sely = screen_hsize(data->backing) + data->cy - data->oy;
s->sel.flag = 1;
window_copy_update_selection(wp);
@ -1018,7 +1134,7 @@ window_copy_update_selection(struct window_pane *wp)
gc.attr |= options_get_number(oo, "mode-attr");
/* Find top of screen. */
ty = screen_hsize(&wp->base) - data->oy;
ty = screen_hsize(data->backing) - data->oy;
/* Adjust the selection. */
sx = data->selx;
@ -1079,7 +1195,7 @@ window_copy_copy_selection(struct window_pane *wp, struct client *c)
/* Find start and end. */
xx = data->cx;
yy = screen_hsize(&wp->base) + data->cy - data->oy;
yy = screen_hsize(data->backing) + data->cy - data->oy;
if (yy < data->sely || (yy == data->sely && xx < data->selx)) {
sx = xx; sy = yy;
ex = data->selx; ey = data->sely;
@ -1158,12 +1274,13 @@ void
window_copy_copy_line(struct window_pane *wp,
char **buf, size_t *off, u_int sy, u_int sx, u_int ex)
{
struct grid *gd = wp->base.grid;
const struct grid_cell *gc;
const struct grid_utf8 *gu;
struct grid_line *gl;
u_int i, xx, wrapped = 0;
size_t size;
struct window_copy_mode_data *data = wp->modedata;
struct grid *gd = data->backing->grid;
const struct grid_cell *gc;
const struct grid_utf8 *gu;
struct grid_line *gl;
u_int i, xx, wrapped = 0;
size_t size;
if (sx > ex)
return;
@ -1218,7 +1335,7 @@ window_copy_clear_selection(struct window_pane *wp)
screen_clear_selection(&data->screen);
py = screen_hsize(&wp->base) + data->cy - data->oy;
py = screen_hsize(data->backing) + data->cy - data->oy;
px = window_copy_find_length(wp, py);
if (data->cx > px)
window_copy_update_cursor(wp, px, data->cy);
@ -1227,9 +1344,10 @@ window_copy_clear_selection(struct window_pane *wp)
int
window_copy_in_set(struct window_pane *wp, u_int px, u_int py, const char *set)
{
const struct grid_cell *gc;
struct window_copy_mode_data *data = wp->modedata;
const struct grid_cell *gc;
gc = grid_peek_cell(wp->base.grid, px, py);
gc = grid_peek_cell(data->backing->grid, px, py);
if (gc->flags & (GRID_FLAG_PADDING|GRID_FLAG_UTF8))
return (0);
if (gc->data == 0x00 || gc->data == 0x7f)
@ -1240,8 +1358,10 @@ window_copy_in_set(struct window_pane *wp, u_int px, u_int py, const char *set)
u_int
window_copy_find_length(struct window_pane *wp, u_int py)
{
const struct grid_cell *gc;
u_int px;
struct window_copy_mode_data *data = wp->modedata;
struct screen *s = data->backing;
const struct grid_cell *gc;
u_int px;
/*
* If the pane has been resized, its grid can contain old overlong
@ -1249,11 +1369,11 @@ window_copy_find_length(struct window_pane *wp, u_int py)
* width of the grid, and screen_write_copy treats them as spaces, so
* ignore them here too.
*/
px = wp->base.grid->linedata[py].cellsize;
if (px > screen_size_x(&wp->base))
px = screen_size_x(&wp->base);
px = s->grid->linedata[py].cellsize;
if (px > screen_size_x(s))
px = screen_size_x(s);
while (px > 0) {
gc = grid_peek_cell(wp->base.grid, px - 1, py);
gc = grid_peek_cell(s->grid, px - 1, py);
if (gc->flags & GRID_FLAG_UTF8)
break;
if (gc->data != ' ')
@ -1281,11 +1401,11 @@ window_copy_cursor_back_to_indentation(struct window_pane *wp)
const struct grid_cell *gc;
px = 0;
py = screen_hsize(&wp->base) + data->cy - data->oy;
py = screen_hsize(data->backing) + data->cy - data->oy;
xx = window_copy_find_length(wp, py);
while (px < xx) {
gc = grid_peek_cell(wp->base.grid, px, py);
gc = grid_peek_cell(data->backing->grid, px, py);
if (gc->flags & GRID_FLAG_UTF8)
break;
if (gc->data != ' ')
@ -1302,21 +1422,22 @@ void
window_copy_cursor_end_of_line(struct window_pane *wp)
{
struct window_copy_mode_data *data = wp->modedata;
struct screen *base_s = &wp->base;
struct grid *gd = base_s->grid;
struct screen *back_s = data->backing;
struct grid *gd = back_s->grid;
u_int px, py;
py = screen_hsize(base_s) + data->cy - data->oy;
py = screen_hsize(back_s) + data->cy - data->oy;
px = window_copy_find_length(wp, py);
if (data->cx == px) {
if (data->screen.sel.flag && data->rectflag)
px = screen_size_x(&wp->base);
px = screen_size_x(back_s);
if (gd->linedata[py].flags & GRID_LINE_WRAPPED) {
while (py < gd->sy + gd->hsize &&
gd->linedata[py].flags & GRID_LINE_WRAPPED) {
window_copy_cursor_down(wp, 0);
py = screen_hsize(base_s) + data->cy - data->oy;
py = screen_hsize(back_s)
+ data->cy - data->oy;
}
px = window_copy_find_length(wp, py);
}
@ -1351,7 +1472,7 @@ window_copy_cursor_right(struct window_pane *wp)
if (data->screen.sel.flag && data->rectflag)
px = screen_size_x(&data->screen);
else {
py = screen_hsize(&wp->base) + data->cy - data->oy;
py = screen_hsize(data->backing) + data->cy - data->oy;
px = window_copy_find_length(wp, py);
}
@ -1372,7 +1493,7 @@ window_copy_cursor_up(struct window_pane *wp, int scroll_only)
struct screen *s = &data->screen;
u_int ox, oy, px, py;
oy = screen_hsize(&wp->base) + data->cy - data->oy;
oy = screen_hsize(data->backing) + data->cy - data->oy;
ox = window_copy_find_length(wp, oy);
if (ox != 0) {
data->lastcx = data->cx;
@ -1399,7 +1520,7 @@ window_copy_cursor_up(struct window_pane *wp, int scroll_only)
}
if (!data->screen.sel.flag || !data->rectflag) {
py = screen_hsize(&wp->base) + data->cy - data->oy;
py = screen_hsize(data->backing) + data->cy - data->oy;
px = window_copy_find_length(wp, py);
if ((data->cx >= data->lastsx && data->cx != px) ||
data->cx > px)
@ -1414,7 +1535,7 @@ window_copy_cursor_down(struct window_pane *wp, int scroll_only)
struct screen *s = &data->screen;
u_int ox, oy, px, py;
oy = screen_hsize(&wp->base) + data->cy - data->oy;
oy = screen_hsize(data->backing) + data->cy - data->oy;
ox = window_copy_find_length(wp, oy);
if (ox != 0) {
data->lastcx = data->cx;
@ -1433,7 +1554,7 @@ window_copy_cursor_down(struct window_pane *wp, int scroll_only)
}
if (!data->screen.sel.flag || !data->rectflag) {
py = screen_hsize(&wp->base) + data->cy - data->oy;
py = screen_hsize(data->backing) + data->cy - data->oy;
px = window_copy_find_length(wp, py);
if ((data->cx >= data->lastsx && data->cx != px) ||
data->cx > px)
@ -1445,16 +1566,16 @@ void
window_copy_cursor_jump(struct window_pane *wp)
{
struct window_copy_mode_data *data = wp->modedata;
struct screen *base_s = &wp->base;
struct screen *back_s = data->backing;
const struct grid_cell *gc;
uint px, py, xx;
px = data->cx + 1;
py = screen_hsize(base_s) + data->cy - data->oy;
py = screen_hsize(back_s) + data->cy - data->oy;
xx = window_copy_find_length(wp, py);
while (px < xx) {
gc = grid_peek_cell(base_s->grid, px, py);
gc = grid_peek_cell(back_s->grid, px, py);
if ((gc->flags & (GRID_FLAG_PADDING|GRID_FLAG_UTF8)) == 0
&& gc->data == data->jumpchar) {
@ -1471,18 +1592,18 @@ void
window_copy_cursor_jump_back(struct window_pane *wp)
{
struct window_copy_mode_data *data = wp->modedata;
struct screen *base_s = &wp->base;
struct screen *back_s = data->backing;
const struct grid_cell *gc;
uint px, py;
px = data->cx;
py = screen_hsize(base_s) + data->cy - data->oy;
py = screen_hsize(back_s) + data->cy - data->oy;
if (px > 0)
px--;
for (;;) {
gc = grid_peek_cell(base_s->grid, px, py);
gc = grid_peek_cell(back_s->grid, px, py);
if ((gc->flags & (GRID_FLAG_PADDING|GRID_FLAG_UTF8)) == 0
&& gc->data == data->jumpchar) {
@ -1501,14 +1622,14 @@ void
window_copy_cursor_next_word(struct window_pane *wp, const char *separators)
{
struct window_copy_mode_data *data = wp->modedata;
struct screen *base_s = &wp->base;
struct screen *back_s = data->backing;
u_int px, py, xx, yy;
int expected = 0;
px = data->cx;
py = screen_hsize(base_s) + data->cy - data->oy;
py = screen_hsize(back_s) + data->cy - data->oy;
xx = window_copy_find_length(wp, py);
yy = screen_hsize(base_s) + screen_size_y(base_s) - 1;
yy = screen_hsize(back_s) + screen_size_y(back_s) - 1;
/*
* First skip past any nonword characters and then any word characters.
@ -1526,7 +1647,7 @@ window_copy_cursor_next_word(struct window_pane *wp, const char *separators)
window_copy_cursor_down(wp, 0);
px = 0;
py = screen_hsize(base_s) + data->cy - data->oy;
py = screen_hsize(back_s) + data->cy - data->oy;
xx = window_copy_find_length(wp, py);
} else
px++;
@ -1543,14 +1664,14 @@ void
window_copy_cursor_next_word_end(struct window_pane *wp, const char *separators)
{
struct window_copy_mode_data *data = wp->modedata;
struct screen *base_s = &wp->base;
struct screen *back_s = data->backing;
u_int px, py, xx, yy;
int expected = 1;
px = data->cx;
py = screen_hsize(base_s) + data->cy - data->oy;
py = screen_hsize(back_s) + data->cy - data->oy;
xx = window_copy_find_length(wp, py);
yy = screen_hsize(base_s) + screen_size_y(base_s) - 1;
yy = screen_hsize(back_s) + screen_size_y(back_s) - 1;
/*
* First skip past any word characters, then any nonword characters.
@ -1568,7 +1689,7 @@ window_copy_cursor_next_word_end(struct window_pane *wp, const char *separators)
window_copy_cursor_down(wp, 0);
px = 0;
py = screen_hsize(base_s) + data->cy - data->oy;
py = screen_hsize(back_s) + data->cy - data->oy;
xx = window_copy_find_length(wp, py);
} else
px++;
@ -1589,7 +1710,7 @@ window_copy_cursor_previous_word(struct window_pane *wp, const char *separators)
u_int px, py;
px = data->cx;
py = screen_hsize(&wp->base) + data->cy - data->oy;
py = screen_hsize(data->backing) + data->cy - data->oy;
/* Move back to the previous word character. */
for (;;) {
@ -1599,12 +1720,12 @@ window_copy_cursor_previous_word(struct window_pane *wp, const char *separators)
break;
} else {
if (data->cy == 0 &&
(screen_hsize(&wp->base) == 0 ||
data->oy >= screen_hsize(&wp->base) - 1))
(screen_hsize(data->backing) == 0 ||
data->oy >= screen_hsize(data->backing) - 1))
goto out;
window_copy_cursor_up(wp, 0);
py = screen_hsize(&wp->base) + data->cy - data->oy;
py = screen_hsize(data->backing) + data->cy - data->oy;
px = window_copy_find_length(wp, py);
}
}
@ -1657,11 +1778,11 @@ window_copy_scroll_down(struct window_pane *wp, u_int ny)
struct screen *s = &data->screen;
struct screen_write_ctx ctx;
if (ny > screen_hsize(&wp->base))
if (ny > screen_hsize(data->backing))
return;
if (data->oy > screen_hsize(&wp->base) - ny)
ny = screen_hsize(&wp->base) - data->oy;
if (data->oy > screen_hsize(data->backing) - ny)
ny = screen_hsize(data->backing) - data->oy;
if (ny == 0)
return;
data->oy += ny;
@ -1688,7 +1809,7 @@ window_copy_rectangle_toggle(struct window_pane *wp)
data->rectflag = !data->rectflag;
py = screen_hsize(&wp->base) + data->cy - data->oy;
py = screen_hsize(data->backing) + data->cy - data->oy;
px = window_copy_find_length(wp, py);
if (data->cx > px)
window_copy_update_cursor(wp, px, data->cy);