diff --git a/extract.c b/extract.c index ac5f3897..dd72ea92 100644 --- a/extract.c +++ b/extract.c @@ -51,10 +51,9 @@ ensure_size(struct extraction_context *ctx, size_t additional_chars) } 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) return false; @@ -63,12 +62,24 @@ extract_finish(struct extraction_context *ctx, char **text, size_t *len) *len = 0; 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) { /* Selection of empty cells only */ if (!ensure_size(ctx, 1)) - goto out; + goto err; ctx->buf[ctx->idx++] = L'\0'; } else { 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'; else { if (!ensure_size(ctx, 1)) - goto out; + goto err; 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) { LOG_ERRNO("failed to convert selection to UTF-8"); goto out; @@ -94,7 +132,7 @@ extract_finish(struct extraction_context *ctx, char **text, size_t *len) goto out; } - wcstombs(*text, ctx->buf, _len + 1); + wcstombs(*text, wtext, _len + 1); if (len != NULL) *len = _len; @@ -102,8 +140,7 @@ extract_finish(struct extraction_context *ctx, char **text, size_t *len) ret = true; out: - free(ctx->buf); - free(ctx); + free(wtext); return ret; } diff --git a/extract.h b/extract.h index 0b3693d2..879461cf 100644 --- a/extract.h +++ b/extract.h @@ -2,6 +2,7 @@ #include #include +#include #include "terminal.h" @@ -14,4 +15,8 @@ bool extract_one( int col, void *context); 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); diff --git a/selection.c b/selection.c index 7b0d93d7..7316dfc3 100644 --- a/selection.c +++ b/selection.c @@ -224,7 +224,7 @@ selection_to_text(const struct terminal *term) &extract_one_const_wrapper, ctx); char *text; - return extract_finish(ctx, &text, NULL) ? text : NULL; + return extract_finish(ctx, true, &text, NULL) ? text : NULL; } void diff --git a/terminal.c b/terminal.c index 4a39b659..c2bcf86f 100644 --- a/terminal.c +++ b/terminal.c @@ -2917,7 +2917,7 @@ rows_to_text(const struct terminal *term, int start, int end, } out: - return extract_finish(ctx, text, len); + return extract_finish(ctx, true, text, len); } bool