1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
|
#ifndef WSAP_VTCORE_TEXT_RUN_H
#define WSAP_VTCORE_TEXT_RUN_H
#include "cell.h"
#include "unicode/unicode.h"
#include "unicode/grapheme.h"
#define UTF8_LEAD_MIN 0xc2
#define UTF8_LEAD_MAX 0xf4
#define UTF8_LEAD3_TAG 0xE0
#define UTF8_LEAD3_MASK 0xF0
#define WSAP_VTCORE_WIDTH_SLOTS 4
struct width_cache {
uint32_t lo[WSAP_VTCORE_WIDTH_SLOTS];
uint32_t span[WSAP_VTCORE_WIDTH_SLOTS];
uint8_t klass;
uint8_t next;
};
/* wsap_vtcore_new() builds the shared tables before any terminal can use them. */
bool wsap_vtcore_tables_ready(void);
void wsap_vtcore_text_tables_init(void);
int wsap_vtcore_text_class(uint32_t cp);
struct text_run_result {
int bytes;
int cols;
uint32_t last;
};
struct text_run_result wsap_vtcore_text_run(struct cell *restrict row, const char *restrict buf,
int len, int max_cols, uint32_t fg, uint32_t bg,
uint32_t flags, uint32_t last, struct width_cache *restrict wc);
struct text_run_bytes {
int bytes; /* input used */
int cols;
int out; /* bytes written */
int chars;
uint32_t last;
bool wide, narrow; /* narrow: every character was one ASCII byte */
};
/* wsap_vtcore_text_run() with the same rules, that writes the text in the history
* format instead of cells: raw UTF-8, a wide character after 0xF5. dst has
* room for 4 bytes per column. */
struct text_run_bytes wsap_vtcore_text_run_bytes(uint8_t *restrict dst, const char *restrict buf, int len,
int max_cols, uint32_t last, struct width_cache *restrict wc);
static inline bool joins_cluster(uint32_t cp, int klass)
{
if (cp < 0x0300)
return false;
if (klass == 0 || wsap_vtcore_grapheme_emoji_modifier(cp))
return true;
return klass == 1 && wsap_vtcore_unicode_spacing_mark(cp);
}
static inline bool can_extend_cluster(uint32_t last_char, uint32_t cp, int klass)
{
if (klass == 0) return true;
if (last_char == 0x200D || wsap_vtcore_grapheme_is_handle(last_char)) return true;
if (cp - 0x1F1E6u <= 0x19u && wsap_vtcore_grapheme_regional_indicator(cp))
return true;
return joins_cluster(cp, klass);
}
static inline bool cluster_contextual(uint32_t cp)
{
return wsap_vtcore_unicode_spacing_mark(cp) || wsap_vtcore_grapheme_emoji_modifier(cp) ||
(cp - 0x1F1E6u <= 0x19u && wsap_vtcore_grapheme_regional_indicator(cp));
}
static inline bool cluster_joins(const uint32_t *cps, int len,
uint32_t cp, int klass)
{
if (joins_cluster(cp, klass))
return true;
if (cps[len - 1] == 0x200D)
return wsap_vtcore_unicode_extended_pictographic(cp);
return len == 1 && cp - 0x1F1E6u <= 0x19u &&
wsap_vtcore_grapheme_regional_indicator(cp) &&
wsap_vtcore_grapheme_regional_indicator(cps[0]);
}
#endif
|