diff options
Diffstat (limited to 'src/palette.c')
| -rw-r--r-- | src/palette.c | 73 |
1 files changed, 52 insertions, 21 deletions
diff --git a/src/palette.c b/src/palette.c index a8add4e..bfaba6c 100644 --- a/src/palette.c +++ b/src/palette.c @@ -133,13 +133,19 @@ static uint32_t *palette_slot(struct term_theme *p, const char *key, const char *digits = key + 5; if (!*digits || (*digits == '0' && digits[1])) return NULL; - int i = 0; - for (const char *d = digits; *d; d++) { - if (*d < '0' || *d > '9') + int i; + if (!digits[1]) { + if (digits[0] < '0' || digits[0] > '9') return NULL; - i = i * 10 + (*d - '0'); + i = digits[0] - '0'; + } else if (!digits[2]) { + if (digits[0] < '0' || digits[0] > '9' || digits[1] < '0' || digits[1] > '9') + return NULL; + i = (digits[0] - '0') * 10 + (digits[1] - '0'); if (i > 15) return NULL; + } else { + return NULL; } *fallback = builtin_theme.ansi[i]; return &p->ansi[i]; @@ -166,19 +172,36 @@ bool term_theme_set_key(struct term_theme *p, const char *key, const char *val) static bool parse_hex_channel(const char *s, size_t len, uint8_t *out) { - if (len == 0 || len > 4) - return false; - unsigned v = 0; - for (size_t i = 0; i < len; i++) { - int d = term_hex_nib(s[i]); + if (len == 2) { + int d0 = term_hex_nib(s[0]), d1 = term_hex_nib(s[1]); + if ((d0 | d1) < 0) + return false; + *out = (uint8_t)((d0 << 4) | d1); + return true; + } + if (len == 1) { + int d = term_hex_nib(s[0]); if (d < 0) return false; - v = (v << 4) | (unsigned)d; + *out = (uint8_t)(d * 17); + return true; } - static const unsigned max_for_len[5] = {0, 15, 255, 4095, 65535}; - unsigned max = max_for_len[len]; - *out = (uint8_t)((unsigned long)v * 255 / max); - return true; + if (len == 4) { + int d0 = term_hex_nib(s[0]), d1 = term_hex_nib(s[1]); + int d2 = term_hex_nib(s[2]), d3 = term_hex_nib(s[3]); + if ((d0 | d1 | d2 | d3) < 0) + return false; + *out = (uint8_t)((((unsigned)d0 << 12) | ((unsigned)d1 << 8) | ((unsigned)d2 << 4) | (unsigned)d3) * 255 / 65535); + return true; + } + if (len == 3) { + int d0 = term_hex_nib(s[0]), d1 = term_hex_nib(s[1]), d2 = term_hex_nib(s[2]); + if ((d0 | d1 | d2) < 0) + return false; + *out = (uint8_t)((((unsigned)d0 << 8) | ((unsigned)d1 << 4) | (unsigned)d2) * 255 / 4095); + return true; + } + return false; } static bool parse_fraction(const char *s, size_t len, uint8_t *out) @@ -224,6 +247,8 @@ static bool parse_fraction(const char *s, size_t len, uint8_t *out) static const char *skip_leading_ws(const char *s) { + if (*s != ' ' && *s != '\t') + return s; while (*s == ' ' || *s == '\t') s++; return s; @@ -232,6 +257,8 @@ static const char *skip_leading_ws(const char *s) static size_t rtrimmed_len(const char *s) { size_t n = strlen(s); + if (n == 0 || (s[n - 1] != ' ' && s[n - 1] != '\t')) + return n; while (n > 0 && (s[n - 1] == ' ' || s[n - 1] == '\t')) n--; return n; @@ -294,15 +321,19 @@ bool term_color_parse(const char *input, uint32_t *out) } if (ci != 3) return false; - uint8_t c[3]; - for (int k = 0; k < 3; k++) { - bool ok = intensity - ? parse_fraction(channels[k], chlens[k], &c[k]) - : parse_hex_channel(channels[k], chlens[k], &c[k]); - if (!ok) + uint8_t c0, c1, c2; + if (intensity) { + if (!parse_fraction(channels[0], chlens[0], &c0) || + !parse_fraction(channels[1], chlens[1], &c1) || + !parse_fraction(channels[2], chlens[2], &c2)) + return false; + } else { + if (!parse_hex_channel(channels[0], chlens[0], &c0) || + !parse_hex_channel(channels[1], chlens[1], &c1) || + !parse_hex_channel(channels[2], chlens[2], &c2)) return false; } - *out = term_rgb(c[0], c[1], c[2]); + *out = term_rgb(c0, c1, c2); return true; } |
