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 <pthread.h>
29 #include <unistd.h>
30 
31 #include "_xitk.h"
32 
_strlcpy(char * d,const char * s,size_t l)33 static size_t _strlcpy (char *d, const char *s, size_t l) {
34   size_t n;
35   if (!s)
36     s = "";
37   n = strlen (s);
38   if (l > n + 1)
39     l = n + 1;
40   memcpy (d, s, l);
41   d[l - 1] = 0;
42   return n;
43 }
44 
_find_pix_font_char(xitk_pix_font_t * pf,xitk_point_t * found,int this_char)45 static int _find_pix_font_char (xitk_pix_font_t *pf, xitk_point_t *found, int this_char) {
46   int range, n = 0;
47 
48   for (range = 0; pf->unicode_ranges[range].first > 0; range++) {
49     if ((this_char >= pf->unicode_ranges[range].first) && (this_char <= pf->unicode_ranges[range].last))
50       break;
51     n += pf->unicode_ranges[range].last - pf->unicode_ranges[range].first + 1;
52   }
53 
54   if (pf->unicode_ranges[range].first <= 0) {
55     *found = pf->unknown;
56     return 0;
57   }
58 
59   n += this_char - pf->unicode_ranges[range].first;
60   found->x = (n % pf->chars_per_row) * pf->char_width;
61   found->y = (n / pf->chars_per_row) * pf->char_height;
62   return 1;
63 }
64 
_create_label_pixmap(xitk_widget_t * w)65 static void _create_label_pixmap(xitk_widget_t *w) {
66   label_private_data_t  *private_data = (label_private_data_t *) w->private_data;
67   xitk_image_t          *font         = (xitk_image_t *) private_data->font;
68   xitk_pix_font_t       *pix_font;
69   int                    pixwidth;
70   int                    x_dest;
71   int                    len, anim_add = 0;
72   uint16_t               buf[2048];
73 
74   private_data->anim_offset = 0;
75 
76   if (!font->pix_font) {
77     /* old style */
78     xitk_image_set_pix_font (font, "");
79     if (!font->pix_font)
80       return;
81   }
82   pix_font = font->pix_font;
83 
84   {
85     const uint8_t *p = (const uint8_t *)private_data->label;
86     uint16_t *q = buf, *e = buf + sizeof (buf) / sizeof (buf[0]) - 1;
87     while (*p && (q < e)) {
88       if (!(p[0] & 0x80)) {
89         *q++ = p[0];
90         p += 1;
91       } else if (((p[0] & 0xe0) == 0xc0) && ((p[1] & 0xc0) == 0x80)) {
92         *q++ = ((uint32_t)(p[0] & 0x1f) << 6) | (p[1] & 0x3f);
93         p += 2;
94       } else if (((p[0] & 0xf0) == 0xe0) && ((p[1] & 0xc0) == 0x80) && ((p[2] & 0xc0) == 0x80)) {
95         *q++ = ((uint32_t)(p[0] & 0x0f) << 12) | ((uint32_t)(p[1] & 0x3f) << 6) | (p[2] & 0x3f);
96         p += 3;
97       } else {
98         *q++ = p[0];
99         p += 1;
100       }
101     }
102     *q = 0;
103     private_data->label_len = len = q - buf;
104   }
105 
106   if (private_data->animation && (len > private_data->length))
107     anim_add = private_data->length + 5;
108 
109   /* reuse or reallocate pixmap */
110   pixwidth = len + anim_add;
111   if (pixwidth < private_data->length)
112     pixwidth = private_data->length;
113   if (pixwidth < 1)
114     pixwidth = 1;
115   pixwidth *= pix_font->char_width;
116   if (private_data->labelpix) {
117     if ((private_data->labelpix->width != pixwidth)
118       || (private_data->labelpix->height != pix_font->char_height)) {
119       xitk_image_destroy_xitk_pixmap (private_data->labelpix);
120       private_data->labelpix = NULL;
121     }
122   }
123   if (!private_data->labelpix) {
124     private_data->labelpix = xitk_image_create_xitk_pixmap (private_data->imlibdata, pixwidth,
125       pix_font->char_height);
126 #if 0
127     printf ("xine.label: new pixmap %d:%d -> %d:%d for \"%s\"\n", pixwidth, pix_font->char_height,
128       private_data->labelpix->width, private_data->labelpix->height, private_data->label);
129 #endif
130   }
131   x_dest = 0;
132 
133   /* [foo] */
134   {
135     const uint16_t *p = buf;
136     XLOCK (private_data->imlibdata->x.x_lock_display, private_data->imlibdata->x.disp);
137     while (*p) {
138       xitk_point_t pt;
139       _find_pix_font_char (font->pix_font, &pt, *p);
140       p++;
141       XCopyArea (private_data->imlibdata->x.disp, font->image->pixmap,
142         private_data->labelpix->pixmap, private_data->labelpix->gc, pt.x, pt.y,
143         pix_font->char_width, pix_font->char_height, x_dest, 0);
144       x_dest += pix_font->char_width;
145     }
146     XUNLOCK (private_data->imlibdata->x.x_unlock_display, private_data->imlibdata->x.disp);
147   }
148   /* foo[ *** fo] */
149   if (anim_add) {
150     XLOCK (private_data->imlibdata->x.x_lock_display, private_data->imlibdata->x.disp);
151     XCopyArea (private_data->imlibdata->x.disp, font->image->pixmap,
152       private_data->labelpix->pixmap, private_data->labelpix->gc,
153       pix_font->space.x, pix_font->space.y,
154       pix_font->char_width, pix_font->char_height, x_dest, 0);
155     x_dest += pix_font->char_width;
156     XCopyArea (private_data->imlibdata->x.disp, font->image->pixmap,
157       private_data->labelpix->pixmap, private_data->labelpix->gc,
158       pix_font->asterisk.x, pix_font->asterisk.y,
159       pix_font->char_width, pix_font->char_height, x_dest, 0);
160     x_dest += pix_font->char_width;
161     XCopyArea (private_data->imlibdata->x.disp, font->image->pixmap,
162       private_data->labelpix->pixmap, private_data->labelpix->gc,
163       pix_font->asterisk.x, pix_font->asterisk.y,
164       pix_font->char_width, pix_font->char_height, x_dest, 0);
165     x_dest += pix_font->char_width;
166     XCopyArea (private_data->imlibdata->x.disp, font->image->pixmap,
167       private_data->labelpix->pixmap, private_data->labelpix->gc,
168       pix_font->asterisk.x, pix_font->asterisk.y,
169       pix_font->char_width, pix_font->char_height, x_dest, 0);
170     x_dest += pix_font->char_width;
171     XCopyArea (private_data->imlibdata->x.disp, font->image->pixmap,
172       private_data->labelpix->pixmap, private_data->labelpix->gc,
173       pix_font->space.x, pix_font->space.y,
174       pix_font->char_width, pix_font->char_height, x_dest, 0);
175     x_dest += pix_font->char_width;
176     XCopyArea (private_data->imlibdata->x.disp, private_data->labelpix->pixmap,
177       private_data->labelpix->pixmap, private_data->labelpix->gc, 0, 0,
178       pixwidth - x_dest, pix_font->char_height, x_dest, 0);
179     XUNLOCK (private_data->imlibdata->x.x_unlock_display, private_data->imlibdata->x.disp);
180     x_dest = pixwidth;
181   }
182 
183   /* fill gap with spaces */
184   if (x_dest < pixwidth) {
185     XLOCK (private_data->imlibdata->x.x_lock_display, private_data->imlibdata->x.disp);
186     do {
187       XCopyArea (private_data->imlibdata->x.disp, font->image->pixmap,
188         private_data->labelpix->pixmap, private_data->labelpix->gc,
189         pix_font->space.x, pix_font->space.y,
190         pix_font->char_width, pix_font->char_height, x_dest, 0);
191       x_dest += pix_font->char_width;
192     } while (x_dest < pixwidth);
193     XUNLOCK (private_data->imlibdata->x.x_unlock_display, private_data->imlibdata->x.disp);
194   }
195 }
196 
197 /*
198  *
199  */
notify_destroy(xitk_widget_t * w)200 static void notify_destroy(xitk_widget_t *w) {
201 
202   if(w && ((w->type & WIDGET_TYPE_MASK) == WIDGET_TYPE_LABEL)) {
203     label_private_data_t *private_data = (label_private_data_t *) w->private_data;
204 
205     pthread_mutex_lock (&private_data->change_mutex);
206 
207     if(private_data->anim_running) {
208       void *dummy;
209 
210       private_data->anim_running = 0;
211       pthread_mutex_unlock (&private_data->change_mutex);
212       pthread_join (private_data->anim_thread, &dummy);
213       pthread_mutex_lock (&private_data->change_mutex);
214     }
215 
216     if (private_data->labelpix) {
217       xitk_image_destroy_xitk_pixmap(private_data->labelpix);
218       private_data->labelpix = NULL;
219     }
220 
221     if (!(private_data->skin_element_name[0] & ~1))
222       xitk_image_free_image(private_data->imlibdata, &(private_data->font));
223 
224     XITK_FREE(private_data->label);
225     XITK_FREE(private_data->fontname);
226 
227     pthread_mutex_unlock (&private_data->change_mutex);
228     pthread_mutex_destroy (&private_data->change_mutex);
229 
230     XITK_FREE(private_data);
231   }
232 }
233 
234 /*
235  *
236  */
get_skin(xitk_widget_t * w,int sk)237 static xitk_image_t *get_skin(xitk_widget_t *w, int sk) {
238 
239   if(w && ((w->type & WIDGET_TYPE_MASK) == WIDGET_TYPE_LABEL)) {
240     label_private_data_t *private_data = (label_private_data_t *) w->private_data;
241 
242     if(sk == FOREGROUND_SKIN && private_data->font) {
243       return private_data->font;
244     }
245   }
246 
247   return NULL;
248 }
249 
250 /*
251  *
252  */
xitk_label_get_label(xitk_widget_t * w)253 const char *xitk_label_get_label(xitk_widget_t *w) {
254 
255   if(w && ((w->type & WIDGET_TYPE_MASK) == WIDGET_TYPE_LABEL)) {
256       label_private_data_t *private_data = (label_private_data_t *) w->private_data;
257     return private_data->label;
258   }
259 
260   return NULL;
261 }
262 
263 /*
264  *
265  */
paint_label(xitk_widget_t * w)266 static void paint_label(xitk_widget_t *w) {
267 
268   if (w && (((w->type & WIDGET_TYPE_MASK) == WIDGET_TYPE_LABEL) && w->visible == 1)) {
269     label_private_data_t  *private_data = (label_private_data_t *) w->private_data;
270     xitk_image_t          *font = (xitk_image_t *) private_data->font;
271 
272     if(!private_data->label_visible)
273       return;
274 
275     /* non skinable widget */
276     if (!(private_data->skin_element_name[0] & ~1)) {
277       xitk_font_t   *fs = NULL;
278       int            lbear, rbear, wid, asc, des;
279       xitk_image_t  *bg;
280 
281       /* Clean old */
282       XLOCK (private_data->imlibdata->x.x_lock_display, private_data->imlibdata->x.disp);
283       XCopyArea (private_data->imlibdata->x.disp, font->image->pixmap, w->wl->win, font->image->gc,
284 		 0, 0, private_data->font->width, font->height, w->x, w->y);
285       XUNLOCK (private_data->imlibdata->x.x_unlock_display, private_data->imlibdata->x.disp);
286 
287       fs = xitk_font_load_font(private_data->imlibdata->x.disp, private_data->fontname);
288       xitk_font_set_font(fs, private_data->font->image->gc);
289       xitk_font_string_extent (fs, private_data->label, &lbear, &rbear, &wid, &asc, &des);
290 
291       bg = xitk_image_create_image(private_data->imlibdata, w->width, w->height);
292 
293       XLOCK (private_data->imlibdata->x.x_lock_display, private_data->imlibdata->x.disp);
294       XCopyArea (private_data->imlibdata->x.disp, font->image->pixmap, bg->image->pixmap,
295 		 font->image->gc,
296 		 0, 0, private_data->font->width, private_data->font->height, 0, 0);
297       XSetForeground(private_data->imlibdata->x.disp, font->image->gc,
298 		     xitk_get_pixel_color_black(private_data->imlibdata));
299       xitk_font_draw_string(fs, bg->image->pixmap, font->image->gc,
300 		  2, ((private_data->font->height + asc + des)>>1) - des,
301 		  private_data->label, private_data->label_len);
302       XCopyArea (private_data->imlibdata->x.disp, bg->image->pixmap, w->wl->win,
303 		 font->image->gc, 0, 0, font->width, font->height, w->x, w->y);
304       XUNLOCK (private_data->imlibdata->x.x_unlock_display, private_data->imlibdata->x.disp);
305 
306       xitk_image_free_image(private_data->imlibdata, &bg);
307 
308       xitk_font_unload_font(fs);
309       return;
310     }
311     else if (private_data->pix_font) {
312       int width = private_data->pix_font->char_width * private_data->length;
313 
314       XLOCK (private_data->imlibdata->x.x_lock_display, private_data->imlibdata->x.disp);
315       XCopyArea (private_data->imlibdata->x.disp,
316         private_data->labelpix->pixmap, w->wl->win, font->image->gc,
317         private_data->anim_offset, 0, width, private_data->pix_font->char_height, w->x, w->y);
318 
319       if (private_data->anim_running)
320         XSync (private_data->imlibdata->x.disp, False);
321       XUNLOCK (private_data->imlibdata->x.x_unlock_display, private_data->imlibdata->x.disp);
322 
323     }
324   }
325 }
326 
327 /*
328  *
329  */
xitk_label_animation_loop(void * data)330 static void *xitk_label_animation_loop (void *data) {
331   label_private_data_t *private_data = (label_private_data_t *)data;
332 
333   pthread_mutex_lock (&private_data->change_mutex);
334 
335   while (1) {
336     xitk_widget_t *w = private_data->lWidget;
337     unsigned long t_anim;
338 
339     if (!w->running || (private_data->anim_running != 1))
340       break;
341     if ((w->visible == 1) && private_data->pix_font) {
342       private_data->anim_offset += private_data->anim_step;
343       if (private_data->anim_offset >= (private_data->pix_font->char_width * ((int)private_data->label_len + 5)))
344         private_data->anim_offset = 0;
345       paint_label (private_data->lWidget);
346     }
347     t_anim = private_data->anim_timer;
348     pthread_mutex_unlock (&private_data->change_mutex);
349     xitk_usec_sleep (t_anim);
350     pthread_mutex_lock (&private_data->change_mutex);
351   }
352   private_data->anim_running = 0;
353   pthread_mutex_unlock (&private_data->change_mutex);
354 
355   return NULL;
356 }
357 
358 /*
359  *
360  */
label_setup_label(xitk_widget_t * w,const char * new_label,int paint)361 static void label_setup_label(xitk_widget_t *w, const char *new_label, int paint) {
362   label_private_data_t *private_data = (label_private_data_t *) w->private_data;
363 
364   /* Inform animation thread to not paint the label */
365   pthread_mutex_lock (&private_data->change_mutex);
366 
367   if (new_label != private_data->label) {
368     size_t new_len;
369 
370     if (!new_label) {
371       new_label = "";
372       new_len = 0;
373     } else {
374       new_len = strlen (new_label);
375     }
376     if (private_data->label) {
377       if (private_data->label_len != new_len) {
378         free (private_data->label);
379         private_data->label = NULL;
380       }
381     }
382     if (!private_data->label)
383       private_data->label = xitk_xmalloc (new_len + 1);
384     if (private_data->label)
385       memcpy (private_data->label, new_label, new_len + 1);
386     private_data->label_len = new_len;
387   }
388 
389   if (private_data->skin_element_name[0] & ~1) {
390     _create_label_pixmap(w);
391   } else {
392     if (private_data->labelpix) {
393       xitk_image_destroy_xitk_pixmap (private_data->labelpix);
394       private_data->labelpix = NULL;
395     }
396     private_data->anim_offset = 0;
397   }
398 
399   if (private_data->animation && ((int)private_data->label_len > private_data->length)) {
400     if (!private_data->anim_running) {
401       pthread_attr_t       pth_attrs;
402 #if defined(_POSIX_THREAD_PRIORITY_SCHEDULING) && (_POSIX_THREAD_PRIORITY_SCHEDULING > 0)
403       struct sched_param   pth_params;
404 #endif
405       int r;
406 
407       private_data->anim_running = 1;
408       pthread_attr_init (&pth_attrs);
409 #if defined(_POSIX_THREAD_PRIORITY_SCHEDULING) && (_POSIX_THREAD_PRIORITY_SCHEDULING > 0)
410       pthread_attr_getschedparam(&pth_attrs, &pth_params);
411       pth_params.sched_priority = sched_get_priority_min(SCHED_OTHER);
412       pthread_attr_setschedparam(&pth_attrs, &pth_params);
413 #endif
414       r = pthread_create (&private_data->anim_thread, &pth_attrs, xitk_label_animation_loop, (void *)private_data);
415       pthread_attr_destroy (&pth_attrs);
416       if (r)
417         private_data->anim_running = 0;
418     } else {
419       private_data->anim_running = 1;
420     }
421   } else {
422     if (private_data->anim_running) {
423       /* panel mrl animation has a long interval of 0.5s.
424        * better not wait for that, as it may interfere with
425        * gapleess stream switch. */
426       private_data->anim_running = 2;
427     }
428   }
429   if (paint)
430     paint_label (w);
431   pthread_mutex_unlock (&private_data->change_mutex);
432 }
433 
434 /*
435  *
436  */
notify_change_skin(xitk_widget_t * w,xitk_skin_config_t * skonfig)437 static void notify_change_skin(xitk_widget_t *w, xitk_skin_config_t *skonfig) {
438 
439   if(w && ((w->type & WIDGET_TYPE_MASK) == WIDGET_TYPE_LABEL)) {
440     label_private_data_t *private_data = (label_private_data_t *) w->private_data;
441 
442     if (private_data->skin_element_name[0] & ~1) {
443       const xitk_skin_element_info_t *info;
444 
445       xitk_skin_lock(skonfig);
446       info = xitk_skin_get_info (skonfig, private_data->skin_element_name);
447       if (info) {
448         private_data->font          = info->label_pixmap_font_img;
449         private_data->pix_font      = private_data->font->pix_font;
450         if (!private_data->pix_font) {
451           xitk_image_set_pix_font (private_data->font, "");
452           private_data->pix_font    = private_data->font->pix_font;
453         }
454         private_data->length        = info->label_length;
455         private_data->animation     = info->label_animation;
456         private_data->anim_step     = info->label_animation_step;
457         private_data->anim_timer    = info->label_animation_timer;
458         if (private_data->anim_timer <= 0)
459           private_data->anim_timer = xitk_get_timer_label_animation ();
460         private_data->label_visible = info->label_printable;
461         w->x                        = info->x;
462         w->y                        = info->y;
463         if (private_data->pix_font) {
464           w->width                  = private_data->pix_font->char_width * private_data->length;
465           w->height                 = private_data->pix_font->char_height;
466         }
467         w->visible                  = info->visibility ? 1 : -1;
468         w->enable                   = info->enability;
469         label_setup_label (w, private_data->label, 1);
470       }
471 
472       xitk_skin_unlock(skonfig);
473       xitk_set_widget_pos (w, w->x, w->y);
474     }
475   }
476 }
477 
478 /*
479  *
480  */
xitk_label_change_label(xitk_widget_t * w,const char * newlabel)481 int xitk_label_change_label(xitk_widget_t *w, const char *newlabel) {
482 
483   if(w && ((w->type & WIDGET_TYPE_MASK) == WIDGET_TYPE_LABEL)) {
484     label_private_data_t *private_data = (label_private_data_t *) w->private_data;
485 
486     if(!newlabel || !private_data->label ||
487        (newlabel && (strcmp(private_data->label, newlabel))))
488       label_setup_label (w, newlabel, 1);
489     return 1;
490   }
491 
492   return 0;
493 }
494 
495 /*
496  *
497  */
notify_click_label(xitk_widget_t * w,int button,int bUp,int x,int y)498 static int notify_click_label(xitk_widget_t *w, int button, int bUp, int x, int y) {
499   int  ret = 0;
500 
501   (void)x;
502   (void)y;
503   if (w && ((w->type & WIDGET_TYPE_MASK) == WIDGET_TYPE_LABEL)) {
504     if(button == Button1) {
505       label_private_data_t *private_data = (label_private_data_t *) w->private_data;
506 
507       if(private_data->callback) {
508 	if(bUp)
509 	  private_data->callback(private_data->lWidget, private_data->userdata);
510 	ret = 1;
511       }
512     }
513   }
514 
515   return ret;
516 }
517 
notify_event(xitk_widget_t * w,widget_event_t * event,widget_event_result_t * result)518 static int notify_event(xitk_widget_t *w, widget_event_t *event, widget_event_result_t *result) {
519   int retval = 0;
520 
521   switch(event->type) {
522   case WIDGET_EVENT_PAINT:
523     {
524       if(w && (((w->type & WIDGET_TYPE_MASK) == WIDGET_TYPE_LABEL))) {
525 	label_private_data_t  *private_data = (label_private_data_t *) w->private_data;
526 
527 	if(!pthread_mutex_trylock(&private_data->change_mutex)) {
528 	  paint_label(w);
529 	  pthread_mutex_unlock(&private_data->change_mutex);
530 	}
531 
532       }
533     }
534     break;
535   case WIDGET_EVENT_CLICK:
536     result->value = notify_click_label(w, event->button,
537 				       event->button_pressed, event->x, event->y);
538     retval = 1;
539     break;
540   case WIDGET_EVENT_CHANGE_SKIN:
541     notify_change_skin(w, event->skonfig);
542     break;
543   case WIDGET_EVENT_DESTROY:
544     notify_destroy(w);
545     break;
546   case WIDGET_EVENT_GET_SKIN:
547     if(result) {
548       result->image = get_skin(w, event->skin_layer);
549       retval = 1;
550     }
551     break;
552   }
553 
554   return retval;
555 }
556 
557 /*
558  *
559  */
_xitk_label_create(xitk_widget_list_t * wl,const xitk_label_widget_t * l,const xitk_skin_element_info_t * info)560 static xitk_widget_t *_xitk_label_create (xitk_widget_list_t *wl, const xitk_label_widget_t *l,
561   const xitk_skin_element_info_t *info) {
562   xitk_widget_t          *mywidget;
563   label_private_data_t   *private_data;
564 
565   mywidget = (xitk_widget_t *) xitk_xmalloc(sizeof(xitk_widget_t));
566   if (!mywidget)
567     return NULL;
568 
569   private_data = (label_private_data_t *) xitk_xmalloc(sizeof(label_private_data_t));
570   if (!private_data) {
571     free (mywidget);
572     return NULL;
573   }
574 
575   private_data->imlibdata = l->imlibdata;
576   private_data->callback  = l->callback;
577   private_data->userdata  = l->userdata;
578 
579   private_data->lWidget = mywidget;
580 
581   private_data->font = info->label_pixmap_font_img;
582 
583   if (info->label_pixmap_font_name && (info->label_pixmap_font_name[0] == '\x01') && (info->label_pixmap_font_name[0] == 0)) {
584     private_data->skin_element_name[0] = '\x01';
585     private_data->skin_element_name[1] = 0;
586   } else {
587     _strlcpy (private_data->skin_element_name, l->skin_element_name, sizeof (private_data->skin_element_name));
588   }
589   if (!(private_data->skin_element_name[0] & ~1)) {
590     mywidget->height            = info->label_pixmap_font_img->height;
591     mywidget->width             =
592     private_data->length        = info->label_pixmap_font_img->width;
593     private_data->fontname      = strdup (info->label_fontname);
594     private_data->pix_font      = NULL;
595     private_data->animation     = 0;
596     private_data->anim_step     = 1;
597     private_data->anim_timer    = xitk_get_timer_label_animation ();
598     private_data->label_visible = 1;
599   } else {
600     if (!private_data->font) {
601       /* wrong pixmmap name in skin? */
602       free (private_data);
603       free (mywidget);
604       return NULL;
605     }
606     private_data->length        = info->label_length;
607     private_data->fontname      = NULL;
608     private_data->pix_font      = private_data->font->pix_font;
609     if (!private_data->pix_font) {
610       xitk_image_set_pix_font (private_data->font, "");
611       private_data->pix_font    = private_data->font->pix_font;
612     }
613     private_data->animation     = info->label_animation;
614     private_data->anim_step     = info->label_animation_step;
615     private_data->anim_timer    = info->label_animation_timer;
616     if (private_data->anim_timer <= 0)
617       private_data->anim_timer = xitk_get_timer_label_animation ();
618     private_data->label_visible = info->label_printable;
619     if (private_data->pix_font) {
620       mywidget->width           = private_data->pix_font->char_width * private_data->length;
621       mywidget->height          = private_data->pix_font->char_height;
622     }
623   }
624   private_data->anim_running  = 0;
625   private_data->label         = NULL;
626   private_data->labelpix      = NULL;
627 
628   pthread_mutex_init (&private_data->change_mutex, NULL);
629 
630   mywidget->private_data       = private_data;
631 
632   mywidget->wl                 = wl;
633 
634   mywidget->enable             = info->enability;
635   mywidget->visible            = info->visibility;
636   mywidget->imlibdata          = private_data->imlibdata;
637   mywidget->x                  = info->x;
638   mywidget->y                  = info->y;
639   mywidget->have_focus         = FOCUS_LOST;
640   mywidget->running            = 1;
641 
642   mywidget->type               = WIDGET_TYPE_LABEL | WIDGET_CLICKABLE | WIDGET_KEYABLE;
643   mywidget->event              = notify_event;
644   mywidget->tips_timeout       = 0;
645   mywidget->tips_string        = NULL;
646 
647   label_setup_label(mywidget, l->label, 0);
648 
649   return mywidget;
650 }
651 
652 /*
653  *
654  */
xitk_label_create(xitk_widget_list_t * wl,xitk_skin_config_t * skonfig,const xitk_label_widget_t * l)655 xitk_widget_t *xitk_label_create (xitk_widget_list_t *wl, xitk_skin_config_t *skonfig,
656   const xitk_label_widget_t *l) {
657   const xitk_skin_element_info_t *pinfo;
658   xitk_skin_element_info_t info;
659 
660   XITK_CHECK_CONSTITENCY (l);
661   pinfo = xitk_skin_get_info (skonfig, l->skin_element_name);
662   if (pinfo) {
663     if (!pinfo->visibility) {
664       info = *pinfo;
665       info.visibility = 1;
666       pinfo = &info;
667     }
668   } else {
669     memset (&info, 0, sizeof (info));
670     info.visibility = -1;
671     pinfo = &info;
672   }
673 
674   return _xitk_label_create (wl, l, pinfo);
675 }
676 
677 /*
678  *
679  */
xitk_noskin_label_create(xitk_widget_list_t * wl,const xitk_label_widget_t * l,int x,int y,int width,int height,const char * fontname)680 xitk_widget_t *xitk_noskin_label_create (xitk_widget_list_t *wl,
681   const xitk_label_widget_t *l, int x, int y, int width, int height,
682   const char *fontname) {
683   xitk_skin_element_info_t info;
684 
685   XITK_CHECK_CONSTITENCY (l);
686   info.x                 = x;
687   info.y                 = y;
688   info.label_printable   = 1;
689   info.label_staticity   = 0;
690   info.visibility        = 0;
691   info.enability         = 0;
692   info.label_fontname    = (char *)fontname;
693   info.label_pixmap_font_name  = (char *)"\x01";
694   info.label_pixmap_font_img   = xitk_image_create_image (l->imlibdata, width, height);
695   if (info.label_pixmap_font_img)
696     draw_flat (l->imlibdata, info.label_pixmap_font_img->image, width, height);
697 
698   return _xitk_label_create (wl, l, &info);
699 }
700 
701