==> include/tui/style.h <==1/* @ajax/tui-style: ratatui's Color, Modifier and Style. A style says only what it changes: an
2 * unset colour leaves the cell's, add/sub modifiers turn bits on and off, and patching one style
3 * onto another keeps the latter's choices (Style::patch). Header-only. */
4#ifndef TUI_STYLE_H
5#define TUI_STYLE_H
6
7#include <stdbool.h>
8#include <stdint.h>
9
10enum { TUI_COLOR_RESET, TUI_COLOR_RGB, TUI_COLOR_INDEXED, TUI_COLOR_NAMED };
11
12/* kind TUI_COLOR_RGB: r g b; TUI_COLOR_INDEXED: r is the 256-colour index; TUI_COLOR_NAMED: r is
13 * ratatui's order (Black 0 .. White 15). */
14typedef struct {
15 uint8_t kind, r, g, b;
16} tui_color;
17
18#define TUI_RGB(R, G, B) ((tui_color){TUI_COLOR_RGB, (R), (G), (B)})
19#define TUI_RESET ((tui_color){TUI_COLOR_RESET, 0, 0, 0})
20#define TUI_NAMED(i) ((tui_color){TUI_COLOR_NAMED, (i), 0, 0})
21#define TUI_BLACK TUI_NAMED(0)
22#define TUI_RED TUI_NAMED(1)
23#define TUI_GREEN TUI_NAMED(2)
24#define TUI_YELLOW TUI_NAMED(3)
25#define TUI_BLUE TUI_NAMED(4)
26#define TUI_MAGENTA TUI_NAMED(5)
27#define TUI_CYAN TUI_NAMED(6)
28#define TUI_GRAY TUI_NAMED(7)
29#define TUI_DARK_GRAY TUI_NAMED(8)
30#define TUI_WHITE TUI_NAMED(15)
31
32enum {
33 TUI_BOLD = 1 << 0,
34 TUI_DIM = 1 << 1,
35 TUI_ITALIC = 1 << 2,
36 TUI_UNDERLINED = 1 << 3,
37 TUI_SLOW_BLINK = 1 << 4,
38 TUI_RAPID_BLINK = 1 << 5,
39 TUI_REVERSED = 1 << 6,
40 TUI_HIDDEN = 1 << 7,
41 TUI_CROSSED_OUT = 1 << 8,
42};
43
44typedef struct {
45 tui_color fg, bg;
46 bool has_fg, has_bg;
47 uint16_t add, sub; /* modifiers turned on, turned off */
48} tui_style;
49
50static inline bool tui_color_eq(tui_color a, tui_color b) {
51 return a.kind == b.kind && a.r == b.r && a.g == b.g && a.b == b.b;
52}
53
54static inline tui_style tui_style_new(void) { return (tui_style){0}; }
55static inline tui_style tui_style_fg(tui_style s, tui_color c) {
56 s.fg = c;
57 s.has_fg = true;
58 return s;
59}
60static inline tui_style tui_style_bg(tui_style s, tui_color c) {
61 s.bg = c;
62 s.has_bg = true;
63 return s;
64}
65static inline tui_style tui_style_add(tui_style s, uint16_t m) {
66 s.sub = (uint16_t)(s.sub & ~m);
67 s.add = (uint16_t)(s.add | m);
68 return s;
69}
70static inline tui_style tui_style_remove(tui_style s, uint16_t m) {
71 s.add = (uint16_t)(s.add & ~m);
72 s.sub = (uint16_t)(s.sub | m);
73 return s;
74}
75static inline tui_style tui_style_bold(tui_style s) { return tui_style_add(s, TUI_BOLD); }
76/* Shorthands: a style with just a foreground (and bold). */
77static inline tui_style tui_fg(tui_color c) { return tui_style_fg(tui_style_new(), c); }
78static inline tui_style tui_fg_bold(tui_color c) { return tui_style_bold(tui_fg(c)); }
79static inline tui_style tui_fg_bg(tui_color fg, tui_color bg) { return tui_style_bg(tui_fg(fg), bg); }
80
81/* Style::patch: other's colours win when set; other's modifiers apply over self's. */
82static inline tui_style tui_style_patch(tui_style self, tui_style other) {
83 if (other.has_fg) {
84 self.fg = other.fg;
85 self.has_fg = true;
86 }
87 if (other.has_bg) {
88 self.bg = other.bg;
89 self.has_bg = true;
90 }
91 self.add = (uint16_t)(self.add & ~other.sub);
92 self.add = (uint16_t)(self.add | other.add);
93 self.sub = (uint16_t)(self.sub & ~other.add);
94 self.sub = (uint16_t)(self.sub | other.sub);
95 return self;
96}
97
98static inline bool tui_style_eq(tui_style a, tui_style b) {
99 return a.has_fg == b.has_fg && a.has_bg == b.has_bg && (!a.has_fg || tui_color_eq(a.fg, b.fg)) &&
100 (!a.has_bg || tui_color_eq(a.bg, b.bg)) && a.add == b.add && a.sub == b.sub;
101}
102
103#endif