summaryrefslogtreecommitdiff
path: root/src/pen.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/pen.h')
-rw-r--r--src/pen.h165
1 files changed, 165 insertions, 0 deletions
diff --git a/src/pen.h b/src/pen.h
new file mode 100644
index 0000000..d7118b5
--- /dev/null
+++ b/src/pen.h
@@ -0,0 +1,165 @@
+#ifndef WSAP_TERM_PEN_H
+#define WSAP_TERM_PEN_H
+
+#include "term.h"
+#include <stdbool.h>
+#include <stdint.h>
+
+struct term_pen {
+ uint32_t fg;
+ uint32_t bg;
+ uint32_t ul;
+ uint8_t underline;
+ bool bold : 1;
+ bool faint : 1;
+ bool italic : 1;
+ bool strike : 1;
+ bool overline : 1;
+ bool inverse : 1;
+};
+
+/* The pen of a stored cell. A cell has no underline color, so neither has
+ * this. */
+struct pen_attr {
+ uint32_t fg;
+ uint32_t bg;
+ uint16_t flags;
+ uint16_t link;
+};
+
+static inline struct pen_attr pen_attr_default(void)
+{
+ return (struct pen_attr){ .fg = TERM_COLOR_FG, .bg = TERM_COLOR_BG };
+}
+
+static inline bool pen_attr_is_default(const struct pen_attr *a)
+{
+ return a->fg == TERM_COLOR_FG && a->bg == TERM_COLOR_BG && a->flags == 0 && a->link == 0;
+}
+
+static inline bool pen_attr_equal(const struct pen_attr *a, const struct pen_attr *b)
+{
+ return a->fg == b->fg && a->bg == b->bg && a->flags == b->flags && a->link == b->link;
+}
+
+static inline uint32_t term_rgb(int r, int g, int b)
+{
+ return term_color_rgb((uint8_t)r, (uint8_t)g, (uint8_t)b);
+}
+
+static inline void pen_reset(struct term_pen *p)
+{
+ p->fg = TERM_COLOR_FG;
+ p->bg = TERM_COLOR_BG;
+ p->ul = 0;
+ p->underline = 0;
+ p->bold = false;
+ p->faint = false;
+ p->italic = false;
+ p->strike = false;
+ p->overline = false;
+ p->inverse = false;
+}
+
+static inline int sgr_extended_color(const int *params, int nparams, uint16_t subparams, int i,
+ uint32_t *color, bool *assigned)
+{
+ *assigned = false;
+ if (i + 1 >= nparams)
+ return 0;
+ if (i + 2 < nparams && params[i + 1] == 5) {
+ int index = params[i + 2];
+ if (index >= 0 && index <= 255) {
+ *color = term_color_index(index);
+ *assigned = true;
+ }
+ return 2;
+ }
+ if (params[i + 1] != 2)
+ return 0;
+ int colon = 0;
+ while (i + 2 + colon < nparams && i + 2 + colon < 16 &&
+ (subparams & (1u << (i + 2 + colon))))
+ colon++;
+ int skip = colon >= 4 ? 1 : 0;
+ if (i + 4 + skip >= nparams)
+ return 0;
+ *color = term_rgb(params[i + 2 + skip], params[i + 3 + skip], params[i + 4 + skip]);
+ *assigned = true;
+ return 4 + skip;
+}
+
+static inline bool pen_set_standard_color(struct term_pen *p, int code)
+{
+ if ((unsigned)(code - 30) < 8)
+ p->fg = term_color_index(code - 30);
+ else if ((unsigned)(code - 40) < 8)
+ p->bg = term_color_index(code - 40);
+ else if ((unsigned)(code - 90) < 8)
+ p->fg = term_color_index(code - 90 + 8);
+ else if ((unsigned)(code - 100) < 8)
+ p->bg = term_color_index(code - 100 + 8);
+ else
+ return false;
+ return true;
+}
+
+static inline void sgr_apply(struct term_pen *pen, const int *params, int nparams, uint16_t subparams)
+{
+ if (nparams == 0) {
+ pen_reset(pen);
+ return;
+ }
+ for (int i = 0; i < nparams; i++) {
+ int p = params[i];
+ switch (p) {
+ case 0: pen_reset(pen); break;
+ case 1: pen->bold = true; break;
+ case 2: pen->faint = true; break;
+ case 3: pen->italic = true; break;
+ case 4: {
+ int style = 1;
+ if (i + 1 < nparams && (subparams & (1u << (i + 1))))
+ style = params[++i];
+ pen->underline = (uint8_t)(style <= 5 ? style : 1);
+ break;
+ }
+ case 7: pen->inverse = true; break;
+ case 9: pen->strike = true; break;
+ case 21: pen->underline = 2; break;
+ case 22: pen->bold = false; pen->faint = false; break;
+ case 23: pen->italic = false; break;
+ case 24: pen->underline = 0; break;
+ case 27: pen->inverse = false; break;
+ case 29: pen->strike = false; break;
+ case 38: {
+ uint32_t c; bool ok;
+ i += sgr_extended_color(params, nparams, subparams, i, &c, &ok);
+ if (ok) pen->fg = c;
+ break;
+ }
+ case 39: pen->fg = TERM_COLOR_FG; break;
+ case 48: {
+ uint32_t c; bool ok;
+ i += sgr_extended_color(params, nparams, subparams, i, &c, &ok);
+ if (ok) pen->bg = c;
+ break;
+ }
+ case 49: pen->bg = TERM_COLOR_BG; break;
+ case 53: pen->overline = true; break;
+ case 55: pen->overline = false; break;
+ case 58: {
+ uint32_t c; bool ok;
+ i += sgr_extended_color(params, nparams, subparams, i, &c, &ok);
+ if (ok) pen->ul = c;
+ break;
+ }
+ case 59: pen->ul = 0; break;
+ default:
+ pen_set_standard_color(pen, p);
+ break;
+ }
+ }
+}
+
+#endif