mirror of
https://codeberg.org/dnkl/foot.git
synced 2026-02-05 04:06:08 -05:00
search highlights
This commit is contained in:
parent
67120e9940
commit
43dd569afc
6 changed files with 198 additions and 160 deletions
1
config.c
1
config.c
|
|
@ -3304,6 +3304,7 @@ add_default_vimode_search_bindings(struct config *conf)
|
|||
const struct config_key_binding bindings[] = {
|
||||
{BIND_ACTION_VIMODE_SEARCH_CONFIRM, m("none"), {{XKB_KEY_Return}}},
|
||||
{BIND_ACTION_VIMODE_SEARCH_CANCEL, m("none"), {{XKB_KEY_Escape}}},
|
||||
{BIND_ACTION_VIMODE_SEARCH_CANCEL, m(XKB_MOD_NAME_CTRL), {{XKB_KEY_c}}},
|
||||
{BIND_ACTION_VIMODE_SEARCH_DELETE_PREV_CHAR, m("none"), {{XKB_KEY_BackSpace}}},
|
||||
{BIND_ACTION_VIMODE_SEARCH_LEFT, m(XKB_MOD_NAME_CTRL), {{XKB_KEY_h}}},
|
||||
{BIND_ACTION_VIMODE_SEARCH_LEFT, m("none"), {{XKB_KEY_leftarrow}}},
|
||||
|
|
|
|||
161
render.c
161
render.c
|
|
@ -12,6 +12,7 @@
|
|||
#include <pthread.h>
|
||||
|
||||
#include "macros.h"
|
||||
#include "terminal.h"
|
||||
#if HAS_INCLUDE(<pthread_np.h>)
|
||||
#include <pthread_np.h>
|
||||
#define pthread_setname_np(thread, name) (pthread_set_name_np(thread, name), 0)
|
||||
|
|
@ -688,6 +689,30 @@ draw_cursor(const struct terminal *term, const struct cell *cell,
|
|||
}
|
||||
}
|
||||
|
||||
static bool is_cell_highlighted(struct terminal* const term,
|
||||
struct coord const cell)
|
||||
{
|
||||
struct highlight_location const* location = term->vimode.highlights;
|
||||
int const row_abs = grid_row_absolute_in_view(term->grid, cell.row);
|
||||
while(location != NULL) {
|
||||
// End the search early if we are past the possible locations.
|
||||
if(location->range.start.row > row_abs) {
|
||||
break;
|
||||
}
|
||||
|
||||
int const start_col = location->range.start.col;
|
||||
int const end_col = location->range.end.col;
|
||||
if(location->range.start.row == row_abs && cell.col >= start_col &&
|
||||
cell.col <= end_col)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
location = location->next;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static int
|
||||
render_cell(struct terminal *term, pixman_image_t *pix,
|
||||
pixman_region32_t *damage, struct row *row, int row_no, int col,
|
||||
|
|
@ -706,6 +731,8 @@ render_cell(struct terminal *term, pixman_image_t *pix,
|
|||
const int y = term->margins.top + row_no * height;
|
||||
|
||||
const bool is_selected = cell->attrs.selected;
|
||||
const bool is_highlighted =
|
||||
is_cell_highlighted(term, (struct coord){.row = row_no, .col = col});
|
||||
|
||||
uint32_t _fg = 0;
|
||||
uint32_t _bg = 0;
|
||||
|
|
@ -785,6 +812,12 @@ render_cell(struct terminal *term, pixman_image_t *pix,
|
|||
alpha = 0xffff;
|
||||
}
|
||||
} else {
|
||||
if(is_highlighted) {
|
||||
// TODO (kociap): colors for the highlight.
|
||||
_fg = term->colors.table[0];
|
||||
_bg = term->colors.table[1];
|
||||
}
|
||||
|
||||
if (unlikely(cell->attrs.reverse)) {
|
||||
uint32_t swap = _fg;
|
||||
_fg = _bg;
|
||||
|
|
@ -1980,7 +2013,7 @@ render_overlay(struct terminal *term)
|
|||
const bool unicode_mode_active = term->unicode_mode.active;
|
||||
|
||||
const enum overlay_style style =
|
||||
term->is_vimming ? OVERLAY_SEARCH :
|
||||
term->is_vimming ? OVERLAY_NONE :
|
||||
term->flash.active ? OVERLAY_FLASH :
|
||||
unicode_mode_active ? OVERLAY_UNICODE_MODE :
|
||||
OVERLAY_NONE;
|
||||
|
|
@ -1999,7 +2032,6 @@ render_overlay(struct terminal *term)
|
|||
pixman_color_t color;
|
||||
|
||||
switch (style) {
|
||||
case OVERLAY_SEARCH:
|
||||
case OVERLAY_UNICODE_MODE:
|
||||
color = (pixman_color_t){0, 0, 0, 0x7fff};
|
||||
break;
|
||||
|
|
@ -2033,125 +2065,8 @@ render_overlay(struct terminal *term)
|
|||
/* Bounding rectangle of damaged areas - for wl_surface_damage_buffer() */
|
||||
pixman_box32_t damage_bounds;
|
||||
|
||||
if (style == OVERLAY_SEARCH) {
|
||||
/*
|
||||
* When possible, we only update the areas that have *changed*
|
||||
* since the last frame. That means:
|
||||
*
|
||||
* - clearing/erasing cells that are now selected, but weren't
|
||||
* in the last frame
|
||||
* - dimming cells that were selected, but aren't anymore
|
||||
*
|
||||
* To do this, we save the last frame's selected cells as a
|
||||
* pixman region.
|
||||
*
|
||||
* Then, we calculate the corresponding region for this
|
||||
* frame's selected cells.
|
||||
*
|
||||
* Last frame's region minus this frame's region gives us the
|
||||
* region that needs to be *dimmed* in this frame
|
||||
*
|
||||
* This frame's region minus last frame's region gives us the
|
||||
* region that needs to be *cleared* in this frame.
|
||||
*
|
||||
* Finally, the union of the two "diff" regions above, gives
|
||||
* us the total region affected by a change, in either way. We
|
||||
* use this as the bounding box for the
|
||||
* wl_surface_damage_buffer() call.
|
||||
*/
|
||||
pixman_region32_t *see_through = &term->render.last_overlay_clip;
|
||||
pixman_region32_t old_see_through;
|
||||
const bool buffer_reuse =
|
||||
buf == term->render.last_overlay_buf &&
|
||||
style == term->render.last_overlay_style &&
|
||||
buf->age == 0;
|
||||
|
||||
if (!buffer_reuse) {
|
||||
/* Can't reuse last frame's damage - set to full window,
|
||||
* to ensure *everything* is updated */
|
||||
pixman_region32_init_rect(
|
||||
&old_see_through, 0, 0, buf->width, buf->height);
|
||||
} else {
|
||||
/* Use last frame's saved region */
|
||||
pixman_region32_init(&old_see_through);
|
||||
pixman_region32_copy(&old_see_through, see_through);
|
||||
}
|
||||
|
||||
pixman_region32_clear(see_through);
|
||||
|
||||
/* Build region consisting of all current search matches */
|
||||
// TODO (kociap): commented this because no search atm.
|
||||
// struct search_match_iterator iter = search_matches_new_iter(term);
|
||||
// for (struct range match = search_matches_next(&iter);
|
||||
// match.start.row >= 0;
|
||||
// match = search_matches_next(&iter))
|
||||
// {
|
||||
// int r = match.start.row;
|
||||
// int start_col = match.start.col;
|
||||
// const int end_row = match.end.row;
|
||||
//
|
||||
// while (true) {
|
||||
// const int end_col =
|
||||
// r == end_row ? match.end.col : term->cols - 1;
|
||||
//
|
||||
// int x = term->margins.left + start_col * term->cell_width;
|
||||
// int y = term->margins.top + r * term->cell_height;
|
||||
// int width = (end_col + 1 - start_col) * term->cell_width;
|
||||
// int height = 1 * term->cell_height;
|
||||
//
|
||||
// pixman_region32_union_rect(
|
||||
// see_through, see_through, x, y, width, height);
|
||||
//
|
||||
// if (++r > end_row)
|
||||
// break;
|
||||
//
|
||||
// start_col = 0;
|
||||
// }
|
||||
// }
|
||||
|
||||
/* Areas that need to be cleared: cells that were dimmed in
|
||||
* the last frame but is now see-through */
|
||||
pixman_region32_t new_see_through;
|
||||
pixman_region32_init(&new_see_through);
|
||||
|
||||
if (buffer_reuse)
|
||||
pixman_region32_subtract(&new_see_through, see_through, &old_see_through);
|
||||
else {
|
||||
/* Buffer content is unknown - explicitly clear *all*
|
||||
* current see-through areas */
|
||||
pixman_region32_copy(&new_see_through, see_through);
|
||||
}
|
||||
pixman_image_set_clip_region32(buf->pix[0], &new_see_through);
|
||||
|
||||
/* Areas that need to be dimmed: cells that were cleared in
|
||||
* the last frame but is not anymore */
|
||||
pixman_region32_t new_dimmed;
|
||||
pixman_region32_init(&new_dimmed);
|
||||
pixman_region32_subtract(&new_dimmed, &old_see_through, see_through);
|
||||
pixman_region32_fini(&old_see_through);
|
||||
|
||||
/* Total affected area */
|
||||
pixman_region32_t damage;
|
||||
pixman_region32_init(&damage);
|
||||
pixman_region32_union(&damage, &new_see_through, &new_dimmed);
|
||||
damage_bounds = damage.extents;
|
||||
|
||||
/* Clear cells that became selected in this frame. */
|
||||
pixman_image_fill_rectangles(
|
||||
PIXMAN_OP_SRC, buf->pix[0], &(pixman_color_t){0}, 1,
|
||||
&(pixman_rectangle16_t){0, 0, term->width, term->height});
|
||||
|
||||
/* Set clip region for the newly dimmed cells. The actual
|
||||
* paint call is done below */
|
||||
pixman_image_set_clip_region32(buf->pix[0], &new_dimmed);
|
||||
|
||||
pixman_region32_fini(&new_see_through);
|
||||
pixman_region32_fini(&new_dimmed);
|
||||
pixman_region32_fini(&damage);
|
||||
}
|
||||
|
||||
else if (buf == term->render.last_overlay_buf &&
|
||||
style == term->render.last_overlay_style)
|
||||
if (buf == term->render.last_overlay_buf &&
|
||||
style == term->render.last_overlay_style)
|
||||
{
|
||||
xassert(style == OVERLAY_FLASH || style == OVERLAY_UNICODE_MODE);
|
||||
shm_did_not_use_buf(buf);
|
||||
|
|
@ -3627,8 +3542,7 @@ grid_render(struct terminal *term)
|
|||
|
||||
pixman_region32_fini(&damage);
|
||||
|
||||
// TODO (kociap): we want to eventually render the overlays.
|
||||
// render_overlay(term);
|
||||
render_overlay(term);
|
||||
render_ime_preedit(term, buf);
|
||||
render_scrollback_position(term);
|
||||
|
||||
|
|
@ -3747,7 +3661,6 @@ render_search_box_cursor(
|
|||
static void
|
||||
render_search_box(struct terminal *term)
|
||||
{
|
||||
printf("REDRAWING SEARCH BOX\n");
|
||||
xassert(term->window->search.sub != NULL);
|
||||
|
||||
/*
|
||||
|
|
|
|||
12
terminal.c
12
terminal.c
|
|
@ -2479,6 +2479,18 @@ term_font_baseline(const struct terminal *term)
|
|||
return term->font_y_ofs + line_height - glyph_top_y - font->descent;
|
||||
}
|
||||
|
||||
void
|
||||
term_damage_cell(struct terminal* const term, int const row, int const col)
|
||||
{
|
||||
if(col >= term->grid->num_cols || col < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
struct row* const r = grid_row(term->grid, row);
|
||||
r->dirty = true;
|
||||
r->cells[col].attrs.clean = 0;
|
||||
}
|
||||
|
||||
void
|
||||
term_damage_cell_in_view(struct terminal* const term, int const row, int const col)
|
||||
{
|
||||
|
|
|
|||
12
terminal.h
12
terminal.h
|
|
@ -374,8 +374,6 @@ enum term_surface {
|
|||
|
||||
enum overlay_style {
|
||||
OVERLAY_NONE,
|
||||
// TODO (kociap): rename to OVERLAY_VIMODE
|
||||
OVERLAY_SEARCH,
|
||||
OVERLAY_FLASH,
|
||||
OVERLAY_UNICODE_MODE,
|
||||
};
|
||||
|
|
@ -658,6 +656,15 @@ struct terminal {
|
|||
size_t len;
|
||||
enum search_direction direction;
|
||||
} confirmed_search;
|
||||
|
||||
/*
|
||||
* Highlight ranges in absolute coordinates.
|
||||
* Sorted in ascending order by the start row and column.
|
||||
*/
|
||||
struct highlight_location {
|
||||
struct highlight_location const* next;
|
||||
struct range range;
|
||||
} const* highlights;
|
||||
} vimode;
|
||||
|
||||
struct wayland *wl;
|
||||
|
|
@ -899,6 +906,7 @@ int term_pt_or_px_as_pixels(
|
|||
|
||||
void term_window_configured(struct terminal *term);
|
||||
|
||||
void term_damage_cell(struct terminal* term, int row, int col);
|
||||
void term_damage_cell_in_view(struct terminal* term, int row, int col);
|
||||
void term_damage_rows(struct terminal *term, int start, int end);
|
||||
void term_damage_rows_in_view(struct terminal *term, int start, int end);
|
||||
|
|
|
|||
166
vimode.c
166
vimode.c
|
|
@ -88,6 +88,7 @@ static void damage_cursor_cell(struct terminal *const term) {
|
|||
struct coord const cursor =
|
||||
offset_to_view_relative(term, term->vimode.cursor);
|
||||
term_damage_cell_in_view(term, cursor.row, cursor.col);
|
||||
render_refresh(term);
|
||||
}
|
||||
|
||||
static void clip_cursor_to_view(struct terminal *const term) {
|
||||
|
|
@ -140,6 +141,102 @@ static void update_selection(struct seat *const seat,
|
|||
}
|
||||
}
|
||||
|
||||
static void damage_highlights(struct terminal *const term) {
|
||||
struct highlight_location const *location = term->vimode.highlights;
|
||||
int const offset = term->grid->offset;
|
||||
printf("DAMAGING HIGHLIGHT CELLS: ");
|
||||
while (location != NULL) {
|
||||
struct coord const start = location->range.start;
|
||||
struct coord const end = location->range.end;
|
||||
for (int col = start.col; col <= end.col; col += 1) {
|
||||
printf("(%d, %d) ", start.row, col);
|
||||
term_damage_cell(term, start.row - offset, col);
|
||||
}
|
||||
location = location->next;
|
||||
}
|
||||
printf("\n");
|
||||
render_refresh(term);
|
||||
}
|
||||
|
||||
static void clear_highlights(struct terminal *const term) {
|
||||
damage_highlights(term);
|
||||
struct highlight_location const *location = term->vimode.highlights;
|
||||
while (location != NULL) {
|
||||
struct highlight_location const *next = location->next;
|
||||
free((void *)location);
|
||||
location = next;
|
||||
}
|
||||
term->vimode.highlights = NULL;
|
||||
}
|
||||
|
||||
// calculate_highlight_regions
|
||||
//
|
||||
// Build a list of regions consisting of all current search matches.
|
||||
// The regions are split so that each one spans at most a single line.
|
||||
// The regions are in absolute row coordinates.
|
||||
//
|
||||
static void calculate_highlight_regions(struct terminal *const term) {
|
||||
char32_t const *search_buf = term->vimode.search.buf;
|
||||
size_t search_len = term->vimode.search.len;
|
||||
if (search_buf == NULL) {
|
||||
search_buf = term->vimode.confirmed_search.buf;
|
||||
search_len = term->vimode.confirmed_search.len;
|
||||
}
|
||||
|
||||
struct highlight_location *start = NULL;
|
||||
struct highlight_location *current = NULL;
|
||||
struct search_match_iterator iter =
|
||||
search_matches_new_iter(term, search_buf, search_len);
|
||||
for (struct range match = search_matches_next(&iter); match.start.row >= 0;
|
||||
match = search_matches_next(&iter)) {
|
||||
int r = match.start.row;
|
||||
int start_col = match.start.col;
|
||||
int const end_row = match.end.row;
|
||||
|
||||
while (true) {
|
||||
const int end_col = r == end_row ? match.end.col : term->cols - 1;
|
||||
struct highlight_location *location =
|
||||
xmalloc(sizeof(struct highlight_location));
|
||||
location->next = NULL;
|
||||
location->range = (struct range){
|
||||
.start.row = r,
|
||||
.start.col = start_col,
|
||||
.end.row = end_row,
|
||||
.end.col = end_col,
|
||||
};
|
||||
r += 1;
|
||||
start_col = 0;
|
||||
if (start != NULL) {
|
||||
current->next = location;
|
||||
current = location;
|
||||
} else {
|
||||
start = location;
|
||||
current = location;
|
||||
}
|
||||
if (r > end_row) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
term->vimode.highlights = start;
|
||||
}
|
||||
|
||||
static void update_highlights(struct terminal *const term) {
|
||||
clear_highlights(term);
|
||||
calculate_highlight_regions(term);
|
||||
struct highlight_location const *location = term->vimode.highlights;
|
||||
printf("NEW HIGHLIGHT REGIONS: ");
|
||||
while (location != NULL) {
|
||||
struct highlight_location const *next = location->next;
|
||||
printf("[(%d, %d) - (%d, %d)] ", location->range.start.row,
|
||||
location->range.start.col, location->range.end.row,
|
||||
location->range.end.col);
|
||||
location = next;
|
||||
}
|
||||
printf("\n");
|
||||
damage_highlights(term);
|
||||
}
|
||||
|
||||
/*
|
||||
* Ensures a "new" viewport doesn't contain any unallocated rows.
|
||||
*
|
||||
|
|
@ -309,6 +406,7 @@ void vimode_cancel(struct terminal *term) {
|
|||
printf("VIMODE CANCEL\n");
|
||||
|
||||
cancel_search(term, false);
|
||||
clear_highlights(term);
|
||||
|
||||
term->is_vimming = false;
|
||||
|
||||
|
|
@ -534,22 +632,25 @@ static bool find_next_from_cursor(struct terminal *const term,
|
|||
return find_next(term, buf, len, direction, start, end, match);
|
||||
}
|
||||
|
||||
struct search_match_iterator search_matches_new_iter(struct terminal *term) {
|
||||
struct search_match_iterator
|
||||
search_matches_new_iter(struct terminal *const term, char32_t const *const buf,
|
||||
size_t const len) {
|
||||
return (struct search_match_iterator){
|
||||
.term = term,
|
||||
.start = {0, 0},
|
||||
.buf = buf,
|
||||
.len = len,
|
||||
};
|
||||
}
|
||||
|
||||
struct range search_matches_next(struct search_match_iterator *iter) {
|
||||
struct terminal *term = iter->term;
|
||||
struct grid *grid = term->grid;
|
||||
|
||||
if (term->vimode.search.match_len == 0)
|
||||
goto no_match;
|
||||
|
||||
if (iter->start.row >= term->rows)
|
||||
goto no_match;
|
||||
if (iter->buf == NULL || iter->len == 0 || iter->start.row >= term->rows) {
|
||||
iter->start.row = -1;
|
||||
iter->start.col = -1;
|
||||
return (struct range){{-1, -1}, {-1, -1}};
|
||||
}
|
||||
|
||||
xassert(iter->start.row >= 0);
|
||||
xassert(iter->start.row < term->rows);
|
||||
|
|
@ -565,43 +666,34 @@ struct range search_matches_next(struct search_match_iterator *iter) {
|
|||
/* BUG: matches *starting* outside the view, but ending *inside*, aren't
|
||||
* matched */
|
||||
struct range match;
|
||||
// TODO (kociap): consider whether using active search buffer is
|
||||
// reasonable.
|
||||
bool found = find_next(term, term->vimode.search.buf, term->vimode.search.len,
|
||||
SEARCH_FORWARD, abs_start, abs_end, &match);
|
||||
if (!found)
|
||||
goto no_match;
|
||||
bool found = find_next(term, iter->buf, iter->len, SEARCH_FORWARD, abs_start,
|
||||
abs_end, &match);
|
||||
if (!found) {
|
||||
iter->start.row = -1;
|
||||
iter->start.col = -1;
|
||||
return (struct range){{-1, -1}, {-1, -1}};
|
||||
}
|
||||
|
||||
LOG_DBG("match at (absolute coordinates) %dx%d-%dx%d", match.start.row,
|
||||
match.start.col, match.end.row, match.end.col);
|
||||
|
||||
/* Convert absolute row numbers back to view relative */
|
||||
match.start.row = match.start.row - grid->view + grid->num_rows;
|
||||
match.start.row &= grid->num_rows - 1;
|
||||
match.end.row = match.end.row - grid->view + grid->num_rows;
|
||||
match.end.row &= grid->num_rows - 1;
|
||||
|
||||
LOG_DBG("match at (view-local coordinates) %dx%d-%dx%d, view=%d",
|
||||
match.start.row, match.start.col, match.end.row, match.end.col,
|
||||
grid->view);
|
||||
|
||||
/* Assert match end comes *after* the match start */
|
||||
xassert(
|
||||
match.end.row > match.start.row ||
|
||||
(match.end.row == match.start.row && match.end.col >= match.start.col));
|
||||
|
||||
/* Assert the match starts at, or after, the iterator position */
|
||||
xassert(match.start.row > iter->start.row ||
|
||||
(match.start.row == iter->start.row &&
|
||||
match.start.col >= iter->start.col));
|
||||
xassert(
|
||||
match.start.row > abs_start.row ||
|
||||
(match.start.row == abs_start.row && match.start.col >= abs_start.col));
|
||||
|
||||
/* Continue at next column, next time */
|
||||
iter->start.row = match.start.row;
|
||||
iter->start.row += match.start.row - abs_start.row;
|
||||
iter->start.col = match.start.col + 1;
|
||||
|
||||
if (iter->start.col >= term->cols) {
|
||||
iter->start.col = 0;
|
||||
iter->start.row++; /* Overflow is caught in next iteration */
|
||||
iter->start.row += 1; /* Overflow is caught in next iteration */
|
||||
}
|
||||
|
||||
xassert(iter->start.row >= 0);
|
||||
|
|
@ -609,11 +701,6 @@ struct range search_matches_next(struct search_match_iterator *iter) {
|
|||
xassert(iter->start.col >= 0);
|
||||
xassert(iter->start.col < term->cols);
|
||||
return match;
|
||||
|
||||
no_match:
|
||||
iter->start.row = -1;
|
||||
iter->start.col = -1;
|
||||
return (struct range){{-1, -1}, {-1, -1}};
|
||||
}
|
||||
|
||||
static void add_wchars(struct terminal *term, char32_t *src, size_t count) {
|
||||
|
|
@ -717,6 +804,7 @@ void vimode_view_down(struct terminal *const term, int const delta) {
|
|||
term->vimode.cursor.row -= delta;
|
||||
printf("VIMODE VIEW DOWN [delta=%d]\n", delta);
|
||||
clip_cursor_to_view(term);
|
||||
update_highlights(term);
|
||||
}
|
||||
|
||||
static void move_cursor_delta(struct terminal *const term,
|
||||
|
|
@ -792,11 +880,13 @@ static void execute_vimode_binding(struct seat *seat, struct terminal *term,
|
|||
case BIND_ACTION_VIMODE_UP:
|
||||
move_cursor_vertical(term, -1);
|
||||
update_selection(seat, term);
|
||||
update_highlights(term);
|
||||
break;
|
||||
|
||||
case BIND_ACTION_VIMODE_DOWN:
|
||||
move_cursor_vertical(term, 1);
|
||||
update_selection(seat, term);
|
||||
update_highlights(term);
|
||||
break;
|
||||
|
||||
case BIND_ACTION_VIMODE_LEFT:
|
||||
|
|
@ -813,36 +903,42 @@ static void execute_vimode_binding(struct seat *seat, struct terminal *term,
|
|||
cmd_scrollback_up(term, term->rows);
|
||||
clip_cursor_to_view(term);
|
||||
update_selection(seat, term);
|
||||
update_highlights(term);
|
||||
break;
|
||||
|
||||
case BIND_ACTION_VIMODE_DOWN_PAGE:
|
||||
cmd_scrollback_down(term, term->rows);
|
||||
clip_cursor_to_view(term);
|
||||
update_selection(seat, term);
|
||||
update_highlights(term);
|
||||
break;
|
||||
|
||||
case BIND_ACTION_VIMODE_UP_HALF_PAGE:
|
||||
cmd_scrollback_up(term, max(term->rows / 2, 1));
|
||||
clip_cursor_to_view(term);
|
||||
update_selection(seat, term);
|
||||
update_highlights(term);
|
||||
break;
|
||||
|
||||
case BIND_ACTION_VIMODE_DOWN_HALF_PAGE:
|
||||
cmd_scrollback_down(term, max(term->rows / 2, 1));
|
||||
clip_cursor_to_view(term);
|
||||
update_selection(seat, term);
|
||||
update_highlights(term);
|
||||
break;
|
||||
|
||||
case BIND_ACTION_VIMODE_UP_LINE:
|
||||
cmd_scrollback_up(term, 1);
|
||||
clip_cursor_to_view(term);
|
||||
update_selection(seat, term);
|
||||
update_highlights(term);
|
||||
break;
|
||||
|
||||
case BIND_ACTION_VIMODE_DOWN_LINE:
|
||||
cmd_scrollback_down(term, 1);
|
||||
clip_cursor_to_view(term);
|
||||
update_selection(seat, term);
|
||||
update_highlights(term);
|
||||
break;
|
||||
|
||||
case BIND_ACTION_VIMODE_FIRST_LINE:
|
||||
|
|
@ -851,6 +947,7 @@ static void execute_vimode_binding(struct seat *seat, struct terminal *term,
|
|||
term->vimode.cursor.row = cursor_from_scrollback_relative(term, 0);
|
||||
damage_cursor_cell(term);
|
||||
update_selection(seat, term);
|
||||
update_highlights(term);
|
||||
break;
|
||||
|
||||
case BIND_ACTION_VIMODE_LAST_LINE:
|
||||
|
|
@ -859,6 +956,7 @@ static void execute_vimode_binding(struct seat *seat, struct terminal *term,
|
|||
term->vimode.cursor.row = term->rows - 1;
|
||||
damage_cursor_cell(term);
|
||||
update_selection(seat, term);
|
||||
update_highlights(term);
|
||||
break;
|
||||
|
||||
case BIND_ACTION_VIMODE_CANCEL: {
|
||||
|
|
@ -906,6 +1004,7 @@ static void execute_vimode_binding(struct seat *seat, struct terminal *term,
|
|||
// TODO (kociap): update selection.
|
||||
move_cursor_delta(term, delta);
|
||||
}
|
||||
update_highlights(term);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -1170,6 +1269,7 @@ void vimode_input(struct seat *seat, struct terminal *term,
|
|||
} else {
|
||||
restore_pre_search_state(term);
|
||||
}
|
||||
update_highlights(term);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
6
vimode.h
6
vimode.h
|
|
@ -25,9 +25,13 @@ void vimode_input(struct seat *seat, struct terminal *term,
|
|||
struct search_match_iterator {
|
||||
struct terminal *term;
|
||||
struct coord start;
|
||||
char32_t const *buf;
|
||||
size_t len;
|
||||
};
|
||||
|
||||
struct search_match_iterator search_matches_new_iter(struct terminal *term);
|
||||
struct search_match_iterator search_matches_new_iter(struct terminal *term,
|
||||
char32_t const *const buf,
|
||||
size_t const len);
|
||||
struct range search_matches_next(struct search_match_iterator *iter);
|
||||
|
||||
void vimode_view_down(struct terminal *term, int delta);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue