New action: move-cursor-line-start.
[elinks/kon.git] / src / util / color.c
blob5b7872a59e49b365cc20de275767238e7b1c91f4
1 /** Color parser
2 * @file */
4 #ifdef HAVE_CONFIG_H
5 #include "config.h"
6 #endif
8 #include <ctype.h>
9 #include <errno.h>
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <string.h>
14 #include "elinks.h"
16 #include "util/color.h"
17 #include "util/conv.h"
18 #include "util/fastfind.h"
19 #include "util/string.h"
21 struct color_spec {
22 const char *name;
23 color_T rgb;
26 static const struct color_spec color_specs[] = {
27 #include "util/color_s.inc"
28 #ifndef CONFIG_SMALL
29 #include "util/color.inc"
30 #endif
31 { NULL, 0}
34 #ifdef USE_FASTFIND
36 static const struct color_spec *internal_pointer;
38 static void
39 colors_list_reset(void)
41 internal_pointer = color_specs;
44 /** Returns a pointer to a struct that contains
45 * current key and data pointers and increment
46 * internal pointer.
47 * It returns NULL when key is NULL. */
48 static struct fastfind_key_value *
49 colors_list_next(void)
51 static struct fastfind_key_value kv;
53 if (!internal_pointer->name) return NULL;
55 kv.key = (unsigned char *) internal_pointer->name;
56 kv.data = (void *) internal_pointer; /* cast away const */
58 internal_pointer++;
60 return &kv;
63 static struct fastfind_index ff_colors_index
64 = INIT_FASTFIND_INDEX("colors_lookup", colors_list_reset, colors_list_next);
66 #endif /* USE_FASTFIND */
68 void
69 init_colors_lookup(void)
71 #ifdef USE_FASTFIND
72 fastfind_index(&ff_colors_index, FF_COMPRESS);
73 #endif
76 void
77 free_colors_lookup(void)
79 #ifdef USE_FASTFIND
80 fastfind_done(&ff_colors_index);
81 #endif
84 int
85 decode_color(unsigned char *str, int slen, color_T *color)
87 if (*str == '#' && (slen == 7 || slen == 4)) {
88 unsigned char buffer[7];
89 unsigned char *end;
90 color_T string_color;
92 str++;
94 decode_hex_color:
95 if (slen == 4) {
96 /* Expand the short hex color format */
97 buffer[0] = buffer[1] = str[0];
98 buffer[2] = buffer[3] = str[1];
99 buffer[4] = buffer[5] = str[2];
100 buffer[6] = 0;
101 str = buffer;
104 errno = 0;
105 string_color = strtoul(str, (char **) &end, 16);
106 if (!errno && (end == str + 6) && string_color <= 0xFFFFFF) {
107 *color = string_color;
108 return 0;
110 } else {
111 const struct color_spec *cs;
113 #ifndef USE_FASTFIND
114 for (cs = color_specs; cs->name; cs++)
115 if (!strlcasecmp(cs->name, -1, str, slen))
116 break;
117 #else
118 cs = fastfind_search(&ff_colors_index, str, slen);
119 #endif
120 if (cs && cs->name) {
121 *color = cs->rgb;
122 return 0;
124 } else if (slen == 6 || slen == 3) {
125 /* Check if the string is just the hexadecimal rgb
126 * color notation with the leading '#' missing and
127 * treat it as such. */
128 int len = 0;
130 while (len < slen && isxdigit(str[len])) len++;
132 if (len == slen) goto decode_hex_color;
136 return -1; /* Not found */
139 const unsigned char *
140 get_color_string(color_T color, unsigned char hexcolor[8])
142 const struct color_spec *cs;
144 for (cs = color_specs; cs->name; cs++)
145 if (cs->rgb == color)
146 return cs->name;
148 color_to_string(color, hexcolor);
149 return hexcolor;
152 void
153 color_to_string(color_T color, unsigned char str[8])
155 str[0]='#';
156 elinks_ulongcat(&str[1], NULL, (unsigned long) color, 6, '0', 16, 0);