Add a mark in copy mode. Set with set-mark command (bound to 'X') by default

and the mark and cursor position are swapped with 'jump-to-mark' (bound to
M-x). The line containing the mark is shown in copy-mode-mark-style with the
horizontal position in reverse.

From Anindya Mukherjee in GitHub issue 2209.
This commit is contained in:
Nicholas Marriott
2020-05-13 06:29:57 +01:00
parent 9d44df9da9
commit 6214cd0726
4 changed files with 121 additions and 9 deletions

View File

@ -131,6 +131,7 @@ static void window_copy_rectangle_toggle(struct window_mode_entry *);
static void window_copy_move_mouse(struct mouse_event *);
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 *);
const struct window_mode window_copy_mode = {
.name = "copy-mode",
@ -254,6 +255,10 @@ struct window_copy_mode_data {
u_int lastcx; /* position in last line w/ content */
u_int lastsx; /* size of last line w/ content */
u_int mx; /* mark position */
u_int my;
int showmark;
int searchtype;
int searchregex;
char *searchstr;
@ -424,6 +429,9 @@ window_copy_init(struct window_mode_entry *wme,
data->screen.cx = data->cx;
data->screen.cy = data->cy;
data->mx = data->cx;
data->my = screen_hsize(data->backing) + data->cy - data->oy;
data->showmark = 0;
screen_write_start(&ctx, &data->screen);
for (i = 0; i < screen_size_y(&data->screen); i++)
@ -448,6 +456,9 @@ window_copy_view_init(struct window_mode_entry *wme,
data->backing = s = xmalloc(sizeof *data->backing);
screen_init(s, screen_size_x(base), screen_size_y(base), UINT_MAX);
data->mx = data->cx;
data->my = screen_hsize(data->backing) + data->cy - data->oy;
data->showmark = 0;
return (&data->screen);
}
@ -1733,6 +1744,17 @@ window_copy_cmd_select_word(struct window_copy_cmd_state *cs)
return (WINDOW_COPY_CMD_REDRAW);
}
static enum window_copy_cmd_action
window_copy_cmd_set_mark(struct window_copy_cmd_state *cs)
{
struct window_copy_mode_data *data = cs->wme->data;
data->mx = data->cx;
data->my = screen_hsize(data->backing) + data->cy - data->oy;
data->showmark = 1;
return (WINDOW_COPY_CMD_REDRAW);
}
static enum window_copy_cmd_action
window_copy_cmd_start_of_line(struct window_copy_cmd_state *cs)
{
@ -1877,6 +1899,15 @@ window_copy_cmd_jump_to_forward(struct window_copy_cmd_state *cs)
return (WINDOW_COPY_CMD_NOTHING);
}
static enum window_copy_cmd_action
window_copy_cmd_jump_to_mark(struct window_copy_cmd_state *cs)
{
struct window_mode_entry *wme = cs->wme;
window_copy_jump_to_mark(wme);
return (WINDOW_COPY_CMD_NOTHING);
}
static enum window_copy_cmd_action
window_copy_cmd_search_backward(struct window_copy_cmd_state *cs)
{
@ -2154,6 +2185,8 @@ static const struct {
window_copy_cmd_jump_to_backward },
{ "jump-to-forward", 1, 1, 1,
window_copy_cmd_jump_to_forward },
{ "jump-to-mark", 0, 0, 0,
window_copy_cmd_jump_to_mark },
{ "middle-line", 0, 0, 1,
window_copy_cmd_middle_line },
{ "next-matching-bracket", 0, 0, 0,
@ -2214,6 +2247,8 @@ static const struct {
window_copy_cmd_select_line },
{ "select-word", 0, 0, 0,
window_copy_cmd_select_word },
{ "set-mark", 0, 0, 0,
window_copy_cmd_set_mark },
{ "start-of-line", 0, 0, 1,
window_copy_cmd_start_of_line },
{ "stop-selection", 0, 0, 0,
@ -3129,11 +3164,26 @@ window_copy_match_at_cursor(struct window_copy_mode_data *data)
static void
window_copy_update_style(struct window_mode_entry *wme, u_int fx, u_int fy,
struct grid_cell *gc, const struct grid_cell *mgc,
const struct grid_cell *cgc)
const struct grid_cell *cgc, const struct grid_cell *mkgc)
{
struct window_copy_mode_data *data = wme->data;
u_int mark, start, end, cy, cursor, current;
u_int sx = screen_size_x(data->backing);
int inv = 0;
if (data->showmark && fy == data->my) {
gc->attr = mkgc->attr;
if (fx == data->mx)
inv = 1;
if (inv) {
gc->fg = mkgc->bg;
gc->bg = mkgc->fg;
}
else {
gc->fg = mkgc->fg;
gc->bg = mkgc->bg;
}
}
if (data->searchmark == NULL)
return;
@ -3150,21 +3200,34 @@ window_copy_update_style(struct window_mode_entry *wme, u_int fx, u_int fy,
window_copy_match_start_end(data, cursor, &start, &end);
if (current >= start && current <= end) {
gc->attr = cgc->attr;
gc->fg = cgc->fg;
gc->bg = cgc->bg;
if (inv) {
gc->fg = cgc->bg;
gc->bg = cgc->fg;
}
else {
gc->fg = cgc->fg;
gc->bg = cgc->bg;
}
return;
}
}
gc->attr = mgc->attr;
gc->fg = mgc->fg;
gc->bg = mgc->bg;
if (inv) {
gc->fg = mgc->bg;
gc->bg = mgc->fg;
}
else {
gc->fg = mgc->fg;
gc->bg = mgc->bg;
}
}
static void
window_copy_write_one(struct window_mode_entry *wme,
struct screen_write_ctx *ctx, u_int py, u_int fy, u_int nx,
const struct grid_cell *mgc, const struct grid_cell *cgc)
const struct grid_cell *mgc, const struct grid_cell *cgc,
const struct grid_cell *mkgc)
{
struct window_copy_mode_data *data = wme->data;
struct grid *gd = data->backing->grid;
@ -3175,7 +3238,8 @@ window_copy_write_one(struct window_mode_entry *wme,
for (fx = 0; fx < nx; fx++) {
grid_get_cell(gd, fx, fy, &gc);
if (fx + gc.data.width <= nx) {
window_copy_update_style(wme, fx, fy, &gc, mgc, cgc);
window_copy_update_style(wme, fx, fy, &gc, mgc, cgc,
mkgc);
screen_write_cell(ctx, &gc);
}
}
@ -3189,7 +3253,7 @@ window_copy_write_line(struct window_mode_entry *wme,
struct window_copy_mode_data *data = wme->data;
struct screen *s = &data->screen;
struct options *oo = wp->window->options;
struct grid_cell gc, mgc, cgc;
struct grid_cell gc, mgc, cgc, mkgc;
char hdr[512];
size_t size = 0;
u_int hsize = screen_hsize(data->backing);
@ -3200,6 +3264,8 @@ window_copy_write_line(struct window_mode_entry *wme,
mgc.flags |= GRID_FLAG_NOPALETTE;
style_apply(&cgc, oo, "copy-mode-current-match-style", NULL);
cgc.flags |= GRID_FLAG_NOPALETTE;
style_apply(&mkgc, oo, "copy-mode-mark-style", NULL);
mkgc.flags |= GRID_FLAG_NOPALETTE;
if (py == 0 && s->rupper < s->rlower && !data->hide_position) {
if (data->searchmark == NULL) {
@ -3233,7 +3299,7 @@ window_copy_write_line(struct window_mode_entry *wme,
if (size < screen_size_x(s)) {
window_copy_write_one(wme, ctx, py, hsize - data->oy + py,
screen_size_x(s) - size, &mgc, &cgc);
screen_size_x(s) - size, &mgc, &cgc, &mkgc);
}
if (py == data->cy && data->cx == screen_size_x(s)) {
@ -4687,3 +4753,26 @@ window_copy_drag_release(struct client *c, struct mouse_event *m)
data = wme->data;
evtimer_del(&data->dragtimer);
}
static void
window_copy_jump_to_mark(struct window_mode_entry *wme)
{
struct window_copy_mode_data *data = wme->data;
u_int tmx, tmy;
tmx = data->cx;
tmy = screen_hsize(data->backing) + data->cy - data->oy;
data->cx = data->mx;
if (data->my < screen_hsize(data->backing)) {
data->cy = 0;
data->oy = screen_hsize(data->backing) - data->my;
} else {
data->cy = data->my - screen_hsize(data->backing);
data->oy = 0;
}
data->mx = tmx;
data->my = tmy;
data->showmark = 1;
window_copy_update_selection(wme, 0, 0);
window_copy_redraw_screen(wme);
}