fcft: adapt to API changes in fcft-3.x

Fcft no longer uses wchar_t, but plain uint32_t to represent
codepoints.

Since we do a fair amount of string operations in foot, it still makes
sense to use something that actually _is_ a string (or character),
rather than an array of uint32_t.

For this reason, we switch out all wchar_t usage in foot to
char32_t. We also verify, at compile-time, that char32_t used
UTF-32 (which is what fcft expects).

Unfortunately, there are no string functions for char32_t. To avoid
having to re-implement all wcs*() functions, we add a small wrapper
layer of c32*() functions.

These wrapper functions take char32_t arguments, but then simply call
the corresponding wcs*() function.

For this to work, wcs*() must _also_ be UTF-32 compatible. We can
check for the presence of the  __STDC_ISO_10646__ macro. If set,
wchar_t is at least 4 bytes and its internal representation is UTF-32.

FreeBSD does *not* define this macro, because its internal wchar_t
representation depends on the current locale. It _does_ use UTF-32
_if_ the current locale is UTF-8.

Since foot enforces UTF-8, we simply need to check if __FreeBSD__ is
defined.

Other fcft API changes:

* fcft_glyph_rasterize() -> fcft_codepoint_rasterize()
* font.space_advance has been removed
* ‘tags’ have been removed from fcft_grapheme_rasterize()
* ‘fcft_log_init()’ removed
* ‘fcft_init()’ and ‘fcft_fini()’ must be explicitly called
This commit is contained in:
Daniel Eklöf 2021-08-21 14:50:42 +02:00
parent 2be8c39044
commit e0227266ca
No known key found for this signature in database
GPG key ID: 5BBD4992C116573F
32 changed files with 962 additions and 385 deletions

View file

@ -1,12 +1,13 @@
#include "extract.h"
#include <stdlib.h>
#include <string.h>
#define LOG_MODULE "extract"
#define LOG_ENABLE_DBG 1
#include "log.h"
#include "char32.h"
struct extraction_context {
wchar_t *buf;
char32_t *buf;
size_t size;
size_t idx;
size_t tab_spaces_left;
@ -40,7 +41,7 @@ ensure_size(struct extraction_context *ctx, size_t additional_chars)
{
while (ctx->size < ctx->idx + additional_chars) {
size_t new_size = ctx->size == 0 ? 512 : ctx->size * 2;
wchar_t *new_buf = realloc(ctx->buf, new_size * sizeof(wchar_t));
char32_t *new_buf = realloc(ctx->buf, new_size * sizeof(new_buf[0]));
if (new_buf == NULL)
return false;
@ -54,7 +55,7 @@ ensure_size(struct extraction_context *ctx, size_t additional_chars)
}
bool
extract_finish_wide(struct extraction_context *ctx, wchar_t **text, size_t *len)
extract_finish_wide(struct extraction_context *ctx, char32_t **text, size_t *len)
{
if (text == NULL)
return false;
@ -72,41 +73,41 @@ extract_finish_wide(struct extraction_context *ctx, wchar_t **text, size_t *len)
goto err;
for (size_t i = 0; i < ctx->newline_count; i++)
ctx->buf[ctx->idx++] = L'\n';
ctx->buf[ctx->idx++] = U'\n';
for (size_t i = 0; i < ctx->empty_count; i++)
ctx->buf[ctx->idx++] = L' ';
ctx->buf[ctx->idx++] = U' ';
}
if (ctx->idx == 0) {
/* Selection of empty cells only */
if (!ensure_size(ctx, 1))
goto err;
ctx->buf[ctx->idx++] = L'\0';
ctx->buf[ctx->idx++] = U'\0';
} else {
xassert(ctx->idx > 0);
xassert(ctx->idx <= ctx->size);
switch (ctx->selection_kind) {
default:
if (ctx->buf[ctx->idx - 1] == L'\n')
ctx->buf[ctx->idx - 1] = L'\0';
if (ctx->buf[ctx->idx - 1] == U'\n')
ctx->buf[ctx->idx - 1] = U'\0';
break;
case SELECTION_LINE_WISE:
if (ctx->buf[ctx->idx - 1] != L'\n') {
if (ctx->buf[ctx->idx - 1] != U'\n') {
if (!ensure_size(ctx, 1))
goto err;
ctx->buf[ctx->idx++] = L'\n';
ctx->buf[ctx->idx++] = U'\n';
}
break;
}
if (ctx->buf[ctx->idx - 1] != L'\0') {
if (ctx->buf[ctx->idx - 1] != U'\0') {
if (!ensure_size(ctx, 1))
goto err;
ctx->buf[ctx->idx++] = L'\0';
ctx->buf[ctx->idx++] = U'\0';
}
}
@ -130,29 +131,20 @@ extract_finish(struct extraction_context *ctx, char **text, size_t *len)
if (len != NULL)
*len = 0;
wchar_t *wtext;
char32_t *wtext;
if (!extract_finish_wide(ctx, &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");
*text = ac32tombs(wtext);
if (*text == NULL) {
LOG_ERR("failed to convert selection to UTF-8");
goto out;
}
*text = malloc(_len + 1);
if (unlikely(text == NULL)) {
LOG_ERRNO("malloc() failed");
goto out;
}
wcstombs(*text, wtext, _len + 1);
if (len != NULL)
*len = _len;
*len = strlen(*text);
ret = true;
out:
@ -188,7 +180,7 @@ extract_one(const struct terminal *term, const struct row *row,
if (!ensure_size(ctx, ctx->empty_count))
goto err;
for (size_t i = 0; i < ctx->empty_count; i++)
ctx->buf[ctx->idx++] = L' ';
ctx->buf[ctx->idx++] = U' ';
}
ctx->empty_count = 0;
}
@ -197,13 +189,13 @@ extract_one(const struct terminal *term, const struct row *row,
if (!ensure_size(ctx, 1))
goto err;
ctx->buf[ctx->idx++] = L'\n';
ctx->buf[ctx->idx++] = U'\n';
if (!ctx->strip_trailing_empty) {
if (!ensure_size(ctx, ctx->empty_count))
goto err;
for (size_t i = 0; i < ctx->empty_count; i++)
ctx->buf[ctx->idx++] = L' ';
ctx->buf[ctx->idx++] = U' ';
}
ctx->empty_count = 0;
}
@ -211,7 +203,7 @@ extract_one(const struct terminal *term, const struct row *row,
ctx->tab_spaces_left = 0;
}
if (cell->wc == L' ' && ctx->tab_spaces_left > 0) {
if (cell->wc == U' ' && ctx->tab_spaces_left > 0) {
ctx->tab_spaces_left--;
return true;
}
@ -230,10 +222,10 @@ extract_one(const struct terminal *term, const struct row *row,
goto err;
for (size_t i = 0; i < ctx->newline_count; i++)
ctx->buf[ctx->idx++] = L'\n';
ctx->buf[ctx->idx++] = U'\n';
for (size_t i = 0; i < ctx->empty_count; i++)
ctx->buf[ctx->idx++] = L' ';
ctx->buf[ctx->idx++] = U' ';
ctx->newline_count = 0;
ctx->empty_count = 0;
@ -255,7 +247,7 @@ extract_one(const struct terminal *term, const struct row *row,
goto err;
ctx->buf[ctx->idx++] = cell->wc;
if (cell->wc == L'\t') {
if (cell->wc == U'\t') {
int next_tab_stop = term->cols - 1;
tll_foreach(term->tab_stops, it) {
if (it->item > col) {