mirror of
https://codeberg.org/dnkl/foot.git
synced 2026-04-05 07:15:30 -04:00
Merge branch 'scrollback-search-extend-to-end-of-word'
This commit is contained in:
commit
ba399fa874
7 changed files with 228 additions and 110 deletions
11
README.md
11
README.md
|
|
@ -118,6 +118,17 @@ available:
|
||||||
|
|
||||||
Search _forward_ for next match
|
Search _forward_ for next match
|
||||||
|
|
||||||
|
* <kbd>ctrl</kbd>+<kbd>w</kbd>
|
||||||
|
|
||||||
|
Extend current selection (and thus the search criteria) to the end
|
||||||
|
of the word, or the next word if currently at a word separating
|
||||||
|
character.
|
||||||
|
|
||||||
|
* <kbd>ctrl</kbd>+<kbd>shift</kbd><kbd>w</kbd>
|
||||||
|
|
||||||
|
Same as <kbd>ctrl</kbd>+<kbd>w</kbd>, except that the only word
|
||||||
|
separating characters are whitespace characters.
|
||||||
|
|
||||||
* <kbd>escape</kbd>, <kbd>ctrl</kbd>+<kbd>g</kbd>
|
* <kbd>escape</kbd>, <kbd>ctrl</kbd>+<kbd>g</kbd>
|
||||||
|
|
||||||
Cancel the search
|
Cancel the search
|
||||||
|
|
|
||||||
|
|
@ -75,6 +75,7 @@ executable(
|
||||||
'input.c', 'input.h',
|
'input.c', 'input.h',
|
||||||
'log.c', 'log.h',
|
'log.c', 'log.h',
|
||||||
'main.c',
|
'main.c',
|
||||||
|
'misc.c', 'misc.h',
|
||||||
'osc.c', 'osc.h',
|
'osc.c', 'osc.h',
|
||||||
'render.c', 'render.h',
|
'render.c', 'render.h',
|
||||||
'search.c', 'search.h',
|
'search.c', 'search.h',
|
||||||
|
|
|
||||||
24
misc.c
Normal file
24
misc.c
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
#include "misc.h"
|
||||||
|
|
||||||
|
#include <wctype.h>
|
||||||
|
|
||||||
|
bool
|
||||||
|
isword(wchar_t wc, bool spaces_only)
|
||||||
|
{
|
||||||
|
if (spaces_only)
|
||||||
|
return iswgraph(wc);
|
||||||
|
|
||||||
|
switch (wc) {
|
||||||
|
default: return iswgraph(wc);
|
||||||
|
|
||||||
|
case L'(': case L')':
|
||||||
|
case L'[': case L']':
|
||||||
|
case L'{': case L'}':
|
||||||
|
case L'<': case L'>':
|
||||||
|
case L'│': case L'|':
|
||||||
|
case L',':
|
||||||
|
case L'`': case L'"': case L'\'':
|
||||||
|
case L':':
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
6
misc.h
Normal file
6
misc.h
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <wchar.h>
|
||||||
|
|
||||||
|
bool isword(wchar_t wc, bool spaces_only);
|
||||||
3
render.c
3
render.c
|
|
@ -795,7 +795,8 @@ render_search_box(struct terminal *term)
|
||||||
|
|
||||||
wl_subsurface_set_position(
|
wl_subsurface_set_position(
|
||||||
term->window->search_sub_surface,
|
term->window->search_sub_surface,
|
||||||
term->width - width - margin, term->height - height - margin);
|
max(0, term->width - width - margin),
|
||||||
|
max(0, term->height - height - margin));
|
||||||
|
|
||||||
wl_surface_damage_buffer(term->window->search_surface, 0, 0, width, height);
|
wl_surface_damage_buffer(term->window->search_surface, 0, 0, width, height);
|
||||||
wl_surface_attach(term->window->search_surface, buf->wl_buf, 0, 0);
|
wl_surface_attach(term->window->search_surface, buf->wl_buf, 0, 0);
|
||||||
|
|
|
||||||
271
search.c
271
search.c
|
|
@ -11,12 +11,32 @@
|
||||||
#define LOG_ENABLE_DBG 0
|
#define LOG_ENABLE_DBG 0
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "grid.h"
|
#include "grid.h"
|
||||||
|
#include "misc.h"
|
||||||
#include "render.h"
|
#include "render.h"
|
||||||
#include "selection.h"
|
#include "selection.h"
|
||||||
#include "shm.h"
|
#include "shm.h"
|
||||||
|
|
||||||
#define max(x, y) ((x) > (y) ? (x) : (y))
|
#define max(x, y) ((x) > (y) ? (x) : (y))
|
||||||
|
|
||||||
|
static bool
|
||||||
|
search_ensure_size(struct terminal *term, size_t wanted_size)
|
||||||
|
{
|
||||||
|
while (wanted_size >= term->search.sz) {
|
||||||
|
size_t new_sz = term->search.sz == 0 ? 64 : term->search.sz * 2;
|
||||||
|
wchar_t *new_buf = realloc(term->search.buf, new_sz * sizeof(term->search.buf[0]));
|
||||||
|
|
||||||
|
if (new_buf == NULL) {
|
||||||
|
LOG_ERRNO("failed to resize search buffer");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
term->search.buf = new_buf;
|
||||||
|
term->search.sz = new_sz;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
search_cancel_keep_selection(struct terminal *term)
|
search_cancel_keep_selection(struct terminal *term)
|
||||||
{
|
{
|
||||||
|
|
@ -64,7 +84,75 @@ search_cancel(struct terminal *term)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
search_update(struct terminal *term)
|
search_update_selection(struct terminal *term,
|
||||||
|
int start_row, int start_col,
|
||||||
|
int end_row, int end_col)
|
||||||
|
{
|
||||||
|
int old_view = term->grid->view;
|
||||||
|
int new_view = start_row;
|
||||||
|
|
||||||
|
/* Prevent scrolling in uninitialized rows */
|
||||||
|
bool all_initialized = false;
|
||||||
|
do {
|
||||||
|
all_initialized = true;
|
||||||
|
|
||||||
|
for (int i = 0; i < term->rows; i++) {
|
||||||
|
int row_no = (new_view + i) % term->grid->num_rows;
|
||||||
|
if (term->grid->rows[row_no] == NULL) {
|
||||||
|
all_initialized = false;
|
||||||
|
new_view--;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while (!all_initialized);
|
||||||
|
|
||||||
|
/* Don't scroll past scrollback history */
|
||||||
|
int end = (term->grid->offset + term->rows - 1) % term->grid->num_rows;
|
||||||
|
if (end >= term->grid->offset) {
|
||||||
|
/* Not wrapped */
|
||||||
|
if (new_view >= term->grid->offset && new_view <= end)
|
||||||
|
new_view = term->grid->offset;
|
||||||
|
} else {
|
||||||
|
if (new_view >= term->grid->offset || new_view <= end)
|
||||||
|
new_view = term->grid->offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Update view */
|
||||||
|
term->grid->view = new_view;
|
||||||
|
if (new_view != old_view)
|
||||||
|
term_damage_view(term);
|
||||||
|
|
||||||
|
/* Selection endpoint is inclusive */
|
||||||
|
assert(end_col > 0);
|
||||||
|
end_col--;
|
||||||
|
|
||||||
|
/* Begin a new selection if the start coords changed */
|
||||||
|
if (start_row != term->search.match.row ||
|
||||||
|
start_col != term->search.match.col)
|
||||||
|
{
|
||||||
|
int selection_row = start_row - term->grid->view;
|
||||||
|
while (selection_row < 0)
|
||||||
|
selection_row += term->grid->num_rows;
|
||||||
|
|
||||||
|
assert(selection_row >= 0 &&
|
||||||
|
selection_row < term->grid->num_rows);
|
||||||
|
selection_start(term, start_col, selection_row);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Update selection endpoint */
|
||||||
|
{
|
||||||
|
int selection_row = end_row - term->grid->view;
|
||||||
|
while (selection_row < 0)
|
||||||
|
selection_row += term->grid->num_rows;
|
||||||
|
|
||||||
|
assert(selection_row >= 0 &&
|
||||||
|
selection_row < term->grid->num_rows);
|
||||||
|
selection_update(term, end_col, selection_row);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
search_find_next(struct terminal *term)
|
||||||
{
|
{
|
||||||
bool backward = term->search.direction == SEARCH_BACKWARD;
|
bool backward = term->search.direction == SEARCH_BACKWARD;
|
||||||
term->search.direction = SEARCH_BACKWARD;
|
term->search.direction = SEARCH_BACKWARD;
|
||||||
|
|
@ -106,14 +194,14 @@ search_update(struct terminal *term)
|
||||||
r < term->grid->num_rows;
|
r < term->grid->num_rows;
|
||||||
backward ? ROW_DEC(start_row) : ROW_INC(start_row), r++)
|
backward ? ROW_DEC(start_row) : ROW_INC(start_row), r++)
|
||||||
{
|
{
|
||||||
const struct row *row = term->grid->rows[start_row];
|
|
||||||
if (row == NULL)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
for (;
|
for (;
|
||||||
backward ? start_col >= 0 : start_col < term->cols;
|
backward ? start_col >= 0 : start_col < term->cols;
|
||||||
backward ? start_col-- : start_col++)
|
backward ? start_col-- : start_col++)
|
||||||
{
|
{
|
||||||
|
const struct row *row = term->grid->rows[start_row];
|
||||||
|
if (row == NULL)
|
||||||
|
continue;
|
||||||
|
|
||||||
if (wcsncasecmp(&row->cells[start_col].wc, term->search.buf, 1) != 0)
|
if (wcsncasecmp(&row->cells[start_col].wc, term->search.buf, 1) != 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
|
@ -129,10 +217,7 @@ search_update(struct terminal *term)
|
||||||
size_t match_len = 0;
|
size_t match_len = 0;
|
||||||
|
|
||||||
for (size_t i = 0; i < term->search.len; i++, match_len++) {
|
for (size_t i = 0; i < term->search.len; i++, match_len++) {
|
||||||
if (wcsncasecmp(&row->cells[end_col].wc, &term->search.buf[i], 1) != 0)
|
if (end_col >= term->cols) {
|
||||||
break;
|
|
||||||
|
|
||||||
if (++end_col >= term->cols) {
|
|
||||||
if (end_row + 1 > grid_row_absolute(term->grid, term->grid->offset + term->rows - 1)) {
|
if (end_row + 1 > grid_row_absolute(term->grid, term->grid->offset + term->rows - 1)) {
|
||||||
/* Don't continue past end of the world */
|
/* Don't continue past end of the world */
|
||||||
break;
|
break;
|
||||||
|
|
@ -142,6 +227,11 @@ search_update(struct terminal *term)
|
||||||
end_col = 0;
|
end_col = 0;
|
||||||
row = term->grid->rows[end_row];
|
row = term->grid->rows[end_row];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (wcsncasecmp(&row->cells[end_col].wc, &term->search.buf[i], 1) != 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
end_col++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (match_len != term->search.len) {
|
if (match_len != term->search.len) {
|
||||||
|
|
@ -153,70 +243,7 @@ search_update(struct terminal *term)
|
||||||
* We matched the entire buffer. Move view to ensure the
|
* We matched the entire buffer. Move view to ensure the
|
||||||
* match is visible, create a selection and return.
|
* match is visible, create a selection and return.
|
||||||
*/
|
*/
|
||||||
|
search_update_selection(term, start_row, start_col, end_row, end_col);
|
||||||
int old_view = term->grid->view;
|
|
||||||
int new_view = start_row;
|
|
||||||
|
|
||||||
/* Prevent scrolling in uninitialized rows */
|
|
||||||
bool all_initialized = false;
|
|
||||||
do {
|
|
||||||
all_initialized = true;
|
|
||||||
|
|
||||||
for (int i = 0; i < term->rows; i++) {
|
|
||||||
int row_no = (new_view + i) % term->grid->num_rows;
|
|
||||||
if (term->grid->rows[row_no] == NULL) {
|
|
||||||
all_initialized = false;
|
|
||||||
new_view--;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} while (!all_initialized);
|
|
||||||
|
|
||||||
/* Don't scroll past scrollback history */
|
|
||||||
int end = (term->grid->offset + term->rows - 1) % term->grid->num_rows;
|
|
||||||
if (end >= term->grid->offset) {
|
|
||||||
/* Not wrapped */
|
|
||||||
if (new_view >= term->grid->offset && new_view <= end)
|
|
||||||
new_view = term->grid->offset;
|
|
||||||
} else {
|
|
||||||
if (new_view >= term->grid->offset || new_view <= end)
|
|
||||||
new_view = term->grid->offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Update view */
|
|
||||||
term->grid->view = new_view;
|
|
||||||
if (new_view != old_view)
|
|
||||||
term_damage_view(term);
|
|
||||||
|
|
||||||
/* Selection endpoint is inclusive */
|
|
||||||
if (--end_col < 0) {
|
|
||||||
end_col = term->cols - 1;
|
|
||||||
start_row--;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Begin a new selection if the start coords changed */
|
|
||||||
if (start_row != term->search.match.row ||
|
|
||||||
start_col != term->search.match.col)
|
|
||||||
{
|
|
||||||
int selection_row = start_row - term->grid->view;
|
|
||||||
while (selection_row < 0)
|
|
||||||
selection_row += term->grid->num_rows;
|
|
||||||
|
|
||||||
assert(selection_row >= 0 &&
|
|
||||||
selection_row < term->grid->num_rows);
|
|
||||||
selection_start(term, start_col, selection_row);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Update selection endpoint */
|
|
||||||
{
|
|
||||||
int selection_row = end_row - term->grid->view;
|
|
||||||
while (selection_row < 0)
|
|
||||||
selection_row += term->grid->num_rows;
|
|
||||||
|
|
||||||
assert(selection_row >= 0 &&
|
|
||||||
selection_row < term->grid->num_rows);
|
|
||||||
selection_update(term, end_col, selection_row);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Update match state */
|
/* Update match state */
|
||||||
term->search.match.row = start_row;
|
term->search.match.row = start_row;
|
||||||
|
|
@ -237,6 +264,77 @@ search_update(struct terminal *term)
|
||||||
#undef ROW_DEC
|
#undef ROW_DEC
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
search_match_to_end_of_word(struct terminal *term, bool spaces_only)
|
||||||
|
{
|
||||||
|
if (term->search.match_len == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
assert(term->search.match.row != -1);
|
||||||
|
assert(term->search.match.col != -1);
|
||||||
|
|
||||||
|
int end_row = term->search.match.row;
|
||||||
|
int end_col = term->search.match.col;
|
||||||
|
size_t len = term->search.match_len;
|
||||||
|
|
||||||
|
/* Calculate end coord - note: assumed to be valid */
|
||||||
|
for (size_t i = 0; i < len; i++) {
|
||||||
|
if (++end_col >= term->cols)
|
||||||
|
end_row = (end_row + 1) % term->grid->num_rows;
|
||||||
|
}
|
||||||
|
|
||||||
|
tll(wchar_t) new_chars = tll_init();
|
||||||
|
|
||||||
|
/* Always append at least one character *if* possible */
|
||||||
|
bool first = true;
|
||||||
|
|
||||||
|
for (size_t r = 0;
|
||||||
|
r < term->grid->num_rows;
|
||||||
|
end_row = (end_row + 1) % term->grid->num_rows, r++)
|
||||||
|
{
|
||||||
|
const struct row *row = term->grid->rows[end_row];
|
||||||
|
if (row == NULL)
|
||||||
|
break;
|
||||||
|
|
||||||
|
bool done = false;
|
||||||
|
for (; end_col < term->cols; end_col++) {
|
||||||
|
wchar_t wc = row->cells[end_col].wc;
|
||||||
|
if (wc == 0 || (!first && !isword(wc, spaces_only))) {
|
||||||
|
done = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
first = false;
|
||||||
|
tll_push_back(new_chars, wc);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (done)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tll_length(new_chars) == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!search_ensure_size(term, term->search.len + tll_length(new_chars)))
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Keep cursor at the end, but don't move it if not */
|
||||||
|
bool move_cursor = term->search.cursor == term->search.len;
|
||||||
|
|
||||||
|
/* Append newly found characters to the search buffer */
|
||||||
|
tll_foreach(new_chars, it)
|
||||||
|
term->search.buf[term->search.len++] = it->item;
|
||||||
|
term->search.buf[term->search.len] = L'\0';
|
||||||
|
|
||||||
|
if (move_cursor)
|
||||||
|
term->search.cursor += tll_length(new_chars);
|
||||||
|
|
||||||
|
tll_free(new_chars);
|
||||||
|
|
||||||
|
search_update_selection(
|
||||||
|
term, term->search.match.row, term->search.match.col, end_row, end_col);
|
||||||
|
}
|
||||||
|
|
||||||
static size_t
|
static size_t
|
||||||
distance_next_word(const struct terminal *term)
|
distance_next_word(const struct terminal *term)
|
||||||
{
|
{
|
||||||
|
|
@ -257,7 +355,6 @@ distance_next_word(const struct terminal *term)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG_INFO("cursor = %zu, iswspace() = %d", cursor, iswspace(term->search.buf[cursor - 1]));
|
|
||||||
assert(cursor == term->search.len || !iswspace(term->search.buf[cursor - 1]));
|
assert(cursor == term->search.len || !iswspace(term->search.buf[cursor - 1]));
|
||||||
|
|
||||||
if (cursor < term->search.len && !iswspace(term->search.buf[cursor]))
|
if (cursor < term->search.len && !iswspace(term->search.buf[cursor]))
|
||||||
|
|
@ -299,7 +396,7 @@ search_input(struct terminal *term, uint32_t key, xkb_keysym_t sym, xkb_mod_mask
|
||||||
|
|
||||||
const xkb_mod_mask_t ctrl = 1 << term->wl->kbd.mod_ctrl;
|
const xkb_mod_mask_t ctrl = 1 << term->wl->kbd.mod_ctrl;
|
||||||
const xkb_mod_mask_t alt = 1 << term->wl->kbd.mod_alt;
|
const xkb_mod_mask_t alt = 1 << term->wl->kbd.mod_alt;
|
||||||
//const xkb_mod_mask_t shift = 1 << term->wl->kbd.mod_shift;
|
const xkb_mod_mask_t shift = 1 << term->wl->kbd.mod_shift;
|
||||||
//const xkb_mod_mask_t meta = 1 << term->wl->kbd.mod_meta;
|
//const xkb_mod_mask_t meta = 1 << term->wl->kbd.mod_meta;
|
||||||
|
|
||||||
enum xkb_compose_status compose_status = xkb_compose_state_get_status(
|
enum xkb_compose_status compose_status = xkb_compose_state_get_status(
|
||||||
|
|
@ -446,6 +543,12 @@ search_input(struct terminal *term, uint32_t key, xkb_keysym_t sym, xkb_mod_mask
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
else if (mods == ctrl && sym == XKB_KEY_w)
|
||||||
|
search_match_to_end_of_word(term, false);
|
||||||
|
|
||||||
|
else if (mods == (ctrl | shift) && sym == XKB_KEY_W)
|
||||||
|
search_match_to_end_of_word(term, true);
|
||||||
|
|
||||||
else {
|
else {
|
||||||
uint8_t buf[64] = {0};
|
uint8_t buf[64] = {0};
|
||||||
int count = 0;
|
int count = 0;
|
||||||
|
|
@ -454,6 +557,8 @@ search_input(struct terminal *term, uint32_t key, xkb_keysym_t sym, xkb_mod_mask
|
||||||
count = xkb_compose_state_get_utf8(
|
count = xkb_compose_state_get_utf8(
|
||||||
term->wl->kbd.xkb_compose_state, (char *)buf, sizeof(buf));
|
term->wl->kbd.xkb_compose_state, (char *)buf, sizeof(buf));
|
||||||
xkb_compose_state_reset(term->wl->kbd.xkb_compose_state);
|
xkb_compose_state_reset(term->wl->kbd.xkb_compose_state);
|
||||||
|
} else if (compose_status == XKB_COMPOSE_CANCELLED) {
|
||||||
|
count = 0;
|
||||||
} else {
|
} else {
|
||||||
count = xkb_state_key_get_utf8(
|
count = xkb_state_key_get_utf8(
|
||||||
term->wl->kbd.xkb_state, key, (char *)buf, sizeof(buf));
|
term->wl->kbd.xkb_state, key, (char *)buf, sizeof(buf));
|
||||||
|
|
@ -468,18 +573,8 @@ search_input(struct terminal *term, uint32_t key, xkb_keysym_t sym, xkb_mod_mask
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (term->search.len + wchars >= term->search.sz) {
|
if (!search_ensure_size(term, term->search.len + wchars))
|
||||||
size_t new_sz = term->search.sz == 0 ? 64 : term->search.sz * 2;
|
return;
|
||||||
wchar_t *new_buf = realloc(term->search.buf, new_sz * sizeof(term->search.buf[0]));
|
|
||||||
|
|
||||||
if (new_buf == NULL) {
|
|
||||||
LOG_ERRNO("failed to resize search buffer");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
term->search.buf = new_buf;
|
|
||||||
term->search.sz = new_sz;
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(term->search.len + wchars < term->search.sz);
|
assert(term->search.len + wchars < term->search.sz);
|
||||||
|
|
||||||
|
|
@ -497,7 +592,7 @@ search_input(struct terminal *term, uint32_t key, xkb_keysym_t sym, xkb_mod_mask
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG_DBG("search: buffer: %S", term->search.buf);
|
LOG_DBG("search: buffer: %S", term->search.buf);
|
||||||
search_update(term);
|
search_find_next(term);
|
||||||
render_refresh(term);
|
render_refresh(term);
|
||||||
render_search_box(term);
|
render_search_box(term);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
22
selection.c
22
selection.c
|
|
@ -15,6 +15,7 @@
|
||||||
|
|
||||||
#include "async.h"
|
#include "async.h"
|
||||||
#include "grid.h"
|
#include "grid.h"
|
||||||
|
#include "misc.h"
|
||||||
#include "render.h"
|
#include "render.h"
|
||||||
#include "vt.h"
|
#include "vt.h"
|
||||||
|
|
||||||
|
|
@ -222,27 +223,6 @@ selection_cancel(struct terminal *term)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
|
||||||
isword(wint_t c, bool spaces_only)
|
|
||||||
{
|
|
||||||
if (spaces_only)
|
|
||||||
return !iswspace(c);
|
|
||||||
|
|
||||||
switch (c) {
|
|
||||||
default: return !iswspace(c);
|
|
||||||
|
|
||||||
case L'{': case L'}':
|
|
||||||
case L'[': case L']':
|
|
||||||
case L'(': case L')':
|
|
||||||
case L'`':
|
|
||||||
case L'\'':
|
|
||||||
case L'"':
|
|
||||||
case L',': case L'.':
|
|
||||||
case L':': case L';':
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
selection_mark_word(struct terminal *term, int col, int row, bool spaces_only,
|
selection_mark_word(struct terminal *term, int col, int row, bool spaces_only,
|
||||||
uint32_t serial)
|
uint32_t serial)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue