1 /*
2 * Copyright (C) 2000-2019 the xine project
3 *
4 * This file is part of xine, a unix video player.
5 *
6 * xine is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * xine is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
19 *
20 */
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <ctype.h>
29 #include <pthread.h>
30 #include <errno.h>
31
32 #include "utils.h"
33 #include "_xitk.h"
34
35 #undef DEBUG_SKIN
36
37 /************************************************************************************
38 * PRIVATES
39 ************************************************************************************/
40
41 typedef struct {
42 const char *name;
43 xitk_image_t *image;
44 } xitk_skin_img_t;
45
xitk_simg_cmp(void * a,void * b)46 static int xitk_simg_cmp (void *a, void *b) {
47 xitk_skin_img_t *d = a, *e = b;
48 return strcmp (d->name, e->name);
49 }
50
51 /*
52 *
53 */
skin_load_img(xitk_skin_config_t * skonfig,const char * pixmap,const char * format)54 static xitk_image_t *skin_load_img (xitk_skin_config_t *skonfig, const char *pixmap, const char *format) {
55
56 if (!skonfig || !pixmap)
57 return NULL;
58
59 {
60 xitk_skin_img_t here;
61 int pos;
62 here.name = pixmap;
63 pos = xine_sarray_binary_search (skonfig->imgs, &here);
64 if (pos >= 0) {
65 xitk_skin_img_t *si = xine_sarray_get (skonfig->imgs, pos);
66 if (format && !si->image->pix_font)
67 xitk_image_set_pix_font (si->image, format);
68 return si->image;
69 }
70 }
71
72 {
73 xitk_skin_img_t *nimg;
74 size_t nlen = strlen (pixmap) + 1;
75 char *nmem = malloc (sizeof (*nimg) + nlen);
76 if (!nmem)
77 return NULL;
78 nimg = (xitk_skin_img_t *)nmem;
79 nmem += sizeof (*nimg);
80 memcpy (nmem, pixmap, nlen);
81 nimg->name = nmem;
82 nimg->image = xitk_image_load_image (skonfig->im, nmem);
83 if (!nimg->image) {
84 free (nimg);
85 return NULL;
86 }
87 if (format)
88 xitk_image_set_pix_font (nimg->image, format);
89 xine_sarray_add (skonfig->imgs, nimg);
90 return nimg->image;
91 }
92 }
93
skin_free_imgs(xitk_skin_config_t * skonfig)94 static void skin_free_imgs (xitk_skin_config_t *skonfig) {
95 int n;
96
97 for (n = xine_sarray_size (skonfig->imgs) - 1; n >= 0; n--) {
98 xitk_skin_img_t *simg = xine_sarray_get (skonfig->imgs, n);
99 xitk_image_free_image (skonfig->im, &simg->image);
100 free (simg);
101 }
102 xine_sarray_clear (skonfig->imgs);
103 }
104
105 #if 0
106 static int _key_from_name (const char *name) {
107 static const char * const names[] = {
108 "\x13""align",
109 "\x0f""animation",
110 "\x00""browser",
111 "\x14""color",
112 "\x0e""color_click",
113 "\x0d""color_focus",
114 "\x02""coords",
115 "\x01""entries",
116 "\x17""font",
117 "\x09""horizontal",
118 "\x0c""label",
119 "\x10""length",
120 "\x06""pixmap",
121 "\x11""pixmap_format",
122 "\x15""print",
123 "\x07""radius",
124 "\x0b""rotate",
125 "\x05""slider",
126 "\x12""static",
127 "\x18""step",
128 "\x16""timer",
129 "\x08""type",
130 "\x0a""vertical",
131 "\x03""x",
132 "\x04""y",
133 };
134 int b = 0, e = sizeof (names) / sizeof (names[0]), m = e >> 1;
135 do {
136 int d = strcasecmp (name, names[m] + 1);
137 if (d == 0)
138 return names[m][0];
139 if (d < 0)
140 e = m;
141 else
142 b = m + 1;
143 m = (b + e) >> 1;
144 } while (b != e);
145 return -1;
146 }
147 #endif
148
149 /*
150 *
151 */
152 #warning FIXME
_expanded(xitk_skin_config_t * skonfig,char * cmd)153 static char *_expanded(xitk_skin_config_t *skonfig, char *cmd) {
154 char *p;
155 char *buf2 = NULL;
156 char buf[BUFSIZ], var[BUFSIZ];
157
158 ABORT_IF_NULL(skonfig);
159
160 if( ! ( cmd && strchr(cmd, '$') ) ) return NULL;
161
162 buf2 = calloc(BUFSIZ, sizeof(char));
163
164 strlcpy(buf, cmd, sizeof(buf));
165
166 buf2[0] = 0;
167
168 p = buf;
169
170 while(*p != '\0') {
171 switch(*p) {
172
173 /*
174 * Prefix of variable names.
175 */
176 case '$':
177 memset(&var, 0, sizeof(var));
178 if(sscanf(p, "$\(%[A-Z-_])", &var[0])) {
179
180 p += (strlen(var) + 2);
181
182 /*
183 * Now check variable validity
184 */
185 if(!strncmp("SKIN_PARENT_PATH", var, strlen(var))) {
186 if(skonfig->path) {
187 char *ppath;
188 char *z;
189
190 ppath = strdup(skonfig->path);
191 if((z = strrchr(ppath, '/')) != NULL) {
192 *z = '\0';
193 strlcat(buf2, ppath, BUFSIZ);
194 }
195 free(ppath);
196 }
197 }
198 else if(!strncmp("SKIN_VERSION", var, strlen(var))) {
199 if(skonfig->version >= 0)
200 snprintf(buf2+strlen(buf2), sizeof(buf2)-strlen(buf2), "%d", skonfig->version);
201 }
202 else if(!strncmp("SKIN_AUTHOR", var, strlen(var))) {
203 if(skonfig->author)
204 strlcat(buf2, skonfig->author, BUFSIZ);
205 }
206 else if(!strncmp("SKIN_PATH", var, strlen(var))) {
207 if(skonfig->path)
208 strlcat(buf2, skonfig->path, BUFSIZ);
209 }
210 else if(!strncmp("SKIN_NAME", var, strlen(var))) {
211 if(skonfig->name)
212 strlcat(buf2, skonfig->name, BUFSIZ);
213 }
214 else if(!strncmp("SKIN_DATE", var, strlen(var))) {
215 if(skonfig->date)
216 strlcat(buf2, skonfig->date, BUFSIZ);
217 }
218 else if(!strncmp("SKIN_URL", var, strlen(var))) {
219 if(skonfig->url)
220 strlcat(buf2, skonfig->url, BUFSIZ);
221 }
222 else if(!strncmp("HOME", var, strlen(var))) {
223 if(skonfig->url)
224 strlcat(buf2, xine_get_homedir(), BUFSIZ);
225 }
226 /* else ignore */
227 }
228 break;
229
230 default:
231 {
232 const size_t buf2_len = strlen(buf2);
233 buf2[buf2_len + 1] = 0;
234 buf2[buf2_len] = *p;
235 }
236 break;
237 }
238 p++;
239 }
240
241 return buf2;
242 }
243
244 /*
245 * Nullify all entried from s element.
246 */
_nullify_me(xitk_skin_element_t * s)247 static void _nullify_me(xitk_skin_element_t *s) {
248 s->section[0] = 0;
249 s->info.pixmap_name = NULL;
250 s->info.pixmap_img = NULL;
251 s->info.slider_pixmap_pad_name = NULL;
252 s->info.slider_pixmap_pad_img = NULL;
253 s->info.label_pixmap_font_name = NULL;
254 s->info.label_pixmap_font_img = NULL;
255 s->info.label_color = NULL;
256 s->info.label_color_focus = NULL;
257 s->info.label_color_click = NULL;
258 s->info.label_fontname = NULL;
259 s->info.browser_entries = -2;
260 s->info.direction = DIRECTION_LEFT; /* Compatibility */
261 s->info.max_buttons = 0;
262 }
263
264 /*
265 * Return position in str of char 'c'. -1 if not found
266 */
_is_there_char(const char * str,int c)267 static int _is_there_char(const char *str, int c) {
268 char *p;
269
270 if(str)
271 if((p = strrchr(str, c)) != NULL) {
272 return (p - str);
273 }
274
275 return -1;
276 }
277
278 /*
279 * Return >= 0 if it's begin of section, otherwise -1
280 */
skin_begin_section(xitk_skin_config_t * skonfig)281 static int skin_begin_section(xitk_skin_config_t *skonfig) {
282
283 ABORT_IF_NULL(skonfig);
284
285 return _is_there_char(skonfig->ln, '{');
286 }
287
288 /*
289 * Return >= 0 if it's end of section, otherwise -1
290 */
skin_end_section(xitk_skin_config_t * skonfig)291 static int skin_end_section(xitk_skin_config_t *skonfig) {
292
293 ABORT_IF_NULL(skonfig);
294
295 return _is_there_char(skonfig->ln, '}');
296 }
297
istriplet(char * c)298 static int istriplet(char *c) {
299 int dummy1, dummy2, dummy3;
300
301 if((strncasecmp(c, "#", 1) <= 0) && (strlen(c) >= 7)) {
302
303 if(((isalnum(*(c+1))) && (isalnum(*(c+2))) && (isalnum(*(c+3)))
304 && (isalnum(*(c+4))) && (isalnum(*(c+5))) && (isalnum(*(c+6)))
305 && ((*(c+7) == '\0') || (*(c+7) == '\n') || (*(c+7) == '\r') || (*(c+7) == ' ')))
306 && (sscanf(c, "#%2x%2x%2x", &dummy1, &dummy2, &dummy3) == 3)) {
307 return 1;
308 }
309 }
310
311 return 0;
312 }
313 /*
314 * Cleanup the EOL ('\n','\r',' ')
315 */
skin_clean_eol(xitk_skin_config_t * skonfig)316 static void skin_clean_eol(xitk_skin_config_t *skonfig) {
317 char *p;
318
319 ABORT_IF_NULL(skonfig);
320
321 p = skonfig->ln;
322
323 if(p) {
324 while(*p != '\0') {
325 if(*p == '\n' || *p == '\r' || (*p == '#' && (istriplet(p) == 0)) || *p == ';'
326 || (*p == '/' && *(p+1) == '*')) {
327 *p = '\0';
328 break;
329 }
330
331 p++;
332 }
333
334 while(p > skonfig->ln) {
335 --p;
336
337 if(*p == ' ')
338 *p = '\0';
339 else
340 break;
341 }
342 }
343 }
344
345 /*
346 * Read from file, store in skonfig->buf, char pointer skonfig->ln point
347 * to buf. Cleanup the BOL/EOL. It also ignore comments lines.
348 */
skin_get_next_line(xitk_skin_config_t * skonfig)349 static void skin_get_next_line(xitk_skin_config_t *skonfig) {
350
351 ABORT_IF_NULL(skonfig);
352 ABORT_IF_NULL(skonfig->fd);
353
354 do {
355 skonfig->ln = fgets(skonfig->buf, 255, skonfig->fd);
356
357 while(skonfig->ln && (*skonfig->ln == ' ' || *skonfig->ln == '\t')) ++skonfig->ln;
358
359 } while(skonfig->ln &&
360 (!strncmp(skonfig->ln, "//", 2) ||
361 !strncmp(skonfig->ln, "/*", 2) || /* */
362 !strncmp(skonfig->ln, ";", 1) ||
363 !strncmp(skonfig->ln, "#", 1)));
364
365 skin_clean_eol(skonfig);
366 }
367
368 /*
369 * Return alignement value.
370 */
skin_get_align_value(const char * val)371 static int skin_get_align_value(const char *val) {
372 static struct {
373 const char *str;
374 int value;
375 } aligns[] = {
376 { "left", ALIGN_LEFT },
377 { "center", ALIGN_CENTER },
378 { "right", ALIGN_RIGHT },
379 { NULL, 0 }
380 };
381 int i;
382
383 ABORT_IF_NULL(val);
384
385 for(i = 0; aligns[i].str != NULL; i++) {
386 if(!(strcasecmp(aligns[i].str, val)))
387 return aligns[i].value;
388 }
389
390 return ALIGN_CENTER;
391 }
392
393 /*
394 * Return direction
395 */
skin_get_direction(const char * val)396 static int skin_get_direction(const char *val) {
397 static struct {
398 const char *str;
399 int value;
400 } directions[] = {
401 { "left", DIRECTION_LEFT },
402 { "right", DIRECTION_RIGHT },
403 { "up", DIRECTION_UP },
404 { "down", DIRECTION_DOWN },
405 { NULL, 0 }
406 };
407 int i;
408
409 ABORT_IF_NULL(val);
410
411 for(i = 0; directions[i].str != NULL; i++) {
412 if(!(strcasecmp(directions[i].str, val)))
413 return directions[i].value;
414 }
415
416 return DIRECTION_LEFT;
417 }
418
419 /*
420 * Set char pointer to first char of value. Delimiter of
421 * value is '=' or ':', e.g: "mykey = myvalue".
422 */
skin_set_pos_to_value(char ** p)423 static void skin_set_pos_to_value(char **p) {
424
425 ABORT_IF_NULL(*p);
426
427 while(*(*p) != '\0' && *(*p) != '=' && *(*p) != ':' && *(*p) != '{') ++(*p);
428 while(*(*p) == '=' || *(*p) == ':' || *(*p) == ' ' || *(*p) == '\t') ++(*p);
429 }
430
431 /*
432 * Parse subsection of skin element (coords/label yet).
433 */
skin_parse_subsection(xitk_skin_config_t * skonfig)434 static void skin_parse_subsection(xitk_skin_config_t *skonfig) {
435 char *p;
436 int brace_offset;
437
438 ABORT_IF_NULL(skonfig);
439
440 if((brace_offset = skin_begin_section(skonfig)) >= 0) {
441 *(skonfig->ln + brace_offset) = '\0';
442 skin_clean_eol(skonfig);
443
444 if(!strncasecmp(skonfig->ln, "browser", 7)) {
445
446 while(skin_end_section(skonfig) < 0) {
447 skin_get_next_line(skonfig);
448 p = skonfig->ln;
449
450 if(!strncasecmp(skonfig->ln, "entries", 7)) {
451 skin_set_pos_to_value(&p);
452 skonfig->celement->info.browser_entries = strtol(p, &p, 10);
453 }
454
455 }
456 skin_get_next_line(skonfig);
457 }
458 else if(!strncasecmp(skonfig->ln, "coords", 6)) {
459
460 while(skin_end_section(skonfig) < 0) {
461 skin_get_next_line(skonfig);
462 p = skonfig->ln;
463 if(!strncasecmp(skonfig->ln, "x", 1)) {
464 skin_set_pos_to_value(&p);
465 skonfig->celement->info.x = strtol(p, &p, 10);
466 }
467 else if(!strncasecmp(skonfig->ln, "y", 1)) {
468 skin_set_pos_to_value(&p);
469 skonfig->celement->info.y = strtol(p, &p, 10);
470 }
471
472 }
473 skin_get_next_line(skonfig);
474 }
475 else if(!strncasecmp(skonfig->ln, "slider", 6)) {
476
477 while(skin_end_section(skonfig) < 0) {
478 skin_get_next_line(skonfig);
479 p = skonfig->ln;
480 if(!strncasecmp(skonfig->ln, "pixmap", 6)) {
481 skin_set_pos_to_value(&p);
482 skonfig->celement->info.slider_pixmap_pad_name = (char *) xitk_xmalloc(strlen(skonfig->path) + strlen(p) + 2);
483 sprintf (skonfig->celement->info.slider_pixmap_pad_name, "%s/%s", skonfig->path, p);
484 skonfig->celement->info.slider_pixmap_pad_img = skin_load_img (skonfig, skonfig->celement->info.slider_pixmap_pad_name, NULL);
485 }
486 else if(!strncasecmp(skonfig->ln, "radius", 6)) {
487 skin_set_pos_to_value(&p);
488 skonfig->celement->info.slider_radius = strtol(p, &p, 10);
489 }
490 else if(!strncasecmp(skonfig->ln, "type", 4)) {
491 skin_set_pos_to_value(&p);
492 if(!strncasecmp("horizontal", p, strlen(p))) {
493 skonfig->celement->info.slider_type = XITK_HSLIDER;
494 }
495 else if(!strncasecmp("vertical", p, strlen(p))) {
496 skonfig->celement->info.slider_type = XITK_VSLIDER;
497 }
498 else if(!strncasecmp("rotate", p, strlen(p))) {
499 skonfig->celement->info.slider_type = XITK_RSLIDER;
500 }
501 else
502 skonfig->celement->info.slider_type = XITK_HSLIDER;
503 }
504
505 }
506 skin_get_next_line(skonfig);
507 }
508 else if(!strncasecmp(skonfig->ln, "label", 5)) {
509 skonfig->celement->info.label_printable = 1;
510 skonfig->celement->info.label_animation_step = 1;
511 skonfig->celement->info.label_animation_timer = xitk_get_timer_label_animation();
512 skonfig->celement->info.label_alignment = ALIGN_CENTER;
513
514 while(skin_end_section(skonfig) < 0) {
515 skin_get_next_line(skonfig);
516 p = skonfig->ln;
517
518 if(!strncasecmp(skonfig->ln, "color_focus", 11)) {
519 skin_set_pos_to_value(&p);
520 skonfig->celement->info.label_color_focus = strdup(p);
521 }
522 else if(!strncasecmp(skonfig->ln, "color_click", 11)) {
523 skin_set_pos_to_value(&p);
524 skonfig->celement->info.label_color_click = strdup(p);
525 }
526 else if(!strncasecmp(skonfig->ln, "animation", 9)) {
527 skin_set_pos_to_value(&p);
528 skonfig->celement->info.label_animation = xitk_get_bool_value(p);
529 }
530 else if(!strncasecmp(skonfig->ln, "length", 6)) {
531 skin_set_pos_to_value(&p);
532 skonfig->celement->info.label_length = strtol(p, &p, 10);
533 }
534 else if(!strncasecmp(skonfig->ln, "pixmap_format", 13)) {
535 skin_set_pos_to_value(&p);
536 if (!skonfig->celement->info.label_pixmap_font_format) {
537 skonfig->celement->info.label_pixmap_font_format = strdup (p);
538 if (skonfig->celement->info.label_pixmap_font_name)
539 skonfig->celement->info.label_pixmap_font_img = skin_load_img (skonfig,
540 skonfig->celement->info.label_pixmap_font_name,
541 skonfig->celement->info.label_pixmap_font_format);
542 }
543 }
544 else if(!strncasecmp(skonfig->ln, "pixmap", 6)) {
545 skin_set_pos_to_value(&p);
546 skonfig->celement->info.label_pixmap_font_name = (char *) xitk_xmalloc(strlen(skonfig->path) + strlen(p) + 2);
547 if (skonfig->celement->info.label_pixmap_font_name) {
548 sprintf (skonfig->celement->info.label_pixmap_font_name, "%s/%s", skonfig->path, p);
549 skonfig->celement->info.label_pixmap_font_img = skin_load_img (skonfig,
550 skonfig->celement->info.label_pixmap_font_name,
551 skonfig->celement->info.label_pixmap_font_format);
552 }
553 }
554 else if(!strncasecmp(skonfig->ln, "static", 6)) {
555 skin_set_pos_to_value(&p);
556 skonfig->celement->info.label_staticity = xitk_get_bool_value(p);
557 }
558 else if(!strncasecmp(skonfig->ln, "align", 5)) {
559 skin_set_pos_to_value(&p);
560 skonfig->celement->info.label_alignment = skin_get_align_value(p);
561 }
562 else if(!strncasecmp(skonfig->ln, "color", 5)) {
563 skin_set_pos_to_value(&p);
564 skonfig->celement->info.label_color = strdup(p);
565 }
566 else if(!strncasecmp(skonfig->ln, "print", 5)) {
567 skin_set_pos_to_value(&p);
568 skonfig->celement->info.label_printable = xitk_get_bool_value(p);
569 }
570 else if(!strncasecmp(skonfig->ln, "timer", 5)) {
571 skin_set_pos_to_value(&p);
572 skonfig->celement->info.label_animation_timer = strtol(p, &p, 10);
573 }
574 else if(!strncasecmp(skonfig->ln, "font", 4)) {
575 skin_set_pos_to_value(&p);
576 skonfig->celement->info.label_fontname = strdup(p);
577 }
578 else if(!strncasecmp(skonfig->ln, "step", 4)) {
579 skin_set_pos_to_value(&p);
580 skonfig->celement->info.label_animation_step = strtol(p, &p, 10);
581 }
582
583 }
584 skin_get_next_line(skonfig);
585 }
586
587 }
588
589 }
590
591 /*
592 * Parse skin element section.
593 */
skin_parse_section(xitk_skin_config_t * skonfig)594 static void skin_parse_section(xitk_skin_config_t *skonfig) {
595 char section[256];
596 char *p;
597
598 ABORT_IF_NULL(skonfig);
599
600 while(skonfig->ln != NULL) {
601
602 p = skonfig->ln;
603
604 if(sscanf(skonfig->ln, "skin.%s", §ion[0]) == 1) {
605
606 while(skonfig->ln != NULL) {
607
608 if(skin_begin_section(skonfig) >= 0) {
609 xitk_skin_element_t *s;
610
611 s = (xitk_skin_element_t *) xitk_xmalloc(sizeof(xitk_skin_element_t));
612 _nullify_me(s);
613
614 skonfig->celement = s;
615
616 strlcpy (s->section, section, sizeof (s->section));
617 s->info.visibility = s->info.enability = 1;
618 xine_sarray_add (skonfig->elements, s);
619
620 skin_get_next_line(skonfig);
621
622 __next_subsection:
623
624 if(skin_begin_section(skonfig) >= 0) {
625 skin_parse_subsection(skonfig);
626
627 if(skin_end_section(skonfig) >= 0) {
628 return;
629 }
630 else
631 goto __next_subsection;
632 }
633 else {
634 if(!strncasecmp(skonfig->ln, "max_buttons", 11)) {
635 skin_set_pos_to_value(&p);
636 s->info.max_buttons = strtol(p, &p, 10);
637 }
638 else if(!strncasecmp(skonfig->ln, "direction", 9)) {
639 skin_set_pos_to_value(&p);
640 s->info.direction = skin_get_direction(p);
641 }
642 else if(!strncasecmp(skonfig->ln, "visible", 7)) {
643 skin_set_pos_to_value(&p);
644 s->info.visibility = xitk_get_bool_value(p);
645 }
646 else if(!strncasecmp(skonfig->ln, "pixmap", 6)) {
647 skin_set_pos_to_value(&p);
648 s->info.pixmap_name = (char *) xitk_xmalloc(strlen(skonfig->path) + strlen(p) + 2);
649 sprintf (s->info.pixmap_name, "%s/%s", skonfig->path, p);
650 s->info.pixmap_img = skin_load_img (skonfig, s->info.pixmap_name, NULL);
651 }
652 else if(!strncasecmp(skonfig->ln, "enable", 6)) {
653 skin_set_pos_to_value(&p);
654 s->info.enability = xitk_get_bool_value(p);
655 }
656
657 }
658
659 skin_get_next_line(skonfig);
660 p = skonfig->ln;
661
662 if(skin_end_section(skonfig) >= 0) {
663 return;
664 }
665
666 goto __next_subsection;
667
668 }
669 else {
670 skin_set_pos_to_value(&p);
671
672 if(!strncasecmp(section, "unload_command", 14)) {
673 skonfig->unload_command = _expanded(skonfig, p);
674 return;
675 }
676 else if(!strncasecmp(section, "load_command", 12)) {
677 skonfig->load_command = _expanded(skonfig, p);
678 return;
679 }
680 else if(!strncasecmp(section, "animation", 9)) {
681 skonfig->animation = strdup(p);
682 return;
683 }
684 else if(!strncasecmp(section, "version", 7)) {
685 skonfig->version = strtol(p, &p, 10);
686 return;
687 }
688 else if(!strncasecmp(section, "author", 6)) {
689 skonfig->author = strdup(p);
690 return;
691 }
692 else if(!strncasecmp(section, "name", 4)) {
693 skonfig->name = strdup(p);
694 return;
695 }
696 else if(!strncasecmp(section, "date", 4)) {
697 skonfig->date = strdup(p);
698 return;
699 }
700 else if(!strncasecmp(section, "logo", 4)) {
701 skonfig->logo = _expanded(skonfig, p);
702 return;
703 }
704 else if(!strncasecmp(section, "url", 3)) {
705 skonfig->url = strdup(p);
706 return;
707 }
708 else {
709 XITK_WARNING("wrong section entry found: '%s'\n", section);
710 return;
711 }
712 }
713 skin_get_next_line(skonfig);
714 }
715 }
716 }
717 }
718
719 #ifdef DEBUG_SKIN
720 /*
721 * Just to check list chained constitency.
722 */
check_skonfig(xitk_skin_config_t * skonfig)723 static void check_skonfig(xitk_skin_config_t *skonfig) {
724 int n;
725
726 ABORT_IF_NULL(skonfig);
727
728 n = xine_sarray_size (skonfig->elements);
729 if (n) {
730 int i;
731
732 printf("Skin name '%s'\n", skonfig->name);
733 printf(" version '%d'\n", skonfig->version);
734 printf(" author '%s'\n", skonfig->author);
735 printf(" date '%s'\n", skonfig->date);
736 printf(" load cmd '%s'\n", skonfig->load_command);
737 printf(" uload cmd '%s'\n", skonfig->unload_command);
738 printf(" URL '%s'\n", skonfig->url);
739 printf(" logo '%s'\n", skonfig->logo);
740 printf(" animation '%s'\n", skonfig->animation);
741
742 for (i = 0; i < n; i++) {
743 xitk_skin_element_t *s = xine_sarray_get (skonfig->elements, i);
744
745 printf("Section '%s'\n", s->section);
746 printf(" enable = %d\n", s->info.enability);
747 printf(" visible = %d\n", s->info.visibility);
748 printf(" X = %d\n", s->info.x);
749 printf(" Y = %d\n", s->info.y);
750 printf(" direction = %d\n", s->info.direction);
751 printf(" pixmap = '%s'\n", s->info.pixmap_name);
752
753 if (s->info.slider_type) {
754 printf(" slider type = %d\n", s->info.slider_type);
755 printf(" pad pixmap = '%s'\n", s->info.slider_pixmap_pad_name);
756 }
757
758 if (s->info.browser_entries > -1)
759 printf(" browser entries = %d\n", s->info.browser_entries);
760
761 printf(" animation = %d\n", s->info.label_animation);
762 printf(" step = %d\n", s->info.label_animation_step);
763 printf(" print = %d\n", s->info.label_printable);
764 printf(" static = %d\n", s->info.label_staticity);
765 printf(" length = %d\n", s->info.label_length);
766 printf(" color = '%s'\n", s->info.label_color);
767 printf(" color focus = '%s'\n", s->info.label_color_focus);
768 printf(" color click = '%s'\n", s->info.label_color_click);
769 printf(" pixmap font = '%s'\n", s->info.label_pixmap_font_name);
770 printf(" pixmap fmt = '%s'\n", s->info.label_pixmap_font_format);
771 printf(" font = '%s'\n", s->info.label_fontname);
772 printf(" max_buttons = %d\n", s->info.max_buttons);
773 }
774
775 }
776 }
777 #endif
778
skin_lookup_section(xitk_skin_config_t * skonfig,const char * str)779 static xitk_skin_element_t *skin_lookup_section(xitk_skin_config_t *skonfig, const char *str) {
780 xitk_skin_element_t *s;
781 int r;
782
783 if (!skonfig || !str)
784 return NULL;
785
786 r = xine_sarray_binary_search (skonfig->elements, (char *)str);
787 if (r < 0)
788 return NULL;
789 s = xine_sarray_get (skonfig->elements, r);
790 return s;
791 }
792
793 /************************************************************************************
794 * END OF PRIVATES
795 ************************************************************************************/
796
797 /*
798 * Alloc a xitk_skin_config_t* memory area, nullify pointers.
799 */
xitk_skin_init_config(ImlibData * im)800 xitk_skin_config_t *xitk_skin_init_config(ImlibData *im) {
801 xitk_skin_config_t *skonfig;
802
803 if((skonfig = (xitk_skin_config_t *) xitk_xmalloc(sizeof(xitk_skin_config_t))) == NULL) {
804 XITK_DIE("xitk_xmalloc() failed: %s\n", strerror(errno));
805 }
806
807 pthread_mutex_init (&skonfig->skin_mutex, NULL);
808
809 skonfig->elements = xine_sarray_new (128, (xine_sarray_comparator_t)strcasecmp);
810 skonfig->imgs = xine_sarray_new (128, xitk_simg_cmp);
811
812 skonfig->im = im;
813 skonfig->version = -1;
814 skonfig->celement = NULL;
815 skonfig->name = skonfig->author
816 = skonfig->date
817 = skonfig->url
818 = skonfig->load_command
819 = skonfig->unload_command
820 = skonfig->logo
821 = skonfig->animation
822 = NULL;
823 skonfig->skinfile = skonfig->path = NULL;
824
825 skonfig->ln = skonfig->buf;
826
827 return skonfig;
828 }
829
830 /*
831 * Release all allocated memory of a xitk_skin_config_t* variable (element chained struct too).
832 */
xitk_skin_free_config(xitk_skin_config_t * skonfig)833 void xitk_skin_free_config(xitk_skin_config_t *skonfig) {
834
835 ABORT_IF_NULL(skonfig);
836 pthread_mutex_lock (&skonfig->skin_mutex);
837 {
838 int n = xine_sarray_size (skonfig->elements);
839 for (n--; n >= 0; n--) {
840 xitk_skin_element_t *s = xine_sarray_get (skonfig->elements, n);
841 XITK_FREE(s->info.pixmap_name);
842 XITK_FREE(s->info.slider_pixmap_pad_name);
843 XITK_FREE(s->info.label_pixmap_font_name);
844 XITK_FREE(s->info.label_pixmap_font_format);
845 XITK_FREE(s->info.label_color);
846 XITK_FREE(s->info.label_color_focus);
847 XITK_FREE(s->info.label_color_click);
848 XITK_FREE(s->info.label_fontname);
849 XITK_FREE(s);
850 }
851 }
852 xine_sarray_delete (skonfig->elements);
853
854 skin_free_imgs (skonfig);
855 xine_sarray_delete (skonfig->imgs);
856
857 XITK_FREE(skonfig->name);
858 XITK_FREE(skonfig->author);
859 XITK_FREE(skonfig->date);
860 XITK_FREE(skonfig->url);
861 XITK_FREE(skonfig->logo);
862 XITK_FREE(skonfig->animation);
863 XITK_FREE(skonfig->path);
864 XITK_FREE(skonfig->load_command);
865 XITK_FREE(skonfig->unload_command);
866 XITK_FREE(skonfig->skinfile);
867
868 pthread_mutex_unlock (&skonfig->skin_mutex);
869 pthread_mutex_destroy (&skonfig->skin_mutex);
870
871 XITK_FREE(skonfig);
872 }
873
874 /*
875 * Load the skin configfile.
876 */
xitk_skin_load_config(xitk_skin_config_t * skonfig,const char * path,const char * filename)877 int xitk_skin_load_config(xitk_skin_config_t *skonfig, const char *path, const char *filename) {
878 char buf[2048];
879
880 ABORT_IF_NULL(skonfig);
881 ABORT_IF_NULL(path);
882 ABORT_IF_NULL(filename);
883
884 pthread_mutex_lock (&skonfig->skin_mutex);
885
886 skonfig->path = strdup(path);
887 skonfig->skinfile = strdup(filename);
888
889 snprintf(buf, sizeof(buf), "%s/%s", skonfig->path, skonfig->skinfile);
890
891 if((skonfig->fd = fopen(buf, "r")) != NULL) {
892
893 skin_get_next_line(skonfig);
894
895 while(skonfig->ln != NULL) {
896
897 if(!strncasecmp(skonfig->ln, "skin.", 5)) {
898 skin_parse_section(skonfig);
899 }
900
901 skin_get_next_line(skonfig);
902 }
903 fclose(skonfig->fd);
904 }
905 else {
906 XITK_WARNING("%s(): Unable to open '%s' file.\n", __FUNCTION__, skonfig->skinfile);
907 XITK_FREE(skonfig->skinfile);
908 pthread_mutex_unlock (&skonfig->skin_mutex);
909 return 0;
910 }
911
912 if (!skonfig->celement) {
913 XITK_WARNING("%s(): no valid skin element found in '%s/%s'.\n",
914 __FUNCTION__, skonfig->path, skonfig->skinfile);
915 pthread_mutex_unlock (&skonfig->skin_mutex);
916 return 0;
917 }
918
919 #ifdef DEBUG_SKIN
920 check_skonfig(skonfig);
921 #endif
922
923 /*
924 * Execute load command
925 */
926 if(skonfig->load_command)
927 xitk_system(0, skonfig->load_command);
928
929 pthread_mutex_unlock (&skonfig->skin_mutex);
930 return 1;
931 }
932
933 /*
934 * Unload (free) xitk_skin_config_t object.
935 */
xitk_skin_unload_config(xitk_skin_config_t * skonfig)936 void xitk_skin_unload_config(xitk_skin_config_t *skonfig) {
937 if(skonfig) {
938
939 if(skonfig->unload_command)
940 xitk_system(0, skonfig->unload_command);
941
942 xitk_skin_free_config(skonfig);
943 }
944 }
945
946 /*
947 * Check skin version.
948 * return: 0 if version found < min_version
949 * 1 if version found == min_version
950 * 2 if version found > min_version
951 * -1 if no version found
952 */
xitk_skin_check_version(xitk_skin_config_t * skonfig,int min_version)953 int xitk_skin_check_version(xitk_skin_config_t *skonfig, int min_version) {
954
955 ABORT_IF_NULL(skonfig);
956
957 if(skonfig->version == -1)
958 return -1;
959 else if(skonfig->version < min_version)
960 return 0;
961 else if(skonfig->version == min_version)
962 return 1;
963 else if(skonfig->version > min_version)
964 return 2;
965
966 return -1;
967 }
968
969 /*
970 *
971 */
xitk_skin_get_direction(xitk_skin_config_t * skonfig,const char * str)972 int xitk_skin_get_direction(xitk_skin_config_t *skonfig, const char *str) {
973 xitk_skin_element_t *s;
974
975 if((s = skin_lookup_section(skonfig, str)) != NULL)
976 return s->info.direction;
977
978 return DIRECTION_LEFT; /* Compatibility */
979 }
980
981 /*
982 *
983 */
xitk_skin_get_visibility(xitk_skin_config_t * skonfig,const char * str)984 int xitk_skin_get_visibility(xitk_skin_config_t *skonfig, const char *str) {
985 xitk_skin_element_t *s;
986
987 if((s = skin_lookup_section(skonfig, str)) != NULL)
988 return s->info.visibility;
989
990 return 1;
991 }
992
993 /*
994 *
995 */
xitk_skin_get_printability(xitk_skin_config_t * skonfig,const char * str)996 int xitk_skin_get_printability(xitk_skin_config_t *skonfig, const char *str) {
997 xitk_skin_element_t *s;
998
999 if((s = skin_lookup_section(skonfig, str)) != NULL)
1000 return s->info.label_printable;
1001
1002 return 1;
1003 }
1004
1005
1006 /*
1007 *
1008 */
xitk_skin_get_enability(xitk_skin_config_t * skonfig,const char * str)1009 int xitk_skin_get_enability(xitk_skin_config_t *skonfig, const char *str) {
1010 xitk_skin_element_t *s;
1011
1012 if((s = skin_lookup_section(skonfig, str)) != NULL)
1013 return s->info.enability;
1014
1015 return 1;
1016 }
1017
1018 /*
1019 *
1020 */
xitk_skin_get_coord_x(xitk_skin_config_t * skonfig,const char * str)1021 int xitk_skin_get_coord_x(xitk_skin_config_t *skonfig, const char *str) {
1022 xitk_skin_element_t *s;
1023
1024 if((s = skin_lookup_section(skonfig, str)) != NULL)
1025 return s->info.x;
1026
1027 return 0;
1028 }
1029
1030 /*
1031 *
1032 */
xitk_skin_get_coord_y(xitk_skin_config_t * skonfig,const char * str)1033 int xitk_skin_get_coord_y(xitk_skin_config_t *skonfig, const char *str) {
1034 xitk_skin_element_t *s;
1035
1036 if((s = skin_lookup_section(skonfig, str)) != NULL)
1037 return s->info.y;
1038
1039 return 0;
1040 }
1041
1042 /*
1043 *
1044 */
xitk_skin_get_label_color(xitk_skin_config_t * skonfig,const char * str)1045 const char *xitk_skin_get_label_color(xitk_skin_config_t *skonfig, const char *str) {
1046 xitk_skin_element_t *s;
1047
1048 if((s = skin_lookup_section(skonfig, str)) != NULL)
1049 return s->info.label_color;
1050
1051 return NULL;
1052 }
1053
1054 /*
1055 *
1056 */
xitk_skin_get_label_color_focus(xitk_skin_config_t * skonfig,const char * str)1057 const char *xitk_skin_get_label_color_focus(xitk_skin_config_t *skonfig, const char *str) {
1058 xitk_skin_element_t *s;
1059
1060 if((s = skin_lookup_section(skonfig, str)) != NULL)
1061 return s->info.label_color_focus;
1062
1063 return NULL;
1064 }
1065
1066 /*
1067 *
1068 */
xitk_skin_get_label_color_click(xitk_skin_config_t * skonfig,const char * str)1069 const char *xitk_skin_get_label_color_click(xitk_skin_config_t *skonfig, const char *str) {
1070 xitk_skin_element_t *s;
1071
1072 if((s = skin_lookup_section(skonfig, str)) != NULL)
1073 return s->info.label_color_click;
1074
1075 return NULL;
1076 }
1077
1078 /*
1079 *
1080 */
xitk_skin_get_label_length(xitk_skin_config_t * skonfig,const char * str)1081 int xitk_skin_get_label_length(xitk_skin_config_t *skonfig, const char *str) {
1082 xitk_skin_element_t *s;
1083
1084 if((s = skin_lookup_section(skonfig, str)) != NULL)
1085 return s->info.label_length;
1086
1087 return 0;
1088 }
1089
1090 /*
1091 *
1092 */
xitk_skin_get_label_animation(xitk_skin_config_t * skonfig,const char * str)1093 int xitk_skin_get_label_animation(xitk_skin_config_t *skonfig, const char *str) {
1094 xitk_skin_element_t *s;
1095
1096 if((s = skin_lookup_section(skonfig, str)) != NULL)
1097 return s->info.label_animation;
1098
1099 return 0;
1100 }
1101
1102 /*
1103 *
1104 */
xitk_skin_get_label_animation_step(xitk_skin_config_t * skonfig,const char * str)1105 int xitk_skin_get_label_animation_step(xitk_skin_config_t *skonfig, const char *str) {
1106 xitk_skin_element_t *s;
1107
1108 if((s = skin_lookup_section(skonfig, str)) != NULL)
1109 return s->info.label_animation_step;
1110
1111 return 1;
1112 }
1113
xitk_skin_get_label_animation_timer(xitk_skin_config_t * skonfig,const char * str)1114 unsigned long xitk_skin_get_label_animation_timer(xitk_skin_config_t *skonfig, const char *str) {
1115 xitk_skin_element_t *s;
1116
1117 if((s = skin_lookup_section(skonfig, str)) != NULL)
1118 return s->info.label_animation_timer;
1119
1120 return 0;
1121 }
1122
1123 /*
1124 *
1125 */
xitk_skin_get_label_fontname(xitk_skin_config_t * skonfig,const char * str)1126 const char *xitk_skin_get_label_fontname(xitk_skin_config_t *skonfig, const char *str) {
1127 xitk_skin_element_t *s;
1128
1129 if((s = skin_lookup_section(skonfig, str)) != NULL)
1130 return s->info.label_fontname;
1131
1132 return NULL;
1133 }
1134
1135 /*
1136 *
1137 */
xitk_skin_get_label_printable(xitk_skin_config_t * skonfig,const char * str)1138 int xitk_skin_get_label_printable(xitk_skin_config_t *skonfig, const char *str) {
1139 xitk_skin_element_t *s;
1140
1141 if((s = skin_lookup_section(skonfig, str)) != NULL)
1142 return s->info.label_printable;
1143
1144 return 1;
1145 }
1146
1147 /*
1148 *
1149 */
xitk_skin_get_label_staticity(xitk_skin_config_t * skonfig,const char * str)1150 int xitk_skin_get_label_staticity(xitk_skin_config_t *skonfig, const char *str) {
1151 xitk_skin_element_t *s;
1152
1153 if((s = skin_lookup_section(skonfig, str)) != NULL)
1154 return s->info.label_staticity;
1155
1156 return 0;
1157 }
1158
1159 /*
1160 *
1161 */
xitk_skin_get_label_alignment(xitk_skin_config_t * skonfig,const char * str)1162 int xitk_skin_get_label_alignment(xitk_skin_config_t *skonfig, const char *str) {
1163 xitk_skin_element_t *s;
1164
1165 if((s = skin_lookup_section(skonfig, str)) != NULL)
1166 return s->info.label_alignment;
1167
1168 return ALIGN_CENTER;
1169 }
1170
1171 /*
1172 *
1173 */
xitk_skin_get_label_skinfont_filename(xitk_skin_config_t * skonfig,const char * str)1174 const char *xitk_skin_get_label_skinfont_filename(xitk_skin_config_t *skonfig, const char *str) {
1175 xitk_skin_element_t *s;
1176
1177 if((s = skin_lookup_section(skonfig, str)) != NULL)
1178 return s->info.label_pixmap_font_name;
1179
1180 return NULL;
1181 }
1182
1183 /*
1184 *
1185 */
xitk_skin_get_skin_filename(xitk_skin_config_t * skonfig,const char * str)1186 const char *xitk_skin_get_skin_filename(xitk_skin_config_t *skonfig, const char *str) {
1187 xitk_skin_element_t *s;
1188
1189 if((s = skin_lookup_section(skonfig, str)) != NULL)
1190 return s->info.pixmap_name;
1191
1192 return NULL;
1193 }
1194
1195 /*
1196 *
1197 */
xitk_skin_get_slider_skin_filename(xitk_skin_config_t * skonfig,const char * str)1198 const char *xitk_skin_get_slider_skin_filename(xitk_skin_config_t *skonfig, const char *str) {
1199 xitk_skin_element_t *s;
1200
1201 if((s = skin_lookup_section(skonfig, str)) != NULL)
1202 if (s->info.slider_type)
1203 return s->info.slider_pixmap_pad_name;
1204
1205 return NULL;
1206 }
1207
1208 /*
1209 *
1210 */
xitk_skin_get_slider_type(xitk_skin_config_t * skonfig,const char * str)1211 int xitk_skin_get_slider_type(xitk_skin_config_t *skonfig, const char *str) {
1212 xitk_skin_element_t *s;
1213
1214 if((s = skin_lookup_section(skonfig, str)) != NULL)
1215 return ((s->info.slider_type) ? s->info.slider_type : XITK_HSLIDER);
1216
1217 return 0;
1218 }
1219
1220 /*
1221 *
1222 */
xitk_skin_get_slider_radius(xitk_skin_config_t * skonfig,const char * str)1223 int xitk_skin_get_slider_radius(xitk_skin_config_t *skonfig, const char *str) {
1224 xitk_skin_element_t *s;
1225
1226 if((s = skin_lookup_section(skonfig, str)) != NULL)
1227 return s->info.slider_radius;
1228
1229 return 0;
1230 }
1231
1232 /*
1233 *
1234 */
xitk_skin_get_animation(xitk_skin_config_t * skonfig)1235 const char *xitk_skin_get_animation(xitk_skin_config_t *skonfig) {
1236 ABORT_IF_NULL(skonfig);
1237
1238 return skonfig->animation;
1239 }
1240
1241 /*
1242 *
1243 */
xitk_skin_get_logo(xitk_skin_config_t * skonfig)1244 const char *xitk_skin_get_logo(xitk_skin_config_t *skonfig) {
1245 ABORT_IF_NULL(skonfig);
1246
1247 return skonfig->logo;
1248 }
1249
1250 /*
1251 *
1252 */
xitk_skin_get_browser_entries(xitk_skin_config_t * skonfig,const char * str)1253 int xitk_skin_get_browser_entries(xitk_skin_config_t *skonfig, const char *str) {
1254 xitk_skin_element_t *s;
1255
1256 if((s = skin_lookup_section(skonfig, str)) != NULL)
1257 return s->info.browser_entries;
1258
1259 return -1;
1260 }
1261
1262 /*
1263 *
1264 */
xitk_skin_get_image(xitk_skin_config_t * skonfig,const char * str)1265 xitk_image_t *xitk_skin_get_image(xitk_skin_config_t *skonfig, const char *str) {
1266 ABORT_IF_NULL(skonfig);
1267
1268 return skin_load_img (skonfig, str, NULL);
1269 }
1270
xitk_skin_get_max_buttons(xitk_skin_config_t * skonfig,const char * str)1271 int xitk_skin_get_max_buttons(xitk_skin_config_t *skonfig, const char *str) {
1272 xitk_skin_element_t *s;
1273
1274 if((s = skin_lookup_section(skonfig, str)) != NULL)
1275 return s->info.max_buttons;
1276
1277 return 0;
1278 }
1279
xitk_skin_get_info(xitk_skin_config_t * skin,const char * element_name)1280 const xitk_skin_element_info_t *xitk_skin_get_info (xitk_skin_config_t *skin, const char *element_name) {
1281 xitk_skin_element_t *s;
1282
1283 if (!skin || !element_name)
1284 return NULL;
1285
1286 s = skin_lookup_section (skin, element_name);
1287 if (!s)
1288 return NULL;
1289
1290 return &s->info;
1291 }
1292
1293 /*
1294 *
1295 */
xitk_skin_lock(xitk_skin_config_t * skonfig)1296 void xitk_skin_lock(xitk_skin_config_t *skonfig) {
1297 if (skonfig)
1298 pthread_mutex_lock (&skonfig->skin_mutex);
1299 }
1300
1301 /*
1302 *
1303 */
xitk_skin_unlock(xitk_skin_config_t * skonfig)1304 void xitk_skin_unlock(xitk_skin_config_t *skonfig) {
1305 if (skonfig)
1306 pthread_mutex_unlock (&skonfig->skin_mutex);
1307 }
1308