]>
Commit | Line | Data |
---|---|---|
4e36662e KZ |
1 | /* |
2 | * No copyright is claimed. This code is in the public domain; do with | |
3 | * it what you wish. | |
4 | * | |
278f76ae | 5 | * Copyright (C) 2012-2015 Karel Zak <kzak@redhat.com> |
4e36662e | 6 | */ |
0bef6f75 KZ |
7 | #include "c.h" |
8 | #include "color-names.h" | |
9 | ||
208480c4 KZ |
10 | #include <ctype.h> |
11 | ||
0bef6f75 KZ |
12 | struct ul_color_name { |
13 | const char *name; | |
14 | const char *seq; | |
15 | }; | |
16 | ||
17 | /* | |
18 | * qsort/bsearch buddy | |
19 | */ | |
20 | static int cmp_color_name(const void *a0, const void *b0) | |
21 | { | |
c8b237a0 KZ |
22 | const struct ul_color_name |
23 | *a = (const struct ul_color_name *) a0, | |
24 | *b = (const struct ul_color_name *) b0; | |
0bef6f75 KZ |
25 | return strcmp(a->name, b->name); |
26 | } | |
27 | ||
28 | /* | |
29 | * Maintains human readable color names | |
30 | */ | |
31 | const char *color_sequence_from_colorname(const char *str) | |
32 | { | |
33 | static const struct ul_color_name basic_schemes[] = { | |
34 | { "black", UL_COLOR_BLACK }, | |
4683cf36 | 35 | { "blink", UL_COLOR_BLINK }, |
0bef6f75 | 36 | { "blue", UL_COLOR_BLUE }, |
4683cf36 | 37 | { "bold", UL_COLOR_BOLD }, |
0bef6f75 KZ |
38 | { "brown", UL_COLOR_BROWN }, |
39 | { "cyan", UL_COLOR_CYAN }, | |
40 | { "darkgray", UL_COLOR_DARK_GRAY }, | |
41 | { "gray", UL_COLOR_GRAY }, | |
42 | { "green", UL_COLOR_GREEN }, | |
4683cf36 | 43 | { "halfbright", UL_COLOR_HALFBRIGHT }, |
0bef6f75 KZ |
44 | { "lightblue", UL_COLOR_BOLD_BLUE }, |
45 | { "lightcyan", UL_COLOR_BOLD_CYAN }, | |
46 | { "lightgray,", UL_COLOR_GRAY }, | |
47 | { "lightgreen", UL_COLOR_BOLD_GREEN }, | |
48 | { "lightmagenta", UL_COLOR_BOLD_MAGENTA }, | |
49 | { "lightred", UL_COLOR_BOLD_RED }, | |
50 | { "magenta", UL_COLOR_MAGENTA }, | |
51 | { "red", UL_COLOR_RED }, | |
4683cf36 KZ |
52 | { "reset", UL_COLOR_RESET, }, |
53 | { "reverse", UL_COLOR_REVERSE }, | |
0bef6f75 | 54 | { "yellow", UL_COLOR_BOLD_YELLOW }, |
53829df2 | 55 | { "white", UL_COLOR_WHITE } |
0bef6f75 | 56 | }; |
c8b237a0 | 57 | struct ul_color_name key = { .name = str }, *res; |
0bef6f75 KZ |
58 | |
59 | if (!str) | |
60 | return NULL; | |
61 | ||
62 | res = bsearch(&key, basic_schemes, ARRAY_SIZE(basic_schemes), | |
63 | sizeof(struct ul_color_name), | |
64 | cmp_color_name); | |
65 | return res ? res->seq : NULL; | |
66 | } | |
208480c4 KZ |
67 | |
68 | ||
69 | int color_is_sequence(const char *color) | |
70 | { | |
71 | if (color && *color == 0x1B) { | |
72 | size_t len = strlen(color); | |
73 | ||
74 | if (len >= 4 && | |
75 | *(color + 1) == '[' && | |
76 | isdigit(*(color + 2)) && | |
77 | *(color + len - 1) == 'm') | |
78 | return 1; | |
79 | } | |
80 | ||
81 | return 0; | |
82 | } | |
83 | ||
84 | /* canonicalize sequence */ | |
85 | static int __color_canonicalize(const char *str, char **seq) | |
86 | { | |
87 | char *in, *out; | |
88 | int len; | |
89 | ||
90 | if (!str) | |
91 | return -EINVAL; | |
92 | ||
93 | *seq = NULL; | |
94 | ||
95 | /* convert color names like "red" to the real sequence */ | |
96 | if (*str != '\\' && isalpha(*str)) { | |
97 | const char *s = color_sequence_from_colorname(str); | |
98 | *seq = strdup(s ? s : str); | |
99 | ||
100 | return *seq ? 0 : -ENOMEM; | |
101 | } | |
102 | ||
103 | /* convert xx;yy sequences to "\033[xx;yy" */ | |
104 | if ((len = asprintf(seq, "\033[%sm", str)) < 1) | |
105 | return -ENOMEM; | |
106 | ||
107 | for (in = *seq, out = *seq; in && *in; in++) { | |
108 | if (*in != '\\') { | |
109 | *out++ = *in; | |
110 | continue; | |
111 | } | |
112 | switch(*(in + 1)) { | |
113 | case 'a': | |
114 | *out++ = '\a'; /* Bell */ | |
115 | break; | |
116 | case 'b': | |
117 | *out++ = '\b'; /* Backspace */ | |
118 | break; | |
119 | case 'e': | |
120 | *out++ = '\033'; /* Escape */ | |
121 | break; | |
122 | case 'f': | |
123 | *out++ = '\f'; /* Form Feed */ | |
124 | break; | |
125 | case 'n': | |
126 | *out++ = '\n'; /* Newline */ | |
127 | break; | |
128 | case 'r': | |
129 | *out++ = '\r'; /* Carriage Return */ | |
130 | break; | |
131 | case 't': | |
132 | *out++ = '\t'; /* Tab */ | |
133 | break; | |
134 | case 'v': | |
135 | *out++ = '\v'; /* Vertical Tab */ | |
136 | break; | |
137 | case '\\': | |
138 | *out++ = '\\'; /* Backslash */ | |
139 | break; | |
140 | case '_': | |
141 | *out++ = ' '; /* Space */ | |
142 | break; | |
143 | case '#': | |
144 | *out++ = '#'; /* Hash mark */ | |
145 | break; | |
146 | case '?': | |
147 | *out++ = '?'; /* Question mark */ | |
148 | break; | |
149 | default: | |
150 | *out++ = *in; | |
151 | *out++ = *(in + 1); | |
152 | break; | |
153 | } | |
154 | in++; | |
155 | } | |
156 | ||
157 | if (out) { | |
158 | assert ((out - *seq) <= len); | |
159 | *out = '\0'; | |
160 | } | |
161 | ||
162 | return 0; | |
163 | } | |
164 | ||
165 | char *color_get_sequence(const char *color) | |
166 | { | |
167 | char *seq = NULL; | |
168 | int rc = __color_canonicalize(color, &seq); | |
169 | ||
170 | return rc ? NULL : seq; | |
171 | } |