summaryrefslogtreecommitdiff
path: root/src/text_run.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/text_run.h')
-rw-r--r--src/text_run.h90
1 files changed, 90 insertions, 0 deletions
diff --git a/src/text_run.h b/src/text_run.h
new file mode 100644
index 0000000..d546062
--- /dev/null
+++ b/src/text_run.h
@@ -0,0 +1,90 @@
+#ifndef TERM_TEXT_RUN_H
+#define TERM_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 TERM_WIDTH_SLOTS 4
+struct width_cache {
+ uint32_t lo[TERM_WIDTH_SLOTS];
+ uint32_t span[TERM_WIDTH_SLOTS];
+ uint8_t klass;
+ uint8_t next;
+};
+
+/* term_new() builds the shared tables before any terminal can use them. */
+bool term_tables_ready(void);
+void term_text_tables_init(void);
+void term_snapshot_tables_init(void);
+
+int term_text_class(uint32_t cp);
+
+struct text_run_result {
+ int bytes;
+ int cols;
+ uint32_t last;
+};
+
+struct text_run_result term_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 */
+};
+
+/* term_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 term_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 || grapheme_emoji_modifier(cp))
+ return true;
+
+ return klass == 1 && 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 || grapheme_is_handle(last_char)) return true;
+ if (cp - 0x1F1E6u <= 0x19u && grapheme_regional_indicator(cp))
+ return true;
+ return joins_cluster(cp, klass);
+}
+
+static inline bool cluster_contextual(uint32_t cp)
+{
+ return unicode_spacing_mark(cp) || grapheme_emoji_modifier(cp) ||
+ (cp - 0x1F1E6u <= 0x19u && 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 unicode_extended_pictographic(cp);
+ return len == 1 && cp - 0x1F1E6u <= 0x19u &&
+ grapheme_regional_indicator(cp) &&
+ grapheme_regional_indicator(cps[0]);
+}
+
+#endif