/* Color parser */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include "elinks.h" #include "util/color.h" #include "util/fastfind.h" #include "util/string.h" struct color_spec { char *name; color_T rgb; }; static struct color_spec color_specs[] = { #include "util/color_s.inc" #ifndef CONFIG_SMALL #include "util/color.inc" #endif { NULL, 0} }; #ifdef USE_FASTFIND static struct color_spec *internal_pointer; static void colors_list_reset(void) { internal_pointer = color_specs; } /* Returns a pointer to a struct that contains * current key and data pointers and increment * internal pointer. * It returns NULL when key is NULL. */ static struct fastfind_key_value * colors_list_next(void) { static struct fastfind_key_value kv; if (!internal_pointer->name) return NULL; kv.key = (unsigned char *) internal_pointer->name; kv.data = internal_pointer; internal_pointer++; return &kv; } static struct fastfind_index ff_colors_index = INIT_FASTFIND_INDEX("colors_lookup", colors_list_reset, colors_list_next); #endif /* USE_FASTFIND */ void init_colors_lookup(void) { #ifdef USE_FASTFIND fastfind_index(&ff_colors_index, FF_COMPRESS | FF_LOCALE_INDEP); #endif } void free_colors_lookup(void) { #ifdef USE_FASTFIND fastfind_done(&ff_colors_index); #endif } int decode_color(const unsigned char *str, int slen, color_T *color) { if (*str == '#' && (slen == 7 || slen == 4)) { unsigned char buffer[7]; unsigned char *end; color_T string_color; str++; decode_hex_color: if (slen == 4) { /* Expand the short hex color format */ buffer[0] = buffer[1] = str[0]; buffer[2] = buffer[3] = str[1]; buffer[4] = buffer[5] = str[2]; buffer[6] = 0; str = buffer; } errno = 0; string_color = strtoul(str, (char **) &end, 16); if (!errno && (end == str + 6) && string_color <= 0xFFFFFF) { *color = string_color; return 0; } } else { struct color_spec *cs; #ifndef USE_FASTFIND for (cs = color_specs; cs->name; cs++) if (!c_strlcasecmp(cs->name, -1, str, slen)) break; #else cs = fastfind_search(&ff_colors_index, str, slen); #endif if (cs && cs->name) { *color = cs->rgb; return 0; } else if (slen == 6 || slen == 3) { /* Check if the string is just the hexadecimal rgb * color notation with the leading '#' missing and * treat it as such. */ int len = 0; while (len < slen && isxdigit(str[len])) len++; if (len == slen) goto decode_hex_color; } } return -1; /* Not found */ } unsigned char * get_color_string(color_T color, unsigned char hexcolor[8]) { struct color_spec *cs; for (cs = color_specs; cs->name; cs++) if (cs->rgb == color) return cs->name; color_to_string(color, hexcolor); return hexcolor; } void color_to_string(color_T color, unsigned char str[]) { snprintf(str, 8, "#%06lx", (unsigned long) color); }