extract: add extract_finish_wide(), and optionally skip stripping trailing empty cells

extract_finish() returns the extracted text in UTF-8, while
extract_finish_wide() returns the extracted text in Unicode.

This patch also adds a new argument to extract_finish{,_wide},
that when set to true, skips stripping trailing empty cells.
This commit is contained in:
Daniel Eklöf 2021-03-28 21:04:48 +02:00
parent eab874eb06
commit 1bc9fd5fe1
No known key found for this signature in database
GPG key ID: 5BBD4992C116573F
4 changed files with 55 additions and 13 deletions

View file

@ -51,10 +51,9 @@ ensure_size(struct extraction_context *ctx, size_t additional_chars)
} }
bool bool
extract_finish(struct extraction_context *ctx, char **text, size_t *len) extract_finish_wide(struct extraction_context *ctx, bool strip_trailing_empty,
wchar_t **text, size_t *len)
{ {
bool ret = false;
if (text == NULL) if (text == NULL)
return false; return false;
@ -63,12 +62,24 @@ extract_finish(struct extraction_context *ctx, char **text, size_t *len)
*len = 0; *len = 0;
if (ctx->failed) if (ctx->failed)
goto out; goto err;
if (!strip_trailing_empty) {
/* Insert pending newlines, and replace empty cells with spaces */
if (!ensure_size(ctx, ctx->newline_count + ctx->empty_count))
goto err;
for (size_t i = 0; i < ctx->newline_count; i++)
ctx->buf[ctx->idx++] = L'\n';
for (size_t i = 0; i < ctx->empty_count; i++)
ctx->buf[ctx->idx++] = L' ';
}
if (ctx->idx == 0) { if (ctx->idx == 0) {
/* Selection of empty cells only */ /* Selection of empty cells only */
if (!ensure_size(ctx, 1)) if (!ensure_size(ctx, 1))
goto out; goto err;
ctx->buf[ctx->idx++] = L'\0'; ctx->buf[ctx->idx++] = L'\0';
} else { } else {
xassert(ctx->idx > 0); xassert(ctx->idx > 0);
@ -77,12 +88,39 @@ extract_finish(struct extraction_context *ctx, char **text, size_t *len)
ctx->buf[ctx->idx - 1] = L'\0'; ctx->buf[ctx->idx - 1] = L'\0';
else { else {
if (!ensure_size(ctx, 1)) if (!ensure_size(ctx, 1))
goto out; goto err;
ctx->buf[ctx->idx++] = L'\0'; ctx->buf[ctx->idx++] = L'\0';
} }
} }
size_t _len = wcstombs(NULL, ctx->buf, 0); *text = ctx->buf;
if (len != NULL)
*len = ctx->idx - 1;
free(ctx);
return true;
err:
free(ctx->buf);
free(ctx);
return false;
}
bool
extract_finish(struct extraction_context *ctx, bool strip_trailing_empty,
char **text, size_t *len)
{
if (text == NULL)
return false;
if (len != NULL)
*len = 0;
wchar_t *wtext;
if (!extract_finish_wide(ctx, strip_trailing_empty, &wtext, NULL))
return false;
bool ret = false;
size_t _len = wcstombs(NULL, wtext, 0);
if (_len == (size_t)-1) { if (_len == (size_t)-1) {
LOG_ERRNO("failed to convert selection to UTF-8"); LOG_ERRNO("failed to convert selection to UTF-8");
goto out; goto out;
@ -94,7 +132,7 @@ extract_finish(struct extraction_context *ctx, char **text, size_t *len)
goto out; goto out;
} }
wcstombs(*text, ctx->buf, _len + 1); wcstombs(*text, wtext, _len + 1);
if (len != NULL) if (len != NULL)
*len = _len; *len = _len;
@ -102,8 +140,7 @@ extract_finish(struct extraction_context *ctx, char **text, size_t *len)
ret = true; ret = true;
out: out:
free(ctx->buf); free(wtext);
free(ctx);
return ret; return ret;
} }

View file

@ -2,6 +2,7 @@
#include <stddef.h> #include <stddef.h>
#include <stdbool.h> #include <stdbool.h>
#include <wchar.h>
#include "terminal.h" #include "terminal.h"
@ -14,4 +15,8 @@ bool extract_one(
int col, void *context); int col, void *context);
bool extract_finish( bool extract_finish(
struct extraction_context *context, char **text, size_t *len); struct extraction_context *context, bool strip_trailing_empty,
char **text, size_t *len);
bool extract_finish_wide(
struct extraction_context *context, bool strip_trailing_empty,
wchar_t **text, size_t *len);

View file

@ -224,7 +224,7 @@ selection_to_text(const struct terminal *term)
&extract_one_const_wrapper, ctx); &extract_one_const_wrapper, ctx);
char *text; char *text;
return extract_finish(ctx, &text, NULL) ? text : NULL; return extract_finish(ctx, true, &text, NULL) ? text : NULL;
} }
void void

View file

@ -2917,7 +2917,7 @@ rows_to_text(const struct terminal *term, int start, int end,
} }
out: out:
return extract_finish(ctx, text, len); return extract_finish(ctx, true, text, len);
} }
bool bool