mirror of
https://codeberg.org/dnkl/foot.git
synced 2026-04-18 06:46:23 -04:00
selection: extract text: also copy combining characters
This commit is contained in:
parent
76567e9ef0
commit
623329cf23
1 changed files with 23 additions and 14 deletions
37
selection.c
37
selection.c
|
|
@ -46,7 +46,7 @@ selection_on_row_in_view(const struct terminal *term, int row_no)
|
||||||
static void
|
static void
|
||||||
foreach_selected_normal(
|
foreach_selected_normal(
|
||||||
struct terminal *term, struct coord _start, struct coord _end,
|
struct terminal *term, struct coord _start, struct coord _end,
|
||||||
void (*cb)(struct terminal *term, struct row *row, struct cell *cell, void *data),
|
void (*cb)(struct terminal *term, struct row *row, struct cell *cell, int col, void *data),
|
||||||
void *data)
|
void *data)
|
||||||
{
|
{
|
||||||
const struct coord *start = &_start;
|
const struct coord *start = &_start;
|
||||||
|
|
@ -80,7 +80,7 @@ foreach_selected_normal(
|
||||||
c <= (r == end_row ? end_col : term->cols - 1);
|
c <= (r == end_row ? end_col : term->cols - 1);
|
||||||
c++)
|
c++)
|
||||||
{
|
{
|
||||||
cb(term, row, &row->cells[c], data);
|
cb(term, row, &row->cells[c], c, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
start_col = 0;
|
start_col = 0;
|
||||||
|
|
@ -90,7 +90,7 @@ foreach_selected_normal(
|
||||||
static void
|
static void
|
||||||
foreach_selected_block(
|
foreach_selected_block(
|
||||||
struct terminal *term, struct coord _start, struct coord _end,
|
struct terminal *term, struct coord _start, struct coord _end,
|
||||||
void (*cb)(struct terminal *term, struct row *row, struct cell *cell, void *data),
|
void (*cb)(struct terminal *term, struct row *row, struct cell *cell, int col, void *data),
|
||||||
void *data)
|
void *data)
|
||||||
{
|
{
|
||||||
const struct coord *start = &_start;
|
const struct coord *start = &_start;
|
||||||
|
|
@ -112,14 +112,14 @@ foreach_selected_block(
|
||||||
assert(row != NULL);
|
assert(row != NULL);
|
||||||
|
|
||||||
for (int c = top_left.col; c <= bottom_right.col; c++)
|
for (int c = top_left.col; c <= bottom_right.col; c++)
|
||||||
cb(term, row, &row->cells[c], data);
|
cb(term, row, &row->cells[c], c, data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
foreach_selected(
|
foreach_selected(
|
||||||
struct terminal *term, struct coord start, struct coord end,
|
struct terminal *term, struct coord start, struct coord end,
|
||||||
void (*cb)(struct terminal *term, struct row *row, struct cell *cell, void *data),
|
void (*cb)(struct terminal *term, struct row *row, struct cell *cell, int col, void *data),
|
||||||
void *data)
|
void *data)
|
||||||
{
|
{
|
||||||
switch (term->selection.kind) {
|
switch (term->selection.kind) {
|
||||||
|
|
@ -142,6 +142,8 @@ min_bufsize_for_extraction(const struct terminal *term)
|
||||||
{
|
{
|
||||||
const struct coord *start = &term->selection.start;
|
const struct coord *start = &term->selection.start;
|
||||||
const struct coord *end = &term->selection.end;
|
const struct coord *end = &term->selection.end;
|
||||||
|
const size_t chars_per_cell
|
||||||
|
= 1 + ALEN(term->grid->cur_row->comb_chars[0].chars);
|
||||||
|
|
||||||
switch (term->selection.kind) {
|
switch (term->selection.kind) {
|
||||||
case SELECTION_NONE:
|
case SELECTION_NONE:
|
||||||
|
|
@ -160,7 +162,7 @@ min_bufsize_for_extraction(const struct terminal *term)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (start->row == end->row)
|
if (start->row == end->row)
|
||||||
return end->col - start->col + 1;
|
return (end->col - start->col + 1) * chars_per_cell;
|
||||||
else {
|
else {
|
||||||
size_t cells = 0;
|
size_t cells = 0;
|
||||||
|
|
||||||
|
|
@ -169,7 +171,7 @@ min_bufsize_for_extraction(const struct terminal *term)
|
||||||
cells += term->cols - start->col + 1;
|
cells += term->cols - start->col + 1;
|
||||||
cells += (term->cols + 1) * (end->row - start->row - 1);
|
cells += (term->cols + 1) * (end->row - start->row - 1);
|
||||||
cells += end->col + 1 + 1;
|
cells += end->col + 1 + 1;
|
||||||
return cells;
|
return cells * chars_per_cell;
|
||||||
}
|
}
|
||||||
|
|
||||||
case SELECTION_BLOCK: {
|
case SELECTION_BLOCK: {
|
||||||
|
|
@ -186,7 +188,7 @@ min_bufsize_for_extraction(const struct terminal *term)
|
||||||
/* Add one extra column on each row, for \n */
|
/* Add one extra column on each row, for \n */
|
||||||
int cols = bottom_right.col - top_left.col + 1 + 1;
|
int cols = bottom_right.col - top_left.col + 1 + 1;
|
||||||
int rows = bottom_right.row - top_left.row + 1;
|
int rows = bottom_right.row - top_left.row + 1;
|
||||||
return rows * cols;
|
return rows * cols * chars_per_cell;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -199,13 +201,13 @@ struct extract {
|
||||||
size_t size;
|
size_t size;
|
||||||
size_t idx;
|
size_t idx;
|
||||||
size_t empty_count;
|
size_t empty_count;
|
||||||
struct row *last_row;
|
const struct row *last_row;
|
||||||
struct cell *last_cell;
|
const struct cell *last_cell;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
extract_one(struct terminal *term, struct row *row, struct cell *cell,
|
extract_one(struct terminal *term, struct row *row, struct cell *cell,
|
||||||
void *data)
|
int col, void *data)
|
||||||
{
|
{
|
||||||
struct extract *ctx = data;
|
struct extract *ctx = data;
|
||||||
|
|
||||||
|
|
@ -235,6 +237,13 @@ extract_one(struct terminal *term, struct row *row, struct cell *cell,
|
||||||
assert(ctx->idx + 1 <= ctx->size);
|
assert(ctx->idx + 1 <= ctx->size);
|
||||||
ctx->buf[ctx->idx++] = cell->wc;
|
ctx->buf[ctx->idx++] = cell->wc;
|
||||||
|
|
||||||
|
const struct combining_chars *comb_chars = &row->comb_chars[col];
|
||||||
|
|
||||||
|
assert(cell->wc != 0);
|
||||||
|
assert(ctx->idx + comb_chars->count <= ctx->size);
|
||||||
|
for (size_t i = 0; i < comb_chars->count; i++)
|
||||||
|
ctx->buf[ctx->idx++] = comb_chars->chars[i];
|
||||||
|
|
||||||
ctx->last_row = row;
|
ctx->last_row = row;
|
||||||
ctx->last_cell = cell;
|
ctx->last_cell = cell;
|
||||||
}
|
}
|
||||||
|
|
@ -299,7 +308,7 @@ selection_start(struct terminal *term, int col, int row,
|
||||||
|
|
||||||
static void
|
static void
|
||||||
unmark_selected(struct terminal *term, struct row *row, struct cell *cell,
|
unmark_selected(struct terminal *term, struct row *row, struct cell *cell,
|
||||||
void *data)
|
int col, void *data)
|
||||||
{
|
{
|
||||||
if (cell->attrs.selected == 0 || (cell->attrs.selected & 2)) {
|
if (cell->attrs.selected == 0 || (cell->attrs.selected & 2)) {
|
||||||
/* Ignore if already deselected, or if premarked for updated selection */
|
/* Ignore if already deselected, or if premarked for updated selection */
|
||||||
|
|
@ -313,7 +322,7 @@ unmark_selected(struct terminal *term, struct row *row, struct cell *cell,
|
||||||
|
|
||||||
static void
|
static void
|
||||||
premark_selected(struct terminal *term, struct row *row, struct cell *cell,
|
premark_selected(struct terminal *term, struct row *row, struct cell *cell,
|
||||||
void *data)
|
int col, void *data)
|
||||||
{
|
{
|
||||||
/* Tell unmark to leave this be */
|
/* Tell unmark to leave this be */
|
||||||
cell->attrs.selected |= 2;
|
cell->attrs.selected |= 2;
|
||||||
|
|
@ -321,7 +330,7 @@ premark_selected(struct terminal *term, struct row *row, struct cell *cell,
|
||||||
|
|
||||||
static void
|
static void
|
||||||
mark_selected(struct terminal *term, struct row *row, struct cell *cell,
|
mark_selected(struct terminal *term, struct row *row, struct cell *cell,
|
||||||
void *data)
|
int col, void *data)
|
||||||
{
|
{
|
||||||
if (cell->attrs.selected & 1) {
|
if (cell->attrs.selected & 1) {
|
||||||
cell->attrs.selected = 1; /* Clear the pre-mark bit */
|
cell->attrs.selected = 1; /* Clear the pre-mark bit */
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue