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", &section[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