theme.c (4565B)
1 #include "graphics.h" 2 #include "surface_cache.h" 3 #include "util.h" 4 #include "theme.h" 5 #include "memory.h" 6 7 /* FIXME: handle '#' or no '#' in color specification */ 8 static int 9 search_helper(const void *keyv, const void *entryv) { 10 char *key = (char *)keyv; 11 ltk_theme_parseinfo *entry = (ltk_theme_parseinfo *)entryv; 12 return strcmp(key, entry->key); 13 } 14 15 static int 16 sort_helper(const void *entry1v, const void *entry2v) { 17 ltk_theme_parseinfo *entry1 = (ltk_theme_parseinfo *)entry1v; 18 ltk_theme_parseinfo *entry2 = (ltk_theme_parseinfo *)entry2v; 19 return strcmp(entry1->key, entry2->key); 20 } 21 22 /* FIXME: more information for errors */ 23 int 24 ltk_theme_handle_value(ltk_window *window, char *debug_name, const char *prop, const char *value, ltk_theme_parseinfo *parseinfo, size_t len, int *sorted) { 25 if (!*sorted) { 26 qsort(parseinfo, len, sizeof(ltk_theme_parseinfo), &sort_helper); 27 *sorted = 1; 28 } 29 ltk_theme_parseinfo *entry = bsearch(prop, parseinfo, len, sizeof(ltk_theme_parseinfo), &search_helper); 30 if (!entry) { 31 ltk_warn("Invalid property '%s:%s'.\n", debug_name, prop); 32 return 1; 33 } else if (entry->initialized) { 34 ltk_warn("Duplicate setting for property '%s:%s'.\n", debug_name, prop); 35 return 1; 36 } 37 const char *errstr = NULL; 38 switch (entry->type) { 39 case THEME_INT: 40 *(entry->ptr.i) = ltk_strtonum(value, entry->min, entry->max, &errstr); 41 if (errstr) { 42 ltk_warn("Invalid value '%s' for property '%s:%s'.\n", value, debug_name, prop); 43 return 1; 44 } else { 45 entry->initialized = 1; 46 } 47 break; 48 case THEME_STRING: 49 /* FIXME: check if already set? */ 50 *(entry->ptr.str) = ltk_strdup(value); 51 entry->initialized = 1; 52 break; 53 case THEME_COLOR: 54 if (ltk_color_create(window->renderdata, value, entry->ptr.color)) { 55 ltk_warn("Unable to create color '%s' for property '%s:%s'.\n", value, debug_name, prop); 56 return 1; 57 } else { 58 entry->initialized = 1; 59 } 60 break; 61 case THEME_BOOL: 62 if (strcmp(value, "true") == 0) { 63 *(entry->ptr.b) = 1; 64 } else if (strcmp(value, "false") == 0) { 65 *(entry->ptr.b) = 0; 66 } else { 67 ltk_warn("Invalid value '%s' for property '%s:%s'.\n", value, debug_name, prop); 68 return 1; 69 } 70 entry->initialized = 1; 71 break; 72 case THEME_BORDERSIDES: 73 *(entry->ptr.border) = LTK_BORDER_NONE; 74 for (const char *c = value; *c != '\0'; c++) { 75 switch (*c) { 76 case 't': 77 *(entry->ptr.border) |= LTK_BORDER_TOP; 78 break; 79 case 'b': 80 *(entry->ptr.border) |= LTK_BORDER_BOTTOM; 81 break; 82 case 'l': 83 *(entry->ptr.border) |= LTK_BORDER_LEFT; 84 break; 85 case 'r': 86 *(entry->ptr.border) |= LTK_BORDER_RIGHT; 87 break; 88 default: 89 ltk_warn("Invalid value '%s' for property '%s:%s'.\n", value, debug_name, prop); 90 return 1; 91 } 92 } 93 entry->initialized = 1; 94 break; 95 default: 96 ltk_fatal("Invalid theme setting type. This should not happen.\n"); 97 /* TODO: ltk_assert(0); */ 98 } 99 return 0; 100 } 101 102 int 103 ltk_theme_fill_defaults(ltk_window *window, char *debug_name, ltk_theme_parseinfo *parseinfo, size_t len) { 104 for (size_t i = 0; i < len; i++) { 105 ltk_theme_parseinfo *e = &parseinfo[i]; 106 if (e->initialized) 107 continue; 108 switch (e->type) { 109 case THEME_INT: 110 *(e->ptr.i) = e->defaultval.i; 111 e->initialized = 1; 112 break; 113 case THEME_STRING: 114 *(e->ptr.str) = ltk_strdup(e->defaultval.str); 115 e->initialized = 1; 116 break; 117 case THEME_COLOR: 118 if (ltk_color_create(window->renderdata, e->defaultval.color, e->ptr.color)) { 119 ltk_warn("Unable to create default color '%s' for property '%s:%s'.\n", e->defaultval.color, debug_name, e->key); 120 return 1; 121 } else { 122 e->initialized = 1; 123 } 124 break; 125 case THEME_BOOL: 126 *(e->ptr.b) = e->defaultval.b; 127 e->initialized = 1; 128 break; 129 case THEME_BORDERSIDES: 130 *(e->ptr.border) = e->defaultval.border; 131 e->initialized = 1; 132 break; 133 default: 134 ltk_fatal("Invalid theme setting type. This should not happen.\n"); 135 /* TODO: ltk_assert(0); */ 136 } 137 } 138 return 0; 139 } 140 141 void 142 ltk_theme_uninitialize(ltk_window *window, ltk_theme_parseinfo *parseinfo, size_t len) { 143 for (size_t i = 0; i < len; i++) { 144 ltk_theme_parseinfo *e = &parseinfo[i]; 145 if (!e->initialized) 146 continue; 147 switch (e->type) { 148 case THEME_STRING: 149 ltk_free(*(e->ptr.str)); 150 e->initialized = 0; 151 break; 152 case THEME_COLOR: 153 ltk_color_destroy(window->renderdata, e->ptr.color); 154 e->initialized = 0; 155 break; 156 case THEME_INT: 157 case THEME_BOOL: 158 case THEME_BORDERSIDES: 159 e->initialized = 0; 160 break; 161 default: 162 ltk_fatal("Invalid theme setting type. This should not happen.\n"); 163 /* TODO: ltk_assert(0); */ 164 } 165 } 166 }