mirror of
https://codeberg.org/dnkl/foot.git
synced 2026-02-05 04:06:08 -05:00
commit
fcca3d3e55
7 changed files with 338 additions and 125 deletions
|
|
@ -32,6 +32,8 @@
|
|||
font glyphs (https://codeberg.org/dnkl/foot/issues/198)
|
||||
* Trailing comments in `foot.ini` must now be preceded by a space or tab
|
||||
(https://codeberg.org/dnkl/foot/issues/270)
|
||||
* Double- or triple clicking then dragging now extends the selection
|
||||
word- or line-wise (https://codeberg.org/dnkl/foot/issues/267).
|
||||
|
||||
|
||||
### Deprecated
|
||||
|
|
|
|||
11
extract.c
11
extract.c
|
|
@ -69,14 +69,17 @@ extract_finish(struct extraction_context *ctx, char **text, size_t *len)
|
|||
/* Selection of empty cells only */
|
||||
if (!ensure_size(ctx, 1))
|
||||
goto out;
|
||||
ctx->buf[ctx->idx] = L'\0';
|
||||
ctx->buf[ctx->idx++] = L'\0';
|
||||
} else {
|
||||
assert(ctx->idx > 0);
|
||||
assert(ctx->idx < ctx->size);
|
||||
assert(ctx->idx <= ctx->size);
|
||||
if (ctx->buf[ctx->idx - 1] == L'\n')
|
||||
ctx->buf[ctx->idx - 1] = L'\0';
|
||||
else
|
||||
ctx->buf[ctx->idx] = L'\0';
|
||||
else {
|
||||
if (!ensure_size(ctx, 1))
|
||||
goto out;
|
||||
ctx->buf[ctx->idx++] = L'\0';
|
||||
}
|
||||
}
|
||||
|
||||
size_t _len = wcstombs(NULL, ctx->buf, 0);
|
||||
|
|
|
|||
19
input.c
19
input.c
|
|
@ -275,7 +275,8 @@ execute_binding(struct seat *seat, struct terminal *term,
|
|||
case BIND_ACTION_SELECT_BEGIN:
|
||||
if (selection_enabled(term, seat) && cursor_is_on_grid) {
|
||||
selection_start(
|
||||
term, seat->mouse.col, seat->mouse.row, SELECTION_NORMAL);
|
||||
term, seat->mouse.col, seat->mouse.row,
|
||||
SELECTION_NORMAL, SELECTION_SEMANTIC_NONE, false);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
|
@ -283,7 +284,8 @@ execute_binding(struct seat *seat, struct terminal *term,
|
|||
case BIND_ACTION_SELECT_BEGIN_BLOCK:
|
||||
if (selection_enabled(term, seat) && cursor_is_on_grid) {
|
||||
selection_start(
|
||||
term, seat->mouse.col, seat->mouse.row, SELECTION_BLOCK);
|
||||
term, seat->mouse.col, seat->mouse.row,
|
||||
SELECTION_BLOCK, SELECTION_SEMANTIC_NONE, false);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
|
@ -298,23 +300,26 @@ execute_binding(struct seat *seat, struct terminal *term,
|
|||
|
||||
case BIND_ACTION_SELECT_WORD:
|
||||
if (selection_enabled(term, seat) && cursor_is_on_grid) {
|
||||
selection_mark_word(
|
||||
seat, term, seat->mouse.col, seat->mouse.row, false, serial);
|
||||
selection_start(
|
||||
term, seat->mouse.col, seat->mouse.row,
|
||||
SELECTION_NORMAL, SELECTION_SEMANTIC_WORD, false);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
case BIND_ACTION_SELECT_WORD_WS:
|
||||
if (selection_enabled(term, seat) && cursor_is_on_grid) {
|
||||
selection_mark_word(
|
||||
seat, term, seat->mouse.col, seat->mouse.row, true, serial);
|
||||
selection_start(
|
||||
term, seat->mouse.col, seat->mouse.row,
|
||||
SELECTION_NORMAL, SELECTION_SEMANTIC_WORD, true);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
case BIND_ACTION_SELECT_ROW:
|
||||
if (selection_enabled(term, seat) && cursor_is_on_grid) {
|
||||
selection_mark_row(seat, term, seat->mouse.row, serial);
|
||||
selection_start(term, seat->mouse.col, seat->mouse.row,
|
||||
SELECTION_NORMAL, SELECTION_SEMANTIC_ROW, false);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
|
|
|||
3
search.c
3
search.c
|
|
@ -222,7 +222,8 @@ search_update_selection(struct terminal *term,
|
|||
|
||||
assert(selection_row >= 0 &&
|
||||
selection_row < term->grid->num_rows);
|
||||
selection_start(term, start_col, selection_row, SELECTION_NORMAL);
|
||||
selection_start(term, start_col, selection_row,
|
||||
SELECTION_NORMAL, SELECTION_SEMANTIC_NONE, false);
|
||||
}
|
||||
|
||||
/* Update selection endpoint */
|
||||
|
|
|
|||
410
selection.c
410
selection.c
|
|
@ -236,9 +236,157 @@ selection_to_text(const struct terminal *term)
|
|||
return extract_finish(ctx, &text, NULL) ? text : NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
find_word_boundary_left(struct terminal *term, struct coord *pos,
|
||||
bool spaces_only)
|
||||
{
|
||||
const struct row *r = grid_row_in_view(term->grid, pos->row);
|
||||
wchar_t c = r->cells[pos->col].wc;
|
||||
|
||||
while (c == CELL_MULT_COL_SPACER) {
|
||||
assert(pos->col > 0);
|
||||
if (pos->col == 0)
|
||||
return;
|
||||
pos->col--;
|
||||
c = r->cells[pos->col].wc;
|
||||
}
|
||||
|
||||
if (c >= CELL_COMB_CHARS_LO &&
|
||||
c < (CELL_COMB_CHARS_LO + term->composed_count))
|
||||
{
|
||||
c = term->composed[c - CELL_COMB_CHARS_LO].base;
|
||||
}
|
||||
|
||||
bool initial_is_space = c == 0 || iswspace(c);
|
||||
bool initial_is_delim =
|
||||
!initial_is_space && !isword(c, spaces_only, term->conf->word_delimiters);
|
||||
bool initial_is_word =
|
||||
c != 0 && isword(c, spaces_only, term->conf->word_delimiters);
|
||||
|
||||
while (true) {
|
||||
int next_col = pos->col - 1;
|
||||
int next_row = pos->row;
|
||||
|
||||
/* Linewrap */
|
||||
if (next_col < 0) {
|
||||
next_col = term->cols - 1;
|
||||
if (--next_row < 0)
|
||||
break;
|
||||
}
|
||||
|
||||
const struct row *row = grid_row_in_view(term->grid, next_row);
|
||||
|
||||
c = row->cells[next_col].wc;
|
||||
while (c == CELL_MULT_COL_SPACER) {
|
||||
assert(next_col > 0);
|
||||
if (--next_col < 0)
|
||||
return;
|
||||
c = row->cells[next_col].wc;
|
||||
}
|
||||
|
||||
if (c >= CELL_COMB_CHARS_LO &&
|
||||
c < (CELL_COMB_CHARS_LO + term->composed_count))
|
||||
{
|
||||
c = term->composed[c - CELL_COMB_CHARS_LO].base;
|
||||
}
|
||||
|
||||
bool is_space = c == 0 || iswspace(c);
|
||||
bool is_delim =
|
||||
!is_space && !isword(c, spaces_only, term->conf->word_delimiters);
|
||||
bool is_word =
|
||||
c != 0 && isword(c, spaces_only, term->conf->word_delimiters);
|
||||
|
||||
if (initial_is_space && !is_space)
|
||||
break;
|
||||
if (initial_is_delim && !is_delim)
|
||||
break;
|
||||
if (initial_is_word && !is_word)
|
||||
break;
|
||||
|
||||
pos->col = next_col;
|
||||
pos->row = next_row;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
find_word_boundary_right(struct terminal *term, struct coord *pos,
|
||||
bool spaces_only)
|
||||
{
|
||||
const struct row *r = grid_row_in_view(term->grid, pos->row);
|
||||
wchar_t c = r->cells[pos->col].wc;
|
||||
|
||||
while (c == CELL_MULT_COL_SPACER) {
|
||||
assert(pos->col > 0);
|
||||
if (pos->col == 0)
|
||||
return;
|
||||
pos->col--;
|
||||
c = r->cells[pos->col].wc;
|
||||
}
|
||||
|
||||
if (c >= CELL_COMB_CHARS_LO &&
|
||||
c < (CELL_COMB_CHARS_LO + term->composed_count))
|
||||
{
|
||||
c = term->composed[c - CELL_COMB_CHARS_LO].base;
|
||||
}
|
||||
|
||||
bool initial_is_space = c == 0 || iswspace(c);
|
||||
bool initial_is_delim =
|
||||
!initial_is_space && !isword(c, spaces_only, term->conf->word_delimiters);
|
||||
bool initial_is_word =
|
||||
c != 0 && isword(c, spaces_only, term->conf->word_delimiters);
|
||||
|
||||
while (true) {
|
||||
int next_col = pos->col + 1;
|
||||
int next_row = pos->row;
|
||||
|
||||
/* Linewrap */
|
||||
if (next_col >= term->cols) {
|
||||
next_col = 0;
|
||||
if (++next_row >= term->rows)
|
||||
break;
|
||||
}
|
||||
|
||||
const struct row *row = grid_row_in_view(term->grid, next_row);
|
||||
|
||||
c = row->cells[next_col].wc;
|
||||
while (c == CELL_MULT_COL_SPACER) {
|
||||
if (++next_col >= term->cols) {
|
||||
next_col = 0;
|
||||
if (++next_row >= term->rows)
|
||||
return;
|
||||
}
|
||||
c = row->cells[next_col].wc;
|
||||
}
|
||||
|
||||
if (c >= CELL_COMB_CHARS_LO &&
|
||||
c < (CELL_COMB_CHARS_LO + term->composed_count))
|
||||
{
|
||||
c = term->composed[c - CELL_COMB_CHARS_LO].base;
|
||||
}
|
||||
|
||||
bool is_space = c == 0 || iswspace(c);
|
||||
bool is_delim =
|
||||
!is_space && !isword(c, spaces_only, term->conf->word_delimiters);
|
||||
bool is_word =
|
||||
c != 0 && isword(c, spaces_only, term->conf->word_delimiters);
|
||||
|
||||
if (initial_is_space && !is_space)
|
||||
break;
|
||||
if (initial_is_delim && !is_delim)
|
||||
break;
|
||||
if (initial_is_word && !is_word)
|
||||
break;
|
||||
|
||||
pos->col = next_col;
|
||||
pos->row = next_row;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
selection_start(struct terminal *term, int col, int row,
|
||||
enum selection_kind kind)
|
||||
enum selection_kind kind,
|
||||
enum selection_semantic semantic,
|
||||
bool spaces_only)
|
||||
{
|
||||
selection_cancel(term);
|
||||
|
||||
|
|
@ -248,9 +396,43 @@ selection_start(struct terminal *term, int col, int row,
|
|||
row, col);
|
||||
|
||||
term->selection.kind = kind;
|
||||
term->selection.start = (struct coord){col, term->grid->view + row};
|
||||
term->selection.end = (struct coord){-1, -1};
|
||||
term->selection.semantic = semantic;
|
||||
term->selection.ongoing = true;
|
||||
term->selection.spaces_only = spaces_only;
|
||||
|
||||
switch (semantic) {
|
||||
case SELECTION_SEMANTIC_NONE:
|
||||
term->selection.start = (struct coord){col, term->grid->view + row};
|
||||
term->selection.end = (struct coord){-1, -1};
|
||||
|
||||
term->selection.pivot.start = term->selection.start;
|
||||
term->selection.pivot.end = term->selection.end;
|
||||
break;
|
||||
|
||||
case SELECTION_SEMANTIC_WORD: {
|
||||
struct coord start = {col, row}, end = {col, row};
|
||||
find_word_boundary_left(term, &start, spaces_only);
|
||||
find_word_boundary_right(term, &end, spaces_only);
|
||||
|
||||
term->selection.start = (struct coord){
|
||||
start.col, term->grid->view + start.row};
|
||||
|
||||
term->selection.pivot.start = term->selection.start;
|
||||
term->selection.pivot.end = (struct coord){end.col, term->grid->view + end.row};
|
||||
|
||||
selection_update(term, end.col, end.row);
|
||||
break;
|
||||
}
|
||||
|
||||
case SELECTION_SEMANTIC_ROW:
|
||||
term->selection.start = (struct coord){0, term->grid->view + row};
|
||||
term->selection.pivot.start = term->selection.start;
|
||||
term->selection.pivot.end = (struct coord){term->cols - 1, term->grid->view + row};
|
||||
|
||||
selection_update(term, term->cols - 1, row);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Context used while (un)marking selected cells, to be able to
|
||||
|
|
@ -379,61 +561,150 @@ selection_update(struct terminal *term, int col, int row)
|
|||
struct coord new_start = term->selection.start;
|
||||
struct coord new_end = {col, term->grid->view + row};
|
||||
|
||||
size_t start_row_idx = new_start.row & (term->grid->num_rows - 1);
|
||||
size_t end_row_idx = new_end.row & (term->grid->num_rows - 1);
|
||||
const struct row *row_start = term->grid->rows[start_row_idx];
|
||||
const struct row *row_end = term->grid->rows[end_row_idx];
|
||||
|
||||
/* Adjust start point if the selection has changed 'direction' */
|
||||
if (!(new_end.row == new_start.row && new_end.col == new_start.col)) {
|
||||
enum selection_direction new_direction;
|
||||
enum selection_direction new_direction = term->selection.direction;
|
||||
|
||||
if (new_end.row > new_start.row ||
|
||||
(new_end.row == new_start.row && new_end.col > new_start.col))
|
||||
struct coord *pivot_start = &term->selection.pivot.start;
|
||||
struct coord *pivot_end = &term->selection.pivot.end;
|
||||
|
||||
if (new_end.row < pivot_start->row ||
|
||||
(new_end.row == pivot_start->row && new_end.col < pivot_start->col))
|
||||
{
|
||||
/* New end point is after the start point */
|
||||
new_direction = SELECTION_RIGHT;
|
||||
} else {
|
||||
/* The new end point is before the start point */
|
||||
/* New end point is before the start point */
|
||||
new_direction = SELECTION_LEFT;
|
||||
} else {
|
||||
/* The new end point is after the start point */
|
||||
new_direction = SELECTION_RIGHT;
|
||||
}
|
||||
|
||||
if (term->selection.direction != new_direction) {
|
||||
if (term->selection.direction != SELECTION_UNDIR) {
|
||||
if (new_direction == SELECTION_LEFT) {
|
||||
if (term->selection.direction == SELECTION_UNDIR &&
|
||||
pivot_end->row < 0)
|
||||
{
|
||||
/* First, make sure ‘start’ isn’t in the middle of a
|
||||
* multi-column character */
|
||||
while (true) {
|
||||
const struct row *row = term->grid->rows[pivot_start->row & (term->grid->num_rows - 1)];
|
||||
const struct cell *cell = &row->cells[pivot_start->col];
|
||||
|
||||
if (cell->wc != CELL_MULT_COL_SPACER)
|
||||
break;
|
||||
|
||||
/* Multi-column chars don’t cross rows */
|
||||
assert(pivot_start->col > 0);
|
||||
if (pivot_start->col == 0)
|
||||
break;
|
||||
|
||||
pivot_start->col--;
|
||||
}
|
||||
|
||||
/*
|
||||
* Setup pivot end to be one character *before* start
|
||||
* Which one we move, the end or start point, depends
|
||||
* on the initial selection direction.
|
||||
*/
|
||||
|
||||
*pivot_end = *pivot_start;
|
||||
|
||||
if (new_direction == SELECTION_RIGHT) {
|
||||
bool keep_going = true;
|
||||
while (keep_going) {
|
||||
const wchar_t wc = row_start->cells[new_start.col].wc;
|
||||
const struct row *row = term->grid->rows[pivot_end->row & (term->grid->num_rows - 1)];
|
||||
const wchar_t wc = row->cells[pivot_end->col].wc;
|
||||
|
||||
keep_going = wc == CELL_MULT_COL_SPACER;
|
||||
|
||||
new_start.col--;
|
||||
if (new_start.col < 0) {
|
||||
new_start.col = term->cols - 1;
|
||||
new_start.row--;
|
||||
}
|
||||
if (pivot_end->col == 0) {
|
||||
if (pivot_end->row - term->grid->view <= 0)
|
||||
break;
|
||||
pivot_end->col = term->cols - 1;
|
||||
pivot_end->row--;
|
||||
} else
|
||||
pivot_end->col--;
|
||||
}
|
||||
} else {
|
||||
bool keep_going = true;
|
||||
while (keep_going) {
|
||||
const wchar_t wc = new_start.col < term->cols - 1
|
||||
? row_start->cells[new_start.col + 1].wc
|
||||
: 0;
|
||||
const struct row *row = term->grid->rows[pivot_start->row & (term->grid->num_rows - 1)];
|
||||
const wchar_t wc = pivot_start->col < term->cols - 1
|
||||
? row->cells[pivot_start->col + 1].wc : 0;
|
||||
|
||||
keep_going = wc == CELL_MULT_COL_SPACER;
|
||||
|
||||
new_start.col++;
|
||||
if (new_start.col >= term->cols) {
|
||||
new_start.col = 0;
|
||||
new_start.row++;
|
||||
}
|
||||
if (pivot_start->col >= term->cols - 1) {
|
||||
if (pivot_start->row - term->grid->view >= term->rows - 1)
|
||||
break;
|
||||
pivot_start->col = 0;
|
||||
pivot_start->row++;
|
||||
} else
|
||||
pivot_start->col++;
|
||||
}
|
||||
}
|
||||
|
||||
assert(term->grid->rows[pivot_start->row & (term->grid->num_rows - 1)]->
|
||||
cells[pivot_start->col].wc != CELL_MULT_COL_SPACER);
|
||||
assert(term->grid->rows[pivot_end->row & (term->grid->num_rows - 1)]->
|
||||
cells[pivot_end->col].wc != CELL_MULT_COL_SPACER);
|
||||
}
|
||||
|
||||
if (new_direction == SELECTION_LEFT) {
|
||||
assert(pivot_end->row >= 0);
|
||||
new_start = *pivot_end;
|
||||
} else
|
||||
new_start = *pivot_start;
|
||||
|
||||
term->selection.direction = new_direction;
|
||||
}
|
||||
}
|
||||
|
||||
switch (term->selection.semantic) {
|
||||
case SELECTION_SEMANTIC_NONE:
|
||||
break;
|
||||
|
||||
case SELECTION_SEMANTIC_WORD:
|
||||
switch (term->selection.direction) {
|
||||
case SELECTION_LEFT: {
|
||||
struct coord end = {col, row};
|
||||
find_word_boundary_left(term, &end, term->selection.spaces_only);
|
||||
new_end = (struct coord){end.col, term->grid->view + end.row};
|
||||
break;
|
||||
}
|
||||
|
||||
case SELECTION_RIGHT: {
|
||||
struct coord end = {col, row};
|
||||
find_word_boundary_right(term, &end, term->selection.spaces_only);
|
||||
new_end = (struct coord){end.col, term->grid->view + end.row};
|
||||
break;
|
||||
}
|
||||
|
||||
case SELECTION_UNDIR:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case SELECTION_SEMANTIC_ROW:
|
||||
switch (term->selection.direction) {
|
||||
case SELECTION_LEFT:
|
||||
new_end.col = 0;
|
||||
break;
|
||||
|
||||
case SELECTION_RIGHT:
|
||||
new_end.col = term->cols - 1;
|
||||
break;
|
||||
|
||||
case SELECTION_UNDIR:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
size_t start_row_idx = new_start.row & (term->grid->num_rows - 1);
|
||||
size_t end_row_idx = new_end.row & (term->grid->num_rows - 1);
|
||||
|
||||
const struct row *row_start = term->grid->rows[start_row_idx];
|
||||
const struct row *row_end = term->grid->rows[end_row_idx];
|
||||
|
||||
/* If an end point is in the middle of a multi-column character,
|
||||
* expand the selection to cover the entire character */
|
||||
if (new_start.row < new_end.row ||
|
||||
|
|
@ -677,6 +948,8 @@ selection_cancel(struct terminal *term)
|
|||
term->selection.kind = SELECTION_NONE;
|
||||
term->selection.start = (struct coord){-1, -1};
|
||||
term->selection.end = (struct coord){-1, -1};
|
||||
term->selection.pivot.start = (struct coord){-1, -1};
|
||||
term->selection.pivot.end = (struct coord){-1, -1};
|
||||
term->selection.direction = SELECTION_UNDIR;
|
||||
term->selection.ongoing = false;
|
||||
}
|
||||
|
|
@ -733,81 +1006,6 @@ selection_primary_unset(struct seat *seat)
|
|||
primary->text = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
selection_mark_word(struct seat *seat, struct terminal *term, int col, int row,
|
||||
bool spaces_only, uint32_t serial)
|
||||
{
|
||||
selection_cancel(term);
|
||||
|
||||
struct coord start = {col, row};
|
||||
struct coord end = {col, row};
|
||||
|
||||
const struct row *r = grid_row_in_view(term->grid, start.row);
|
||||
wchar_t c = r->cells[start.col].wc;
|
||||
|
||||
if (!(c == 0 || !isword(c, spaces_only, term->conf->word_delimiters))) {
|
||||
while (true) {
|
||||
int next_col = start.col - 1;
|
||||
int next_row = start.row;
|
||||
|
||||
/* Linewrap */
|
||||
if (next_col < 0) {
|
||||
next_col = term->cols - 1;
|
||||
if (--next_row < 0)
|
||||
break;
|
||||
}
|
||||
|
||||
const struct row *row = grid_row_in_view(term->grid, next_row);
|
||||
|
||||
c = row->cells[next_col].wc;
|
||||
if (c == 0 || !isword(c, spaces_only, term->conf->word_delimiters))
|
||||
break;
|
||||
|
||||
start.col = next_col;
|
||||
start.row = next_row;
|
||||
}
|
||||
}
|
||||
|
||||
r = grid_row_in_view(term->grid, end.row);
|
||||
c = r->cells[end.col].wc;
|
||||
|
||||
if (!(c == 0 || !isword(c, spaces_only, term->conf->word_delimiters))) {
|
||||
while (true) {
|
||||
int next_col = end.col + 1;
|
||||
int next_row = end.row;
|
||||
|
||||
/* Linewrap */
|
||||
if (next_col >= term->cols) {
|
||||
next_col = 0;
|
||||
if (++next_row >= term->rows)
|
||||
break;
|
||||
}
|
||||
|
||||
const struct row *row = grid_row_in_view(term->grid, next_row);
|
||||
|
||||
c = row->cells[next_col].wc;
|
||||
if (c == '\0' || !isword(c, spaces_only, term->conf->word_delimiters))
|
||||
break;
|
||||
|
||||
end.col = next_col;
|
||||
end.row = next_row;
|
||||
}
|
||||
}
|
||||
|
||||
selection_start(term, start.col, start.row, SELECTION_NORMAL);
|
||||
selection_update(term, end.col, end.row);
|
||||
selection_finalize(seat, term, serial);
|
||||
}
|
||||
|
||||
void
|
||||
selection_mark_row(
|
||||
struct seat *seat, struct terminal *term, int row, uint32_t serial)
|
||||
{
|
||||
selection_start(term, 0, row, SELECTION_NORMAL);
|
||||
selection_update(term, term->cols - 1, row);
|
||||
selection_finalize(seat, term, serial);
|
||||
}
|
||||
|
||||
static bool
|
||||
fdm_scroll_timer(struct fdm *fdm, int fd, int events, void *data)
|
||||
{
|
||||
|
|
|
|||
10
selection.h
10
selection.h
|
|
@ -10,7 +10,9 @@ extern const struct zwp_primary_selection_device_v1_listener primary_selection_d
|
|||
|
||||
bool selection_enabled(const struct terminal *term, struct seat *seat);
|
||||
void selection_start(
|
||||
struct terminal *term, int col, int row, enum selection_kind kind);
|
||||
struct terminal *term, int col, int row,
|
||||
enum selection_kind kind, enum selection_semantic semantic,
|
||||
bool spaces_only);
|
||||
void selection_update(struct terminal *term, int col, int row);
|
||||
void selection_finalize(
|
||||
struct seat *seat, struct terminal *term, uint32_t serial);
|
||||
|
|
@ -24,12 +26,6 @@ bool selection_on_rows(const struct terminal *term, int start, int end);
|
|||
void selection_view_up(struct terminal *term, int new_view);
|
||||
void selection_view_down(struct terminal *term, int new_view);
|
||||
|
||||
void selection_mark_word(
|
||||
struct seat *seat, struct terminal *term, int col, int row,
|
||||
bool spaces_only, uint32_t serial);
|
||||
void selection_mark_row(
|
||||
struct seat *seat, struct terminal *term, int row, uint32_t serial);
|
||||
|
||||
void selection_clipboard_unset(struct seat *seat);
|
||||
void selection_primary_unset(struct seat *seat);
|
||||
|
||||
|
|
|
|||
|
|
@ -181,6 +181,7 @@ enum mouse_reporting {
|
|||
enum cursor_style { CURSOR_BLOCK, CURSOR_UNDERLINE, CURSOR_BAR };
|
||||
|
||||
enum selection_kind { SELECTION_NONE, SELECTION_NORMAL, SELECTION_BLOCK };
|
||||
enum selection_semantic { SELECTION_SEMANTIC_NONE, SELECTION_SEMANTIC_WORD, SELECTION_SEMANTIC_ROW};
|
||||
enum selection_direction {SELECTION_UNDIR, SELECTION_LEFT, SELECTION_RIGHT};
|
||||
enum selection_scroll_direction {SELECTION_SCROLL_NOT, SELECTION_SCROLL_UP, SELECTION_SCROLL_DOWN};
|
||||
|
||||
|
|
@ -359,10 +360,17 @@ struct terminal {
|
|||
|
||||
struct {
|
||||
enum selection_kind kind;
|
||||
enum selection_semantic semantic;
|
||||
enum selection_direction direction;
|
||||
struct coord start;
|
||||
struct coord end;
|
||||
bool ongoing;
|
||||
bool spaces_only; /* SELECTION_SEMANTIC_WORD */
|
||||
|
||||
struct {
|
||||
struct coord start;
|
||||
struct coord end;
|
||||
} pivot;
|
||||
|
||||
struct {
|
||||
int fd;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue