selection: extract text: also copy combining characters

This commit is contained in:
Daniel Eklöf 2020-05-01 11:59:09 +02:00
parent 76567e9ef0
commit 623329cf23
No known key found for this signature in database
GPG key ID: 5BBD4992C116573F

View file

@ -46,7 +46,7 @@ selection_on_row_in_view(const struct terminal *term, int row_no)
static void
foreach_selected_normal(
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)
{
const struct coord *start = &_start;
@ -80,7 +80,7 @@ foreach_selected_normal(
c <= (r == end_row ? end_col : term->cols - 1);
c++)
{
cb(term, row, &row->cells[c], data);
cb(term, row, &row->cells[c], c, data);
}
start_col = 0;
@ -90,7 +90,7 @@ foreach_selected_normal(
static void
foreach_selected_block(
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)
{
const struct coord *start = &_start;
@ -112,14 +112,14 @@ foreach_selected_block(
assert(row != NULL);
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
foreach_selected(
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)
{
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 *end = &term->selection.end;
const size_t chars_per_cell
= 1 + ALEN(term->grid->cur_row->comb_chars[0].chars);
switch (term->selection.kind) {
case SELECTION_NONE:
@ -160,7 +162,7 @@ min_bufsize_for_extraction(const struct terminal *term)
}
if (start->row == end->row)
return end->col - start->col + 1;
return (end->col - start->col + 1) * chars_per_cell;
else {
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 + 1) * (end->row - start->row - 1);
cells += end->col + 1 + 1;
return cells;
return cells * chars_per_cell;
}
case SELECTION_BLOCK: {
@ -186,7 +188,7 @@ min_bufsize_for_extraction(const struct terminal *term)
/* Add one extra column on each row, for \n */
int cols = bottom_right.col - top_left.col + 1 + 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 idx;
size_t empty_count;
struct row *last_row;
struct cell *last_cell;
const struct row *last_row;
const struct cell *last_cell;
};
static void
extract_one(struct terminal *term, struct row *row, struct cell *cell,
void *data)
int col, void *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);
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_cell = cell;
}
@ -299,7 +308,7 @@ selection_start(struct terminal *term, int col, int row,
static void
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)) {
/* 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
premark_selected(struct terminal *term, struct row *row, struct cell *cell,
void *data)
int col, void *data)
{
/* Tell unmark to leave this be */
cell->attrs.selected |= 2;
@ -321,7 +330,7 @@ premark_selected(struct terminal *term, struct row *row, struct cell *cell,
static void
mark_selected(struct terminal *term, struct row *row, struct cell *cell,
void *data)
int col, void *data)
{
if (cell->attrs.selected & 1) {
cell->attrs.selected = 1; /* Clear the pre-mark bit */