1 #include "theme.h"
2
3 #include "debug.h"
4 #include "filesys.h"
5 #include "theme_tables.h"
6 #include "ui.h"
7
8 #include <stdlib.h>
9 #include <string.h>
10
11 #define COLOR_PROC(a_ulColor) RGB((a_ulColor >> 16) & 0x0000FF, (a_ulColor >> 8) & 0x0000FF, a_ulColor & 0x0000FF)
12
13 /* Solarized color scheme */
14 #define SOLAR_BASE03 0x002b36
15 #define SOLAR_BASE02 0x073642
16 #define SOLAR_BASE01 0x586e75
17 #define SOLAR_BASE00 0x657b83
18 #define SOLAR_BASE0 0x839496
19 #define SOLAR_BASE1 0x93a1a1
20 #define SOLAR_BASE2 0xeee8d5
21 #define SOLAR_BASE3 0xfdf6e3
22 #define SOLAR_YELLOW 0xb58900
23 #define SOLAR_ORANGE 0xcb4b16
24 #define SOLAR_RED 0xdc322f
25 #define SOLAR_MAGENTA 0xd33682
26 #define SOLAR_VIOLET 0x6c71c4
27 #define SOLAR_BLUE 0x268bd2
28 #define SOLAR_CYAN 0x2aa198
29 #define SOLAR_GREEN 0x859900
30
31 uint32_t COLOR_BKGRND_MAIN;
32 uint32_t COLOR_BKGRND_ALT;
33 uint32_t COLOR_BKGRND_AUX;
34 uint32_t COLOR_BKGRND_MENU;
35 uint32_t COLOR_BKGRND_MENU_HOVER;
36 uint32_t COLOR_BKGRND_MENU_ACTIVE;
37 uint32_t COLOR_BKGRND_LIST;
38 uint32_t COLOR_BKGRND_LIST_HOVER;
39
40 uint32_t COLOR_MAIN_TEXT;
41 uint32_t COLOR_MAIN_TEXT_CHAT;
42 uint32_t COLOR_MAIN_TEXT_SUBTEXT;
43 uint32_t COLOR_MAIN_TEXT_ACTION;
44 uint32_t COLOR_MAIN_TEXT_QUOTE;
45 uint32_t COLOR_MAIN_TEXT_RED;
46 uint32_t COLOR_MAIN_TEXT_URL;
47 uint32_t COLOR_MAIN_TEXT_HINT;
48
49 uint32_t COLOR_MSG_USER;
50 uint32_t COLOR_MSG_USER_PEND;
51 uint32_t COLOR_MSG_USER_ERROR;
52 uint32_t COLOR_MSG_CONTACT;
53
54 uint32_t COLOR_MENU_TEXT;
55 uint32_t COLOR_MENU_TEXT_SUBTEXT;
56 uint32_t COLOR_MENU_TEXT_ACTIVE;
57
58 uint32_t COLOR_LIST_TEXT;
59 uint32_t COLOR_LIST_TEXT_SUBTEXT;
60
61 uint32_t COLOR_AUX_EDGE_NORMAL;
62 uint32_t COLOR_AUX_EDGE_HOVER;
63 uint32_t COLOR_AUX_EDGE_ACTIVE;
64 uint32_t COLOR_AUX_TEXT;
65 uint32_t COLOR_AUX_ACTIVEOPTION_BKGRND;
66 uint32_t COLOR_AUX_ACTIVEOPTION_TEXT;
67
68 uint32_t COLOR_GROUP_SELF;
69 uint32_t COLOR_GROUP_PEER;
70 uint32_t COLOR_GROUP_AUDIO;
71 uint32_t COLOR_GROUP_MUTED;
72
73 uint32_t COLOR_SELECTION_BACKGROUND;
74 uint32_t COLOR_SELECTION_TEXT;
75
76 uint32_t COLOR_EDGE_NORMAL;
77 uint32_t COLOR_EDGE_ACTIVE;
78 uint32_t COLOR_EDGE_HOVER;
79
80 uint32_t COLOR_ACTIVEOPTION_BKGRND;
81 uint32_t COLOR_ACTIVEOPTION_TEXT;
82
83 uint32_t COLOR_STATUS_ONLINE;
84 uint32_t COLOR_STATUS_AWAY;
85
86 uint32_t COLOR_STATUS_BUSY;
87 uint32_t COLOR_BTN_SUCCESS_BKGRND;
88 uint32_t COLOR_BTN_SUCCESS_TEXT;
89 uint32_t COLOR_BTN_SUCCESS_BKGRND_HOVER;
90 uint32_t COLOR_BTN_SUCCESS_TEXT_HOVER;
91
92 uint32_t COLOR_BTN_WARNING_BKGRND;
93 uint32_t COLOR_BTN_WARNING_TEXT;
94 uint32_t COLOR_BTN_WARNING_BKGRND_HOVER;
95 uint32_t COLOR_BTN_WARNING_TEXT_HOVER;
96
97 uint32_t COLOR_BTN_DANGER_BACKGROUND;
98 uint32_t COLOR_BTN_DANGER_TEXT;
99 uint32_t COLOR_BTN_DANGER_BKGRND_HOVER;
100 uint32_t COLOR_BTN_DANGER_TEXT_HOVER;
101
102 uint32_t COLOR_BTN_DISABLED_BKGRND;
103 uint32_t COLOR_BTN_DISABLED_TEXT;
104 uint32_t COLOR_BTN_DISABLED_BKGRND_HOVER;
105 uint32_t COLOR_BTN_DISABLED_TRANSFER;
106
107 uint32_t COLOR_BTN_INPROGRESS_BKGRND;
108 uint32_t COLOR_BTN_INPROGRESS_TEXT;
109 uint32_t COLOR_BTN_DISABLED_FORGRND;
110 uint32_t COLOR_BTN_INPROGRESS_FORGRND;
111
112 uint32_t status_color[4];
113
114 /**
115 * Loads a custom theme and sets out to the size of the data
116 *
117 * Returns a pointer to the theme data on success, the caller needs to free this
118 * Returns NULL on failure
119 */
120 static uint8_t *utox_data_load_custom_theme(size_t *out);
121 static void read_custom_theme(const uint8_t *data, size_t length);
122 static uint32_t try_parse_hex_colour(char *color, bool *error);
123
theme_load(const THEME loadtheme)124 void theme_load(const THEME loadtheme) {
125 // Update the settings dropdown UI
126
127 // ==== Default theme ====
128 // ---- Background Colors ----
129 COLOR_BKGRND_MAIN = COLOR_PROC(0xffffff);
130 COLOR_BKGRND_ALT = COLOR_PROC(0xaaaaaa);
131 COLOR_BKGRND_AUX = COLOR_PROC(0x313131);
132 COLOR_BKGRND_LIST = COLOR_PROC(0x414141);
133 COLOR_BKGRND_LIST_HOVER = COLOR_PROC(0x505050);
134 COLOR_BKGRND_MENU = COLOR_PROC(0x1c1c1c);
135 COLOR_BKGRND_MENU_HOVER = COLOR_PROC(0x282828);
136 COLOR_BKGRND_MENU_ACTIVE = COLOR_PROC(0x414141);
137
138 /* ---- Text Colors --- */
139 COLOR_MAIN_TEXT = COLOR_PROC(0x333333);
140 COLOR_MAIN_TEXT_CHAT = COLOR_PROC(0x000000);
141 COLOR_MAIN_TEXT_SUBTEXT = COLOR_PROC(0x414141);
142 COLOR_MAIN_TEXT_ACTION = COLOR_PROC(0x4e4ec8);
143 COLOR_MAIN_TEXT_QUOTE = COLOR_PROC(0x008000);
144 COLOR_MAIN_TEXT_RED = COLOR_PROC(0xFF0000);
145 COLOR_MAIN_TEXT_URL = COLOR_PROC(0x001fff);
146 COLOR_MAIN_TEXT_HINT = COLOR_PROC(0x969696);
147
148 /* Message window colors */
149 COLOR_MSG_USER = COLOR_MAIN_TEXT_SUBTEXT;
150 COLOR_MSG_USER_PEND = COLOR_MAIN_TEXT_ACTION;
151 COLOR_MSG_USER_ERROR = COLOR_MAIN_TEXT_RED;
152 COLOR_MSG_CONTACT = COLOR_MAIN_TEXT;
153
154 //---- Friend list header and bottom-left buttons ----
155 COLOR_MENU_TEXT = COLOR_BKGRND_MAIN;
156 COLOR_MENU_TEXT_SUBTEXT = COLOR_PROC(0xd1d1d1);
157 COLOR_MENU_TEXT_ACTIVE = COLOR_BKGRND_MAIN;
158
159 //---- Friend list ----
160 COLOR_LIST_TEXT = COLOR_MENU_TEXT;
161 COLOR_LIST_TEXT_SUBTEXT = COLOR_MENU_TEXT_SUBTEXT;
162
163 //---- Groupchat user list and title ----
164 COLOR_GROUP_SELF = COLOR_PROC(0x6bc260);
165 COLOR_GROUP_PEER = COLOR_MAIN_TEXT_HINT;
166 COLOR_GROUP_AUDIO = COLOR_PROC(0xc84e4e);
167 COLOR_GROUP_MUTED = COLOR_MAIN_TEXT_ACTION;
168
169 //---- Text selection ----
170 COLOR_SELECTION_BACKGROUND = COLOR_MAIN_TEXT;
171 COLOR_SELECTION_TEXT = COLOR_BKGRND_MAIN;
172
173 //---- Inputs, dropdowns & tooltips ----
174 COLOR_EDGE_NORMAL = COLOR_PROC(0xc0c0c0);
175 COLOR_EDGE_HOVER = COLOR_PROC(0x969696);
176 COLOR_EDGE_ACTIVE = COLOR_PROC(0x4ea6ea);
177 COLOR_ACTIVEOPTION_BKGRND = COLOR_PROC(0xd1d1d1);
178 COLOR_ACTIVEOPTION_TEXT = COLOR_MAIN_TEXT;
179
180 //---- Auxiliary style for inputs/dropdowns ("Search friends" bar) ----
181 COLOR_AUX_EDGE_NORMAL = COLOR_BKGRND_AUX;
182 COLOR_AUX_EDGE_HOVER = COLOR_PROC(0x999999);
183 COLOR_AUX_EDGE_ACTIVE = COLOR_PROC(0x1A73B7);
184 COLOR_AUX_TEXT = COLOR_LIST_TEXT;
185 COLOR_AUX_ACTIVEOPTION_BKGRND = COLOR_BKGRND_LIST_HOVER;
186 COLOR_AUX_ACTIVEOPTION_TEXT = COLOR_AUX_TEXT;
187
188 //---- Status circles ----
189 COLOR_STATUS_ONLINE = COLOR_PROC(0x6bc260);
190 COLOR_STATUS_AWAY = COLOR_PROC(0xcebf45);
191 COLOR_STATUS_BUSY = COLOR_PROC(0xc84e4e);
192
193 //---- Buttons ----
194 COLOR_BTN_SUCCESS_BKGRND = COLOR_STATUS_ONLINE;
195 COLOR_BTN_SUCCESS_BKGRND_HOVER = COLOR_PROC(0x76d56a);
196 COLOR_BTN_SUCCESS_TEXT = COLOR_BKGRND_MAIN;
197 COLOR_BTN_SUCCESS_TEXT_HOVER = COLOR_BKGRND_MAIN;
198
199 COLOR_BTN_WARNING_BKGRND = COLOR_STATUS_AWAY;
200 COLOR_BTN_WARNING_BKGRND_HOVER = COLOR_PROC(0xe3d24c);
201 COLOR_BTN_WARNING_TEXT = COLOR_BKGRND_MAIN;
202 COLOR_BTN_WARNING_TEXT_HOVER = COLOR_BKGRND_MAIN;
203
204 COLOR_BTN_DANGER_BACKGROUND = COLOR_STATUS_BUSY;
205 COLOR_BTN_DANGER_BKGRND_HOVER = COLOR_PROC(0xdc5656);
206 COLOR_BTN_DANGER_TEXT = COLOR_BKGRND_MAIN;
207 COLOR_BTN_DANGER_TEXT_HOVER = COLOR_BKGRND_MAIN;
208
209 COLOR_BTN_DISABLED_BKGRND = COLOR_PROC(0xd1d1d1);
210 COLOR_BTN_DISABLED_BKGRND_HOVER = COLOR_BKGRND_LIST_HOVER;
211 COLOR_BTN_DISABLED_TEXT = COLOR_BKGRND_MAIN;
212 COLOR_BTN_DISABLED_TRANSFER = COLOR_BKGRND_LIST;
213 COLOR_BTN_DISABLED_FORGRND = COLOR_PROC(0xb3b3b3);
214
215 COLOR_BTN_INPROGRESS_BKGRND = COLOR_PROC(0x4ea6ea);
216 COLOR_BTN_INPROGRESS_TEXT = COLOR_BKGRND_MAIN;
217 COLOR_BTN_INPROGRESS_FORGRND = COLOR_PROC(0x76baef);
218
219 switch (loadtheme) {
220 case THEME_DARK: {
221 COLOR_BKGRND_MAIN = COLOR_PROC(0x333333);
222 COLOR_BKGRND_ALT = COLOR_PROC(0x151515);
223 COLOR_BKGRND_LIST = COLOR_PROC(0x222222);
224 COLOR_BKGRND_LIST_HOVER = COLOR_PROC(0x151515);
225 COLOR_BKGRND_MENU = COLOR_PROC(0x171717);
226 COLOR_BKGRND_AUX = COLOR_BKGRND_MENU;
227 COLOR_BKGRND_MENU_HOVER = COLOR_BKGRND_LIST_HOVER;
228 COLOR_BKGRND_MENU_ACTIVE = COLOR_BKGRND_LIST;
229
230 COLOR_MAIN_TEXT = COLOR_PROC(0xdfdfdf);
231 COLOR_MAIN_TEXT_CHAT = COLOR_PROC(0xffffff);
232 COLOR_MAIN_TEXT_SUBTEXT = COLOR_PROC(0xbbbbbb);
233 COLOR_MAIN_TEXT_ACTION = COLOR_PROC(0x27a9bc);
234 COLOR_MAIN_TEXT_URL = COLOR_MAIN_TEXT_ACTION;
235 COLOR_MAIN_TEXT_QUOTE = COLOR_PROC(0x55b317);
236
237 COLOR_MSG_USER = COLOR_MAIN_TEXT_SUBTEXT;
238 COLOR_MSG_USER_PEND = COLOR_PROC(0x66ccff);
239 COLOR_MSG_USER_ERROR = COLOR_MAIN_TEXT_RED;
240 COLOR_MSG_CONTACT = COLOR_MAIN_TEXT;
241
242 COLOR_MENU_TEXT_ACTIVE = COLOR_MAIN_TEXT;
243
244 COLOR_GROUP_MUTED = COLOR_MAIN_TEXT_URL;
245
246 COLOR_SELECTION_BACKGROUND = COLOR_MAIN_TEXT;
247 COLOR_SELECTION_TEXT = COLOR_BKGRND_MAIN;
248
249 COLOR_EDGE_NORMAL = COLOR_PROC(0x555555);
250 COLOR_EDGE_ACTIVE = COLOR_PROC(0x228888);
251 COLOR_EDGE_HOVER = COLOR_PROC(0x999999);
252 COLOR_ACTIVEOPTION_BKGRND = COLOR_PROC(0x228888);
253 COLOR_ACTIVEOPTION_TEXT = COLOR_MAIN_TEXT;
254
255 COLOR_AUX_EDGE_NORMAL = COLOR_BKGRND_AUX;
256 COLOR_AUX_EDGE_ACTIVE = COLOR_EDGE_ACTIVE;
257 COLOR_AUX_ACTIVEOPTION_BKGRND = COLOR_ACTIVEOPTION_BKGRND;
258
259 COLOR_BTN_SUCCESS_BKGRND = COLOR_PROC(0x414141);
260 COLOR_BTN_SUCCESS_TEXT = COLOR_PROC(0x33a63d);
261 COLOR_BTN_SUCCESS_BKGRND_HOVER = COLOR_PROC(0x455147);
262 COLOR_BTN_SUCCESS_TEXT_HOVER = COLOR_PROC(0x6eff3a);
263
264 COLOR_BTN_WARNING_BKGRND = COLOR_PROC(0x414141);
265 COLOR_BTN_WARNING_TEXT = COLOR_PROC(0xbd9e22);
266 COLOR_BTN_WARNING_BKGRND_HOVER = COLOR_PROC(0x4c493c);
267 COLOR_BTN_WARNING_TEXT_HOVER = COLOR_PROC(0xff8d2a);
268
269 COLOR_BTN_DANGER_BACKGROUND = COLOR_PROC(0x414141);
270 COLOR_BTN_DANGER_TEXT = COLOR_PROC(0xbd2525);
271 COLOR_BTN_DANGER_BKGRND_HOVER = COLOR_PROC(0x513939);
272 COLOR_BTN_DANGER_TEXT_HOVER = COLOR_PROC(0xfa2626);
273
274 COLOR_BTN_DISABLED_BKGRND = COLOR_PROC(0x414141);
275 COLOR_BTN_DISABLED_TEXT = COLOR_MAIN_TEXT;
276 COLOR_BTN_DISABLED_TRANSFER = COLOR_BTN_DISABLED_TEXT;
277 COLOR_BTN_DISABLED_FORGRND = COLOR_PROC(0x666666);
278
279 COLOR_BTN_INPROGRESS_BKGRND = COLOR_BTN_DISABLED_BKGRND;
280 COLOR_BTN_INPROGRESS_TEXT = COLOR_MAIN_TEXT_URL;
281 COLOR_BTN_INPROGRESS_FORGRND = COLOR_PROC(0x2f656a);
282 break;
283 }
284 case THEME_LIGHT: {
285 COLOR_BKGRND_AUX = COLOR_PROC(0xe0e0e0);
286 COLOR_BKGRND_LIST = COLOR_PROC(0xf0f0f0);
287 COLOR_BKGRND_LIST_HOVER = COLOR_PROC(0xe0e0e0);
288 COLOR_BKGRND_MENU = COLOR_BKGRND_LIST;
289 COLOR_BKGRND_MENU_HOVER = COLOR_PROC(0xe0e0e0);
290 COLOR_BKGRND_MENU_ACTIVE = COLOR_PROC(0x555555);
291
292 COLOR_LIST_TEXT = COLOR_MAIN_TEXT;
293 COLOR_LIST_TEXT_SUBTEXT = COLOR_MAIN_TEXT_SUBTEXT;
294
295 COLOR_MENU_TEXT = COLOR_PROC(0x555555);
296 COLOR_MENU_TEXT_ACTIVE = COLOR_PROC(0xffffff);
297 COLOR_MENU_TEXT_SUBTEXT = COLOR_PROC(0x414141);
298
299 COLOR_EDGE_NORMAL = COLOR_PROC(0xc0c0c0);
300 COLOR_EDGE_HOVER = COLOR_PROC(0x707070);
301 COLOR_ACTIVEOPTION_BKGRND = COLOR_PROC(0xc2e0ff);
302 COLOR_ACTIVEOPTION_TEXT = COLOR_MAIN_TEXT;
303
304 COLOR_AUX_EDGE_NORMAL = COLOR_BKGRND_AUX;
305 COLOR_AUX_EDGE_HOVER = COLOR_PROC(0x999999);
306 COLOR_AUX_EDGE_ACTIVE = COLOR_EDGE_ACTIVE;
307 COLOR_AUX_TEXT = COLOR_LIST_TEXT;
308 COLOR_AUX_ACTIVEOPTION_BKGRND = COLOR_ACTIVEOPTION_BKGRND;
309 COLOR_AUX_ACTIVEOPTION_TEXT = COLOR_AUX_TEXT;
310 break;
311 }
312 case THEME_HIGHCONTRAST: {
313 COLOR_BKGRND_MAIN = COLOR_PROC(0xffffff);
314 COLOR_BKGRND_AUX = COLOR_BKGRND_MAIN;
315 COLOR_BKGRND_LIST = COLOR_PROC(0x444444);
316 COLOR_BKGRND_LIST_HOVER = COLOR_PROC(0x000001);
317 COLOR_BKGRND_MENU = COLOR_BKGRND_MAIN;
318 COLOR_BKGRND_MENU_HOVER = COLOR_BKGRND_MAIN;
319 COLOR_BKGRND_MENU_ACTIVE = COLOR_BKGRND_LIST_HOVER;
320
321 COLOR_MAIN_TEXT = COLOR_PROC(0x000001);
322 COLOR_MAIN_TEXT_CHAT = COLOR_MAIN_TEXT;
323 COLOR_MAIN_TEXT_SUBTEXT = COLOR_MAIN_TEXT;
324 COLOR_MAIN_TEXT_ACTION = COLOR_PROC(0x0000ff);
325 COLOR_MAIN_TEXT_QUOTE = COLOR_PROC(0x00ff00);
326 COLOR_MAIN_TEXT_URL = COLOR_MAIN_TEXT_ACTION;
327 COLOR_MAIN_TEXT_HINT = COLOR_MAIN_TEXT;
328
329 COLOR_MENU_TEXT = COLOR_MAIN_TEXT;
330 COLOR_MENU_TEXT_SUBTEXT = COLOR_MAIN_TEXT;
331 COLOR_MENU_TEXT_ACTIVE = COLOR_BKGRND_MAIN;
332
333 COLOR_LIST_TEXT = COLOR_BKGRND_MAIN;
334 COLOR_LIST_TEXT_SUBTEXT = COLOR_BKGRND_MAIN;
335
336 COLOR_GROUP_SELF = COLOR_PROC(0x00ff00);
337 COLOR_GROUP_PEER = COLOR_MAIN_TEXT_HINT;
338 COLOR_GROUP_AUDIO = COLOR_PROC(0xff0000);
339 COLOR_GROUP_MUTED = COLOR_MAIN_TEXT_URL;
340
341 COLOR_SELECTION_BACKGROUND = COLOR_MAIN_TEXT;
342 COLOR_SELECTION_TEXT = COLOR_BKGRND_MAIN;
343
344 COLOR_EDGE_NORMAL = COLOR_MAIN_TEXT;
345 COLOR_EDGE_ACTIVE = COLOR_MAIN_TEXT;
346 COLOR_EDGE_HOVER = COLOR_MAIN_TEXT;
347 COLOR_ACTIVEOPTION_BKGRND = COLOR_MAIN_TEXT;
348 COLOR_ACTIVEOPTION_TEXT = COLOR_BKGRND_MAIN;
349
350 COLOR_AUX_EDGE_NORMAL = COLOR_EDGE_NORMAL;
351 COLOR_AUX_EDGE_HOVER = COLOR_EDGE_NORMAL;
352 COLOR_AUX_EDGE_ACTIVE = COLOR_EDGE_ACTIVE;
353 COLOR_AUX_TEXT = COLOR_MAIN_TEXT;
354 COLOR_AUX_ACTIVEOPTION_BKGRND = COLOR_ACTIVEOPTION_BKGRND;
355 COLOR_AUX_ACTIVEOPTION_TEXT = COLOR_ACTIVEOPTION_TEXT;
356
357 COLOR_STATUS_ONLINE = COLOR_PROC(0x00ff00);
358 COLOR_STATUS_AWAY = COLOR_PROC(0xffff00);
359 COLOR_STATUS_BUSY = COLOR_PROC(0xff0000);
360
361 COLOR_BTN_SUCCESS_BKGRND = COLOR_PROC(0x00ff00);
362 COLOR_BTN_SUCCESS_TEXT = COLOR_BKGRND_MAIN;
363 COLOR_BTN_SUCCESS_BKGRND_HOVER = COLOR_PROC(0x00ff00);
364 COLOR_BTN_SUCCESS_TEXT_HOVER = COLOR_BKGRND_MAIN;
365
366 COLOR_BTN_WARNING_BKGRND = COLOR_PROC(0xffff00);
367 COLOR_BTN_WARNING_TEXT = COLOR_BKGRND_MAIN;
368 COLOR_BTN_WARNING_BKGRND_HOVER = COLOR_PROC(0xffff00);
369 COLOR_BTN_WARNING_TEXT_HOVER = COLOR_BKGRND_MAIN;
370
371 COLOR_BTN_DANGER_BACKGROUND = COLOR_PROC(0xff0000);
372 COLOR_BTN_DANGER_TEXT = COLOR_BKGRND_MAIN;
373 COLOR_BTN_DANGER_BKGRND_HOVER = COLOR_PROC(0xff0000);
374 COLOR_BTN_DANGER_TEXT_HOVER = COLOR_BKGRND_MAIN;
375
376 COLOR_BTN_DISABLED_BKGRND = COLOR_PROC(0x444444);
377 COLOR_BTN_DISABLED_TEXT = COLOR_MAIN_TEXT;
378 COLOR_BTN_DISABLED_TRANSFER = COLOR_BKGRND_MAIN;
379 COLOR_BTN_DISABLED_FORGRND = COLOR_PROC(0x000000);
380
381 COLOR_BTN_INPROGRESS_TEXT = COLOR_BTN_DISABLED_TEXT;
382 COLOR_BTN_INPROGRESS_BKGRND = COLOR_PROC(0x00ffff);
383 break;
384 }
385 case THEME_ZENBURN: {
386 COLOR_BKGRND_MAIN = COLOR_PROC(0x3f3f3f);
387 COLOR_BKGRND_AUX = COLOR_BKGRND_MAIN;
388 COLOR_BKGRND_LIST = COLOR_PROC(0x5f5f5f);
389 COLOR_BKGRND_LIST_HOVER = COLOR_PROC(0x7f7f7f);
390 COLOR_BKGRND_MENU = COLOR_BKGRND_MAIN;
391 COLOR_BKGRND_MENU_HOVER = COLOR_PROC(0x7f9f7f);
392 COLOR_BKGRND_MENU_ACTIVE = COLOR_BKGRND_MENU_HOVER;
393
394 COLOR_MAIN_TEXT = COLOR_PROC(0xdcdccc);
395 COLOR_MAIN_TEXT_CHAT = COLOR_MAIN_TEXT;
396 COLOR_MAIN_TEXT_SUBTEXT = COLOR_MAIN_TEXT;
397 COLOR_MAIN_TEXT_ACTION = COLOR_PROC(0xd0bf8f);
398 COLOR_MAIN_TEXT_QUOTE = COLOR_PROC(0x7f9f7f);
399 COLOR_MAIN_TEXT_RED = COLOR_PROC(0xcc9393);
400 COLOR_MAIN_TEXT_URL = COLOR_PROC(0x6ca0a3);
401 COLOR_MAIN_TEXT_HINT = COLOR_MAIN_TEXT;
402
403 COLOR_MSG_USER = COLOR_MAIN_TEXT;
404 COLOR_MSG_USER_PEND = COLOR_MAIN_TEXT_ACTION;
405 COLOR_MSG_USER_ERROR = COLOR_MAIN_TEXT_RED;
406 COLOR_MSG_CONTACT = COLOR_MAIN_TEXT;
407
408 COLOR_MENU_TEXT = COLOR_MAIN_TEXT;
409 COLOR_MENU_TEXT_SUBTEXT = COLOR_MAIN_TEXT;
410 COLOR_MENU_TEXT_ACTIVE = COLOR_MAIN_TEXT;
411
412 COLOR_LIST_TEXT = COLOR_MAIN_TEXT;
413 COLOR_LIST_TEXT_SUBTEXT = COLOR_MAIN_TEXT;
414
415 COLOR_GROUP_SELF = COLOR_MAIN_TEXT;
416 COLOR_GROUP_PEER = COLOR_MAIN_TEXT;
417 COLOR_GROUP_AUDIO = COLOR_MAIN_TEXT_QUOTE;
418 COLOR_GROUP_MUTED = COLOR_MAIN_TEXT_ACTION;
419
420 COLOR_SELECTION_BACKGROUND = COLOR_MAIN_TEXT_QUOTE;
421 COLOR_SELECTION_TEXT = COLOR_MAIN_TEXT;
422
423 COLOR_EDGE_NORMAL = COLOR_BKGRND_LIST;
424 COLOR_EDGE_ACTIVE = COLOR_MAIN_TEXT;
425 COLOR_EDGE_HOVER = COLOR_MAIN_TEXT_QUOTE;
426 COLOR_ACTIVEOPTION_BKGRND = COLOR_MAIN_TEXT_QUOTE;
427 COLOR_ACTIVEOPTION_TEXT = COLOR_MAIN_TEXT;
428
429 COLOR_AUX_EDGE_NORMAL = COLOR_BKGRND_LIST;
430 COLOR_AUX_EDGE_HOVER = COLOR_MAIN_TEXT_QUOTE;
431 COLOR_AUX_EDGE_ACTIVE = COLOR_MAIN_TEXT;
432 COLOR_AUX_TEXT = COLOR_MAIN_TEXT;
433 COLOR_AUX_ACTIVEOPTION_BKGRND = COLOR_MAIN_TEXT_QUOTE;
434 COLOR_AUX_ACTIVEOPTION_TEXT = COLOR_MAIN_TEXT;
435
436 COLOR_STATUS_ONLINE = COLOR_MAIN_TEXT_QUOTE;
437 COLOR_STATUS_AWAY = COLOR_MAIN_TEXT_ACTION;
438 COLOR_STATUS_BUSY = COLOR_MAIN_TEXT_RED;
439
440 COLOR_BTN_SUCCESS_BKGRND = COLOR_MAIN_TEXT_QUOTE;
441 COLOR_BTN_SUCCESS_TEXT = COLOR_MAIN_TEXT;
442 COLOR_BTN_SUCCESS_BKGRND_HOVER = COLOR_PROC(0xbfebbf);
443 COLOR_BTN_SUCCESS_TEXT_HOVER = COLOR_PROC(0xffffff);
444
445 COLOR_BTN_WARNING_BKGRND = COLOR_MAIN_TEXT_ACTION;
446 COLOR_BTN_WARNING_TEXT = COLOR_BTN_SUCCESS_TEXT_HOVER;
447 COLOR_BTN_WARNING_BKGRND_HOVER = COLOR_PROC(0xf0dfaf);
448 COLOR_BTN_WARNING_TEXT_HOVER = COLOR_BTN_SUCCESS_TEXT_HOVER;
449
450 COLOR_BTN_DANGER_BACKGROUND = COLOR_STATUS_AWAY;
451 COLOR_BTN_DANGER_TEXT = COLOR_MAIN_TEXT;
452 COLOR_BTN_DANGER_BKGRND_HOVER = COLOR_PROC(0xdca3a3);
453 COLOR_BTN_DANGER_TEXT_HOVER = COLOR_BTN_SUCCESS_TEXT_HOVER;
454
455 COLOR_BTN_DISABLED_BKGRND = COLOR_BKGRND_LIST;
456 COLOR_BTN_DISABLED_TEXT = COLOR_MAIN_TEXT;
457 COLOR_BTN_DISABLED_BKGRND_HOVER = COLOR_BKGRND_LIST_HOVER;
458 COLOR_BTN_DISABLED_TRANSFER = COLOR_MAIN_TEXT;
459 COLOR_BTN_DISABLED_FORGRND = COLOR_BKGRND_LIST_HOVER;
460
461 COLOR_BTN_INPROGRESS_BKGRND = COLOR_PROC(0xc1c1a4);
462 COLOR_BTN_INPROGRESS_TEXT = COLOR_BKGRND_MAIN;
463 COLOR_BTN_INPROGRESS_FORGRND = COLOR_MAIN_TEXT;
464 break;
465 }
466 case THEME_SOLARIZED_DARK: {
467 COLOR_BKGRND_MAIN = COLOR_PROC(SOLAR_BASE03);
468 COLOR_BKGRND_ALT = COLOR_PROC(SOLAR_BASE02);
469 COLOR_BKGRND_AUX = COLOR_BKGRND_ALT;
470 COLOR_BKGRND_LIST = COLOR_BKGRND_ALT;
471 COLOR_BKGRND_LIST_HOVER = COLOR_PROC(SOLAR_BASE01);
472 COLOR_BKGRND_MENU = COLOR_PROC(SOLAR_BASE03);
473 COLOR_BKGRND_MENU_HOVER = COLOR_PROC(SOLAR_CYAN);
474 COLOR_BKGRND_MENU_ACTIVE = COLOR_BKGRND_ALT;
475
476 COLOR_MAIN_TEXT = COLOR_PROC(SOLAR_BASE2);
477 COLOR_MAIN_TEXT_CHAT = COLOR_MAIN_TEXT;
478 COLOR_MAIN_TEXT_SUBTEXT = COLOR_PROC(SOLAR_BASE1);
479 COLOR_MAIN_TEXT_ACTION = COLOR_PROC(SOLAR_BASE3);
480 COLOR_MAIN_TEXT_QUOTE = COLOR_MAIN_TEXT_SUBTEXT;
481 COLOR_MAIN_TEXT_RED = COLOR_PROC(SOLAR_RED);
482 COLOR_MAIN_TEXT_URL = COLOR_PROC(SOLAR_MAGENTA);
483 COLOR_MAIN_TEXT_HINT = COLOR_PROC(SOLAR_VIOLET);
484
485 COLOR_MSG_USER = COLOR_MAIN_TEXT_SUBTEXT;
486 COLOR_MSG_USER_PEND = COLOR_MAIN_TEXT_ACTION;
487 COLOR_MSG_USER_ERROR = COLOR_MAIN_TEXT_RED;
488 COLOR_MSG_CONTACT = COLOR_MAIN_TEXT;
489
490 COLOR_MENU_TEXT = COLOR_MAIN_TEXT;
491 COLOR_MENU_TEXT_SUBTEXT = COLOR_MAIN_TEXT_SUBTEXT;
492 COLOR_MENU_TEXT_ACTIVE = COLOR_MAIN_TEXT;
493
494 COLOR_LIST_TEXT = COLOR_MAIN_TEXT;
495 COLOR_LIST_TEXT_SUBTEXT = COLOR_MAIN_TEXT_SUBTEXT;
496
497 COLOR_GROUP_SELF = COLOR_PROC(SOLAR_GREEN);
498 COLOR_GROUP_PEER = COLOR_MAIN_TEXT_HINT;
499 COLOR_GROUP_AUDIO = COLOR_PROC(SOLAR_RED);
500 COLOR_GROUP_MUTED = COLOR_MAIN_TEXT_ACTION;
501
502 COLOR_SELECTION_BACKGROUND = COLOR_MAIN_TEXT;
503 COLOR_SELECTION_TEXT = COLOR_BKGRND_MAIN;
504
505 COLOR_EDGE_NORMAL = COLOR_PROC(SOLAR_VIOLET);
506 COLOR_EDGE_HOVER = COLOR_PROC(SOLAR_BLUE);
507 COLOR_EDGE_ACTIVE = COLOR_PROC(SOLAR_ORANGE);
508 COLOR_ACTIVEOPTION_BKGRND = COLOR_BKGRND_LIST_HOVER;
509 COLOR_ACTIVEOPTION_TEXT = COLOR_MAIN_TEXT;
510
511 COLOR_AUX_EDGE_NORMAL = COLOR_BKGRND_AUX;
512 COLOR_AUX_EDGE_HOVER = COLOR_PROC(SOLAR_VIOLET);
513 COLOR_AUX_EDGE_ACTIVE = COLOR_PROC(SOLAR_CYAN);
514 COLOR_AUX_TEXT = COLOR_LIST_TEXT;
515 COLOR_AUX_ACTIVEOPTION_BKGRND = COLOR_BKGRND_LIST_HOVER;
516 COLOR_AUX_ACTIVEOPTION_TEXT = COLOR_AUX_TEXT;
517
518 COLOR_STATUS_ONLINE = COLOR_PROC(SOLAR_GREEN);
519 COLOR_STATUS_AWAY = COLOR_PROC(SOLAR_YELLOW);
520 COLOR_STATUS_BUSY = COLOR_PROC(SOLAR_RED);
521
522 COLOR_BTN_SUCCESS_BKGRND = COLOR_STATUS_ONLINE;
523 COLOR_BTN_SUCCESS_TEXT = COLOR_MAIN_TEXT;
524 COLOR_BTN_SUCCESS_BKGRND_HOVER = COLOR_PROC(SOLAR_CYAN);
525 COLOR_BTN_SUCCESS_TEXT_HOVER = COLOR_BKGRND_MAIN;
526
527 COLOR_BTN_WARNING_BKGRND = COLOR_STATUS_AWAY;
528 COLOR_BTN_WARNING_TEXT = COLOR_MAIN_TEXT;
529 COLOR_BTN_WARNING_BKGRND_HOVER = COLOR_PROC(SOLAR_ORANGE);
530 COLOR_BTN_WARNING_TEXT_HOVER = COLOR_BKGRND_MAIN;
531
532 COLOR_BTN_DANGER_BACKGROUND = COLOR_STATUS_BUSY;
533 COLOR_BTN_DANGER_TEXT = COLOR_MAIN_TEXT;
534 COLOR_BTN_DANGER_BKGRND_HOVER = COLOR_PROC(SOLAR_MAGENTA);
535 COLOR_BTN_DANGER_TEXT_HOVER = COLOR_BKGRND_MAIN;
536
537 COLOR_BTN_DISABLED_BKGRND = COLOR_PROC(SOLAR_BASE00);
538 COLOR_BTN_DISABLED_TEXT = COLOR_BKGRND_MAIN;
539 COLOR_BTN_DISABLED_BKGRND_HOVER = COLOR_BKGRND_LIST_HOVER;
540 COLOR_BTN_DISABLED_TRANSFER = COLOR_BKGRND_LIST;
541 COLOR_BTN_DISABLED_FORGRND = COLOR_PROC(SOLAR_ORANGE);
542
543 COLOR_BTN_INPROGRESS_FORGRND = COLOR_PROC(SOLAR_MAGENTA);
544 COLOR_BTN_INPROGRESS_BKGRND = COLOR_PROC(SOLAR_VIOLET);
545 COLOR_BTN_INPROGRESS_TEXT = COLOR_BKGRND_MAIN;
546 break;
547 }
548 case THEME_SOLARIZED_LIGHT: {
549 COLOR_BKGRND_MAIN = COLOR_PROC(SOLAR_BASE3);
550 COLOR_BKGRND_ALT = COLOR_PROC(SOLAR_BASE2);
551 COLOR_BKGRND_AUX = COLOR_BKGRND_ALT;
552 COLOR_BKGRND_LIST = COLOR_BKGRND_ALT;
553 COLOR_BKGRND_LIST_HOVER = COLOR_PROC(SOLAR_BASE1);
554 COLOR_BKGRND_MENU = COLOR_BKGRND_ALT;
555 COLOR_BKGRND_MENU_HOVER = COLOR_PROC(SOLAR_CYAN);
556 COLOR_BKGRND_MENU_ACTIVE = COLOR_BKGRND_ALT;
557
558 COLOR_MAIN_TEXT = COLOR_PROC(SOLAR_BASE02);
559 COLOR_MAIN_TEXT_CHAT = COLOR_MAIN_TEXT;
560 COLOR_MAIN_TEXT_SUBTEXT = COLOR_PROC(SOLAR_BASE01);
561 COLOR_MAIN_TEXT_ACTION = COLOR_PROC(SOLAR_BASE03);
562 COLOR_MAIN_TEXT_QUOTE = COLOR_MAIN_TEXT_SUBTEXT;
563 COLOR_MAIN_TEXT_RED = COLOR_PROC(SOLAR_RED);
564 COLOR_MAIN_TEXT_URL = COLOR_PROC(SOLAR_MAGENTA);
565 COLOR_MAIN_TEXT_HINT = COLOR_PROC(SOLAR_VIOLET);
566
567 COLOR_MSG_USER = COLOR_MAIN_TEXT_SUBTEXT;
568 COLOR_MSG_USER_PEND = COLOR_MAIN_TEXT_ACTION;
569 COLOR_MSG_USER_ERROR = COLOR_MAIN_TEXT_RED;
570 COLOR_MSG_CONTACT = COLOR_MAIN_TEXT;
571
572 COLOR_MENU_TEXT = COLOR_MAIN_TEXT;
573 COLOR_MENU_TEXT_SUBTEXT = COLOR_MAIN_TEXT_SUBTEXT;
574 COLOR_MENU_TEXT_ACTIVE = COLOR_MAIN_TEXT;
575
576 COLOR_LIST_TEXT = COLOR_MAIN_TEXT;
577 COLOR_LIST_TEXT_SUBTEXT = COLOR_MAIN_TEXT_SUBTEXT;
578
579 COLOR_GROUP_SELF = COLOR_PROC(SOLAR_GREEN);
580 COLOR_GROUP_PEER = COLOR_MAIN_TEXT_HINT;
581 COLOR_GROUP_AUDIO = COLOR_PROC(SOLAR_RED);
582 COLOR_GROUP_MUTED = COLOR_MAIN_TEXT_ACTION;
583
584 COLOR_SELECTION_BACKGROUND = COLOR_MAIN_TEXT;
585 COLOR_SELECTION_TEXT = COLOR_BKGRND_MAIN;
586
587 COLOR_EDGE_NORMAL = COLOR_PROC(SOLAR_VIOLET);
588 COLOR_EDGE_HOVER = COLOR_PROC(SOLAR_BLUE);
589 COLOR_EDGE_ACTIVE = COLOR_PROC(SOLAR_CYAN);
590 COLOR_ACTIVEOPTION_BKGRND = COLOR_BKGRND_LIST_HOVER;
591 COLOR_ACTIVEOPTION_TEXT = COLOR_MAIN_TEXT;
592
593 COLOR_AUX_EDGE_NORMAL = COLOR_BKGRND_AUX;
594 COLOR_AUX_EDGE_HOVER = COLOR_PROC(SOLAR_VIOLET);
595 COLOR_AUX_EDGE_ACTIVE = COLOR_PROC(SOLAR_CYAN);
596 COLOR_AUX_TEXT = COLOR_LIST_TEXT;
597 COLOR_AUX_ACTIVEOPTION_BKGRND = COLOR_BKGRND_LIST_HOVER;
598 COLOR_AUX_ACTIVEOPTION_TEXT = COLOR_AUX_TEXT;
599
600 COLOR_STATUS_ONLINE = COLOR_PROC(SOLAR_GREEN);
601 COLOR_STATUS_AWAY = COLOR_PROC(SOLAR_YELLOW);
602 COLOR_STATUS_BUSY = COLOR_PROC(SOLAR_RED);
603
604 COLOR_BTN_SUCCESS_BKGRND = COLOR_STATUS_ONLINE;
605 COLOR_BTN_SUCCESS_TEXT = COLOR_MAIN_TEXT;
606 COLOR_BTN_SUCCESS_BKGRND_HOVER = COLOR_PROC(SOLAR_CYAN);
607 COLOR_BTN_SUCCESS_TEXT_HOVER = COLOR_BKGRND_MAIN;
608
609 COLOR_BTN_WARNING_BKGRND = COLOR_STATUS_AWAY;
610 COLOR_BTN_WARNING_TEXT = COLOR_MAIN_TEXT;
611 COLOR_BTN_WARNING_BKGRND_HOVER = COLOR_PROC(SOLAR_ORANGE);
612 COLOR_BTN_WARNING_TEXT_HOVER = COLOR_BKGRND_MAIN;
613
614 COLOR_BTN_DANGER_BACKGROUND = COLOR_STATUS_BUSY;
615 COLOR_BTN_DANGER_TEXT = COLOR_MAIN_TEXT;
616 COLOR_BTN_DANGER_BKGRND_HOVER = COLOR_PROC(SOLAR_MAGENTA);
617 COLOR_BTN_DANGER_TEXT_HOVER = COLOR_BKGRND_MAIN;
618
619 COLOR_BTN_DISABLED_BKGRND = COLOR_PROC(SOLAR_BASE0);
620 COLOR_BTN_DISABLED_TEXT = COLOR_BKGRND_MAIN;
621 COLOR_BTN_DISABLED_BKGRND_HOVER = COLOR_BKGRND_LIST_HOVER;
622 COLOR_BTN_DISABLED_TRANSFER = COLOR_BKGRND_LIST;
623 COLOR_BTN_DISABLED_FORGRND = COLOR_PROC(SOLAR_ORANGE);
624
625 COLOR_BTN_INPROGRESS_BKGRND = COLOR_PROC(SOLAR_VIOLET);
626 COLOR_BTN_INPROGRESS_TEXT = COLOR_BKGRND_MAIN;
627 COLOR_BTN_INPROGRESS_FORGRND = COLOR_PROC(SOLAR_MAGENTA);
628 break;
629 }
630 case THEME_CUSTOM: {
631 size_t size;
632 uint8_t *themedata = utox_data_load_custom_theme(&size);
633 if (!themedata) {
634 return;
635 }
636 read_custom_theme(themedata, size);
637 free(themedata);
638 break;
639 }
640 case THEME_DEFAULT: {
641 // Set above the switch.
642 break;
643 }
644 }
645
646 status_color[0] = COLOR_STATUS_ONLINE;
647 status_color[1] = COLOR_STATUS_AWAY;
648 status_color[2] = COLOR_STATUS_BUSY;
649 status_color[3] = COLOR_STATUS_BUSY;
650 }
651
find_colour_pointer(char * color)652 uint32_t *find_colour_pointer(char *color) {
653 while (*color == 0 || *color == ' ' || *color == '\t') {
654 ++color;
655 }
656
657 for (int l = strlen(color) - 1; l > 0; --l) {
658 if (color[l] != ' ' && color[l] != '\t') {
659 color[l + 1] = '\0';
660 break;
661 }
662 }
663
664 // Skip past "COLOR_" prefix
665 if (!strncmp(color, "COLOR_", 6)) {
666 color += 6;
667 }
668
669 LOG_INFO("Theme", "Color: %s" , color);
670
671 for (int i = 0;; ++i) {
672 const char *s = COLOUR_NAME_TABLE[i];
673
674 if (!s) {
675 break;
676 }
677
678 if (!strcmp(color, s)) {
679 return COLOUR_POINTER_TABLE[i];
680 }
681 }
682
683 return NULL;
684 }
685
try_parse_hex_colour(char * color,bool * error)686 static uint32_t try_parse_hex_colour(char *color, bool *error) {
687 while (*color == 0 || *color == ' ' || *color == '\t') {
688 color++;
689 }
690
691 for (int l = strlen(color) - 1; l > 0; --l) {
692 if (color[l] != ' ' && color[l] != '\n') {
693 color[++l] = '\0';
694
695 if (l != 6) {
696 *error = true;
697 return 0;
698 }
699 break;
700 }
701 }
702
703 char hex[3] = { 0 };
704
705 memcpy(hex, color, 2);
706 unsigned char red = strtol(hex, NULL, 16);
707 memcpy(hex, color + 2, 2);
708 unsigned char green = strtol(hex, NULL, 16);
709 memcpy(hex, color + 4, 2);
710 unsigned char blue = strtol(hex, NULL, 16);
711
712 return RGB(red, green, blue);
713 }
714
read_custom_theme(const uint8_t * data,size_t length)715 static void read_custom_theme(const uint8_t *data, size_t length) {
716 while (length) {
717 char *line = (char *)data;
718 while (*line != 0) {
719 if (*line == '#') {
720 *line = 0;
721 break;
722 }
723 ++line;
724 --length;
725 }
726
727 char *color = strpbrk(line, "=");
728
729 if (!color || color == line) {
730 continue;
731 }
732
733 *color++ = 0;
734
735 uint32_t *colorp = find_colour_pointer(line);
736 if (!colorp) {
737 continue;
738 }
739
740 bool err = false;
741 const uint32_t col = try_parse_hex_colour(color, &err);
742
743 if (err) {
744 LOG_ERR("Theme", "Error: Parsing hex color failed.");
745 continue;
746 } else {
747 *colorp = COLOR_PROC(col);
748 }
749 }
750 }
751
utox_data_load_custom_theme(size_t * out)752 static uint8_t *utox_data_load_custom_theme(size_t *out) {
753 FILE *fp = utox_get_file("utox_theme.ini", out, UTOX_FILE_OPTS_READ);
754
755 if (fp == NULL) {
756 LOG_ERR("Theme", "Failed to open custom theme file.");
757 return NULL;
758 }
759
760 uint8_t *data = calloc(1, *out + 1);
761 if (data == NULL) {
762 LOG_ERR("Theme", "Failed to allocate memory for custom theme.");
763 fclose(fp);
764 return NULL;
765 }
766
767 if (fread(data, *out, 1, fp) != 1) {
768 LOG_ERR("Theme", "Could not read custom theme from file.");
769 fclose(fp);
770 free(data);
771 return NULL;
772 }
773 fclose(fp);
774
775 return data;
776 }
777