From cfe5e3905201349e9cf3f95d52ff4bd100bde37d Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 14 Apr 2024 21:10:49 +0200 Subject: Adding upstream version 2.39.3. Signed-off-by: Daniel Baumann --- lib/color-names.c | 171 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 171 insertions(+) create mode 100644 lib/color-names.c (limited to 'lib/color-names.c') diff --git a/lib/color-names.c b/lib/color-names.c new file mode 100644 index 0000000..fa5453c --- /dev/null +++ b/lib/color-names.c @@ -0,0 +1,171 @@ +/* + * No copyright is claimed. This code is in the public domain; do with + * it what you wish. + * + * Copyright (C) 2012-2015 Karel Zak + */ +#include "c.h" +#include "color-names.h" + +#include + +struct ul_color_name { + const char *name; + const char *seq; +}; + +/* + * qsort/bsearch buddy + */ +static int cmp_color_name(const void *a0, const void *b0) +{ + const struct ul_color_name + *a = (const struct ul_color_name *) a0, + *b = (const struct ul_color_name *) b0; + return strcmp(a->name, b->name); +} + +/* + * Maintains human readable color names + */ +const char *color_sequence_from_colorname(const char *str) +{ + static const struct ul_color_name basic_schemes[] = { + { "black", UL_COLOR_BLACK }, + { "blink", UL_COLOR_BLINK }, + { "blue", UL_COLOR_BLUE }, + { "bold", UL_COLOR_BOLD }, + { "brown", UL_COLOR_BROWN }, + { "cyan", UL_COLOR_CYAN }, + { "darkgray", UL_COLOR_DARK_GRAY }, + { "gray", UL_COLOR_GRAY }, + { "green", UL_COLOR_GREEN }, + { "halfbright", UL_COLOR_HALFBRIGHT }, + { "lightblue", UL_COLOR_BOLD_BLUE }, + { "lightcyan", UL_COLOR_BOLD_CYAN }, + { "lightgray,", UL_COLOR_GRAY }, + { "lightgreen", UL_COLOR_BOLD_GREEN }, + { "lightmagenta", UL_COLOR_BOLD_MAGENTA }, + { "lightred", UL_COLOR_BOLD_RED }, + { "magenta", UL_COLOR_MAGENTA }, + { "red", UL_COLOR_RED }, + { "reset", UL_COLOR_RESET, }, + { "reverse", UL_COLOR_REVERSE }, + { "yellow", UL_COLOR_BOLD_YELLOW }, + { "white", UL_COLOR_WHITE } + }; + struct ul_color_name key = { .name = str }, *res; + + if (!str) + return NULL; + + res = bsearch(&key, basic_schemes, ARRAY_SIZE(basic_schemes), + sizeof(struct ul_color_name), + cmp_color_name); + return res ? res->seq : NULL; +} + + +int color_is_sequence(const char *color) +{ + if (color && *color == 0x1B) { + size_t len = strlen(color); + + if (len >= 4 && + *(color + 1) == '[' && + isdigit(*(color + 2)) && + *(color + len - 1) == 'm') + return 1; + } + + return 0; +} + +/* canonicalize sequence */ +static int __color_canonicalize(const char *str, char **seq) +{ + char *in, *out; + int len; + + if (!str) + return -EINVAL; + + *seq = NULL; + + /* convert color names like "red" to the real sequence */ + if (*str != '\\' && isalpha(*str)) { + const char *s = color_sequence_from_colorname(str); + *seq = strdup(s ? s : str); + + return *seq ? 0 : -ENOMEM; + } + + /* convert xx;yy sequences to "\033[xx;yy" */ + if ((len = asprintf(seq, "\033[%sm", str)) < 1) + return -ENOMEM; + + for (in = *seq, out = *seq; in && *in; in++) { + if (*in != '\\') { + *out++ = *in; + continue; + } + switch(*(in + 1)) { + case 'a': + *out++ = '\a'; /* Bell */ + break; + case 'b': + *out++ = '\b'; /* Backspace */ + break; + case 'e': + *out++ = '\033'; /* Escape */ + break; + case 'f': + *out++ = '\f'; /* Form Feed */ + break; + case 'n': + *out++ = '\n'; /* Newline */ + break; + case 'r': + *out++ = '\r'; /* Carriage Return */ + break; + case 't': + *out++ = '\t'; /* Tab */ + break; + case 'v': + *out++ = '\v'; /* Vertical Tab */ + break; + case '\\': + *out++ = '\\'; /* Backslash */ + break; + case '_': + *out++ = ' '; /* Space */ + break; + case '#': + *out++ = '#'; /* Hash mark */ + break; + case '?': + *out++ = '?'; /* Question mark */ + break; + default: + *out++ = *in; + *out++ = *(in + 1); + break; + } + in++; + } + + if (out) { + assert ((out - *seq) <= len); + *out = '\0'; + } + + return 0; +} + +char *color_get_sequence(const char *color) +{ + char *seq = NULL; + int rc = __color_canonicalize(color, &seq); + + return rc ? NULL : seq; +} -- cgit v1.2.3