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 
29 #include "_xitk.h"
30 
31 #define CLICK     1
32 #define FOCUS     2
33 #define NORMAL    3
34 
_strlcpy(char * d,const char * s,size_t l)35 static size_t _strlcpy (char *d, const char *s, size_t l) {
36   size_t n;
37   if (!s)
38     s = "";
39   n = strlen (s);
40   if (l > n + 1)
41     l = n + 1;
42   memcpy (d, s, l);
43   d[l - 1] = 0;
44   return n;
45 }
46 
_set_label(lbutton_private_data_t * private_data,const char * label)47 static void _set_label (lbutton_private_data_t *private_data, const char *label) {
48   size_t n;
49   if (private_data->label != private_data->lbuf)
50     free (private_data->label);
51   if (!label)
52     label = "";
53   n = strlen (label) + 1;
54   if (n <= sizeof (private_data->lbuf)) {
55     memcpy (private_data->lbuf, label, n);
56     private_data->label = private_data->lbuf;
57   } else {
58     private_data->label = strdup (label);
59   }
60 }
61 
62 /*
63  *
64  */
notify_destroy(xitk_widget_t * w)65 static void notify_destroy(xitk_widget_t *w) {
66   lbutton_private_data_t *private_data;
67 
68   if(w && ((w->type & WIDGET_TYPE_MASK) == WIDGET_TYPE_LABELBUTTON)) {
69     private_data = (lbutton_private_data_t *) w->private_data;
70 
71     if (private_data->skin_element_name[0] == '\x01')
72       xitk_image_free_image(private_data->imlibdata, &(private_data->skin));
73 
74     if (private_data->label != private_data->lbuf) {
75       XITK_FREE (private_data->label);
76     }
77     XITK_FREE(private_data->shortcut_label);
78     XITK_FREE(private_data->shortcut_font);
79     XITK_FREE(private_data->fontname);
80     XITK_FREE(private_data);
81   }
82 }
83 
84 /*
85  *
86  */
get_skin(xitk_widget_t * w,int sk)87 static xitk_image_t *get_skin(xitk_widget_t *w, int sk) {
88   lbutton_private_data_t *private_data;
89 
90   if(w && ((w->type & WIDGET_TYPE_MASK) == WIDGET_TYPE_LABELBUTTON)) {
91     private_data = (lbutton_private_data_t *) w->private_data;
92 
93     if(sk == FOREGROUND_SKIN && private_data->skin) {
94       return private_data->skin;
95     }
96   }
97 
98   return NULL;
99 }
100 
101 /*
102  *
103  */
notify_inside(xitk_widget_t * w,int x,int y)104 static int notify_inside(xitk_widget_t *w, int x, int y) {
105   lbutton_private_data_t *private_data;
106 
107   if (w && ((w->type & WIDGET_TYPE_MASK) == WIDGET_TYPE_LABELBUTTON)) {
108     private_data = (lbutton_private_data_t *) w->private_data;
109 
110     if(w->visible == 1) {
111       xitk_image_t *skin = private_data->skin;
112 
113       if(skin->mask)
114 	return xitk_is_cursor_out_mask(private_data->imlibdata->x.disp, w, skin->mask->pixmap, x, y);
115     }
116     else
117       return 0;
118   }
119 
120   return 1;
121 }
122 
123 /*
124  * Draw the string in pixmap pix, then return it
125  */
create_labelofbutton(xitk_widget_t * lb,Window win,GC gc,Pixmap pix,int xsize,int ysize,char * label,char * shortcut_label,int shortcut_pos,int state)126 static void create_labelofbutton(xitk_widget_t *lb,
127 				 Window win, GC gc, Pixmap pix,
128 				 int xsize, int ysize,
129 				 char *label, char *shortcut_label, int shortcut_pos, int state) {
130   lbutton_private_data_t  *private_data = (lbutton_private_data_t *) lb->private_data;
131   xitk_font_t             *fs = NULL;
132   int                      lbear, rbear, width, asc, des;
133   int                      xoff = 0, yoff = 0, DefaultColor = -1;
134   unsigned int             fg = 0;
135   unsigned int             origin = 0;
136   XColor                   xcolor;
137   xitk_color_names_t      *color = NULL;
138 
139   xcolor.flags = DoRed|DoBlue|DoGreen;
140 
141   /* Try to load font */
142   if(private_data->fontname)
143     fs = xitk_font_load_font(private_data->imlibdata->x.disp, private_data->fontname);
144 
145   if(fs == NULL)
146     fs = xitk_font_load_font(private_data->imlibdata->x.disp, xitk_get_system_font());
147 
148   if(fs == NULL)
149     XITK_DIE("%s()@%d: xitk_font_load_font() failed. Exiting\n", __FUNCTION__, __LINE__);
150 
151   xitk_font_set_font(fs, gc);
152   xitk_font_string_extent(fs, (label && strlen(label)) ? label : "Button", &lbear, &rbear, &width, &asc, &des);
153 
154   if((state == CLICK) && (private_data->label_static == 0)) {
155     xoff = -4;
156     yoff = 1;
157   }
158 
159   if ((private_data->skin_element_name[0] & ~1)
160     || (!(private_data->skin_element_name[0] & ~1) && ((fg = xitk_get_black_color()) == (unsigned int)-1))) {
161 
162     /*  Some colors configurations */
163     switch(state) {
164     case CLICK:
165       if(!strcasecmp(private_data->clickcolor, "Default")) {
166 	DefaultColor = 255;
167       }
168       else {
169 	color = xitk_get_color_name(private_data->clickcolor);
170       }
171       break;
172 
173     case FOCUS:
174       if(!strcasecmp(private_data->focuscolor, "Default")) {
175 	DefaultColor = 0;
176       }
177       else {
178 	color = xitk_get_color_name(private_data->focuscolor);
179       }
180       break;
181 
182     case NORMAL:
183       if(!strcasecmp(private_data->normcolor, "Default")) {
184 	DefaultColor = 0;
185       }
186       else {
187 	color = xitk_get_color_name(private_data->normcolor);
188       }
189       break;
190     }
191 
192     if(color == NULL || DefaultColor != -1) {
193       xcolor.red = xcolor.blue = xcolor.green = DefaultColor<<8;
194     }
195     else {
196       xcolor.red = color->red<<8;
197       xcolor.blue = color->blue<<8;
198       xcolor.green = color->green<<8;
199     }
200 
201     XLOCK (private_data->imlibdata->x.x_lock_display, private_data->imlibdata->x.disp);
202     XAllocColor(private_data->imlibdata->x.disp,
203     Imlib_get_colormap(private_data->imlibdata), &xcolor);
204     XUNLOCK (private_data->imlibdata->x.x_unlock_display, private_data->imlibdata->x.disp);
205 
206     fg = xcolor.pixel;
207   }
208 
209   XLOCK (private_data->imlibdata->x.x_lock_display, private_data->imlibdata->x.disp);
210   XSetForeground(private_data->imlibdata->x.disp, gc, fg);
211   XUNLOCK (private_data->imlibdata->x.x_unlock_display, private_data->imlibdata->x.disp);
212 
213   origin = ((ysize+asc+des+yoff)>>1)-des;
214 
215   /*  Put text in the right place */
216   if(private_data->align == ALIGN_CENTER) {
217     xitk_font_draw_string(fs, pix, gc,
218 			  ((xsize-(width+xoff))>>1) + private_data->label_offset,
219 			  origin, label, strlen(label));
220   }
221   else if(private_data->align == ALIGN_LEFT) {
222     xitk_font_draw_string(fs, pix, gc,
223 			  (((state != CLICK) ? 1 : 5)) + private_data->label_offset,
224 			  origin, label, strlen(label));
225 
226     /* shortcut is only permited if alignement is set to left */
227     if(strlen(shortcut_label) && shortcut_pos >= 0) {
228       xitk_font_t *short_font;
229       if (private_data->shortcut_font)
230 	short_font = xitk_font_load_font(private_data->imlibdata->x.disp, private_data->shortcut_font);
231       else
232         short_font = fs;
233       xitk_font_draw_string(short_font, pix, gc,
234 			    (((state != CLICK) ? 1 : 5)) + shortcut_pos,
235 			    origin, shortcut_label, strlen(shortcut_label));
236       if (short_font != fs)
237 	xitk_font_unload_font(short_font);
238     }
239 
240   }
241   else if(private_data->align == ALIGN_RIGHT) {
242     xitk_font_draw_string(fs, pix, gc,
243 			  (xsize - (width + ((state != CLICK) ? 5 : 1))) + private_data->label_offset,
244 			  origin, label, strlen(label));
245   }
246 
247   xitk_font_unload_font(fs);
248 
249   if(color)
250     xitk_free_color_name(color);
251 }
252 
253 /*
254  * Paint the button with correct background pixmap
255  */
paint_labelbutton(xitk_widget_t * w)256 static void paint_labelbutton (xitk_widget_t *w) {
257   lbutton_private_data_t *private_data;
258   int               button_width, state = 0;
259   GC                lgc;
260   xitk_image_t     *skin;
261   XWindowAttributes attr;
262   xitk_pixmap_t    *btn;
263 
264   if (w && ((w->type & WIDGET_TYPE_MASK) == WIDGET_TYPE_LABELBUTTON)) {
265 
266     private_data = (lbutton_private_data_t *) w->private_data;
267 
268     if(w->visible == 1) {
269 
270       XLOCK (private_data->imlibdata->x.x_lock_display, private_data->imlibdata->x.disp);
271       XGetWindowAttributes(private_data->imlibdata->x.disp, w->wl->win, &attr);
272       XUNLOCK (private_data->imlibdata->x.x_unlock_display, private_data->imlibdata->x.disp);
273 
274       skin = private_data->skin;
275 
276       XLOCK (private_data->imlibdata->x.x_lock_display, private_data->imlibdata->x.disp);
277       lgc = XCreateGC(private_data->imlibdata->x.disp, w->wl->win, None, None);
278       XCopyGC(private_data->imlibdata->x.disp, w->wl->gc, (1 << GCLastBit) - 1, lgc);
279       XUNLOCK (private_data->imlibdata->x.x_unlock_display, private_data->imlibdata->x.disp);
280 
281       if (skin->mask) {
282         XLOCK (private_data->imlibdata->x.x_lock_display, private_data->imlibdata->x.disp);
283 	XSetClipOrigin(private_data->imlibdata->x.disp, lgc, w->x, w->y);
284 	XSetClipMask(private_data->imlibdata->x.disp, lgc, skin->mask->pixmap);
285         XUNLOCK (private_data->imlibdata->x.x_unlock_display, private_data->imlibdata->x.disp);
286       }
287 
288       button_width = skin->width / 3;
289       btn = xitk_image_create_xitk_pixmap(private_data->imlibdata, button_width, skin->height);
290 
291       if ((private_data->focus == FOCUS_RECEIVED) || (private_data->focus == FOCUS_MOUSE_IN)) {
292 	if (private_data->bClicked) {
293 	  state = CLICK;
294           XLOCK (private_data->imlibdata->x.x_lock_display, private_data->imlibdata->x.disp);
295 	  XCopyArea (private_data->imlibdata->x.disp, skin->image->pixmap,
296 		     btn->pixmap, w->wl->gc, 2*button_width, 0,
297 		     button_width, skin->height, 0, 0);
298           XUNLOCK (private_data->imlibdata->x.x_unlock_display, private_data->imlibdata->x.disp);
299 	}
300 	else {
301 	  if(!private_data->bState || private_data->bType == CLICK_BUTTON) {
302 	    state = FOCUS;
303             XLOCK (private_data->imlibdata->x.x_lock_display, private_data->imlibdata->x.disp);
304 	    XCopyArea (private_data->imlibdata->x.disp, skin->image->pixmap,
305 		       btn->pixmap, w->wl->gc, button_width, 0,
306 		       button_width, skin->height, 0, 0);
307             XUNLOCK (private_data->imlibdata->x.x_unlock_display, private_data->imlibdata->x.disp);
308 	  }
309 	  else {
310 	    if(private_data->bType == RADIO_BUTTON) {
311 	      state = CLICK;
312               XLOCK (private_data->imlibdata->x.x_lock_display, private_data->imlibdata->x.disp);
313 	      XCopyArea (private_data->imlibdata->x.disp, skin->image->pixmap,
314 			 btn->pixmap, w->wl->gc, 2*button_width, 0,
315 			 button_width, skin->height, 0, 0);
316               XUNLOCK (private_data->imlibdata->x.x_unlock_display, private_data->imlibdata->x.disp);
317 	    }
318 	  }
319 	}
320       }
321       else {
322         XLOCK (private_data->imlibdata->x.x_lock_display, private_data->imlibdata->x.disp);
323 	if(private_data->bState && private_data->bType == RADIO_BUTTON) {
324 	  if(private_data->bOldState == 1 && private_data->bClicked == 1) {
325 	    state = NORMAL;
326 	    XCopyArea (private_data->imlibdata->x.disp, skin->image->pixmap, btn->pixmap,
327 		       w->wl->gc, 0, 0, button_width, skin->height, 0, 0);
328 	  }
329 	  else {
330 	    state = CLICK;
331 	    XCopyArea (private_data->imlibdata->x.disp, skin->image->pixmap,
332 		       btn->pixmap, w->wl->gc, 2*button_width, 0,
333 		       button_width, skin->height, 0, 0);
334 	  }
335 	}
336 	else {
337 	  state = NORMAL;
338 	  XCopyArea (private_data->imlibdata->x.disp, skin->image->pixmap, btn->pixmap,
339 		     w->wl->gc, 0, 0, button_width, skin->height, 0, 0);
340 	}
341         XUNLOCK (private_data->imlibdata->x.x_unlock_display, private_data->imlibdata->x.disp);
342       }
343 
344       if(private_data->label_visible) {
345 	create_labelofbutton(w, w->wl->win, w->wl->gc, btn->pixmap,
346 			     button_width, skin->height,
347 			     private_data->label, private_data->shortcut_label, private_data->shortcut_pos, state);
348       }
349 
350       XLOCK (private_data->imlibdata->x.x_lock_display, private_data->imlibdata->x.disp);
351       XCopyArea (private_data->imlibdata->x.disp, btn->pixmap, w->wl->win, lgc, 0, 0,
352 		 button_width, skin->height, w->x, w->y);
353       XUNLOCK (private_data->imlibdata->x.x_unlock_display, private_data->imlibdata->x.disp);
354 
355       xitk_image_destroy_xitk_pixmap(btn);
356 
357       XLOCK (private_data->imlibdata->x.x_lock_display, private_data->imlibdata->x.disp);
358       XFreeGC(private_data->imlibdata->x.disp, lgc);
359       XUNLOCK (private_data->imlibdata->x.x_unlock_display, private_data->imlibdata->x.disp);
360     }
361   }
362 }
363 
364 /*
365  * Handle click events
366  */
notify_click_labelbutton(xitk_widget_t * w,int button,int bUp,int x,int y)367 static int notify_click_labelbutton (xitk_widget_t *w, int button, int bUp, int x, int y) {
368   lbutton_private_data_t *private_data;
369   int                     ret = 0;
370 
371   if (w && ((w->type & WIDGET_TYPE_MASK) == WIDGET_TYPE_LABELBUTTON)) {
372     if(button == Button1) {
373       private_data = (lbutton_private_data_t *) w->private_data;
374 
375       private_data->bClicked = !bUp;
376       private_data->bOldState = private_data->bState;
377 
378       if (bUp && (private_data->focus == FOCUS_RECEIVED)) {
379 	private_data->bState = !private_data->bState;
380 	paint_labelbutton(w);
381 	if(private_data->bType == RADIO_BUTTON) {
382 	  if(private_data->state_callback) {
383 	    private_data->state_callback(private_data->bWidget,
384 					 private_data->userdata,
385 					 private_data->bState);
386 	  }
387 	}
388 	else if(private_data->bType == CLICK_BUTTON) {
389 	  if(private_data->callback) {
390 	    private_data->callback(private_data->bWidget,
391 				   private_data->userdata);
392 	  }
393 	}
394       }
395       else
396 	paint_labelbutton(w);
397 
398       ret = 1;
399     }
400   }
401 
402   return ret;
403 }
404 
405 /*
406  * Changing button caption
407  */
xitk_labelbutton_change_label(xitk_widget_t * w,const char * newlabel)408 int xitk_labelbutton_change_label (xitk_widget_t *w, const char *newlabel) {
409   lbutton_private_data_t *private_data;
410 
411   if (w && ((w->type & WIDGET_TYPE_MASK) == WIDGET_TYPE_LABELBUTTON)) {
412     private_data = (lbutton_private_data_t *) w->private_data;
413     _set_label (private_data, newlabel);
414     paint_labelbutton(w);
415     return 1;
416   }
417 
418   return 0;
419 }
420 
421 /*
422  * Return the current button label
423  */
xitk_labelbutton_get_label(xitk_widget_t * w)424 const char *xitk_labelbutton_get_label(xitk_widget_t *w) {
425   lbutton_private_data_t *private_data;
426 
427   if (w && ((w->type & WIDGET_TYPE_MASK) == WIDGET_TYPE_LABELBUTTON)) {
428     private_data = (lbutton_private_data_t *) w->private_data;
429     return private_data->label;
430   }
431 
432   return NULL;
433 }
434 
435 /*
436  * Changing button caption
437  */
xitk_labelbutton_change_shortcut_label(xitk_widget_t * w,const char * newlabel,int pos,const char * newfont)438 int xitk_labelbutton_change_shortcut_label(xitk_widget_t *w, const char *newlabel, int pos, const char *newfont) {
439   lbutton_private_data_t *private_data;
440 
441   if (w && (((w->type & WIDGET_TYPE_MASK) == WIDGET_TYPE_LABELBUTTON) &&
442 	    (((w->type & WIDGET_GROUP_MASK) == WIDGET_GROUP_MENU) || ((w->type & WIDGET_GROUP_MASK) == WIDGET_GROUP_BROWSER)))) {
443     private_data = (lbutton_private_data_t *) w->private_data;
444 
445     if((private_data->shortcut_label = (char *) realloc(private_data->shortcut_label, strlen(newlabel) + 1)) != NULL)
446       strcpy(private_data->shortcut_label, newlabel);
447 
448     if(newfont &&
449 	(private_data->shortcut_font = (char *) realloc(private_data->shortcut_font, strlen(newfont) + 1)) != NULL)
450       strcpy(private_data->shortcut_font, newfont);
451 
452     if(strlen(private_data->shortcut_label)) {
453       if(pos >= 0)
454 	private_data->shortcut_pos = pos;
455       else
456 	private_data->shortcut_pos = -1;
457     }
458 
459     paint_labelbutton(w);
460 
461     return 1;
462   }
463 
464   return 0;
465 }
466 
467 /*
468  * Return the current button label
469  */
xitk_labelbutton_get_shortcut_label(xitk_widget_t * w)470 const char *xitk_labelbutton_get_shortcut_label(xitk_widget_t *w) {
471   lbutton_private_data_t *private_data;
472 
473   if (w && (((w->type & WIDGET_TYPE_MASK) == WIDGET_TYPE_LABELBUTTON) &&
474 	    (((w->type & WIDGET_GROUP_MASK) == WIDGET_GROUP_MENU) || ((w->type & WIDGET_GROUP_MASK) == WIDGET_GROUP_BROWSER)))) {
475     private_data = (lbutton_private_data_t *) w->private_data;
476     return private_data->shortcut_label;
477   }
478 
479   return NULL;
480 }
481 
482 /*
483  * Handle focus on button
484  */
notify_focus_labelbutton(xitk_widget_t * w,int focus)485 static int notify_focus_labelbutton (xitk_widget_t *w, int focus) {
486   lbutton_private_data_t *private_data;
487 
488   if (w && ((w->type & WIDGET_TYPE_MASK) == WIDGET_TYPE_LABELBUTTON)) {
489     private_data = (lbutton_private_data_t *) w->private_data;
490     private_data->focus = focus;
491   }
492 
493   return 1;
494 }
495 
496 /*
497  *
498  */
notify_change_skin(xitk_widget_t * w,xitk_skin_config_t * skonfig)499 static void notify_change_skin(xitk_widget_t *w, xitk_skin_config_t *skonfig) {
500   lbutton_private_data_t *private_data;
501 
502   if (w && ((w->type & WIDGET_TYPE_MASK) == WIDGET_TYPE_LABELBUTTON)) {
503     private_data = (lbutton_private_data_t *) w->private_data;
504 
505     if (private_data->skin_element_name[0] & ~1) {
506       const xitk_skin_element_info_t *info;
507 
508       xitk_skin_lock(skonfig);
509       info = xitk_skin_get_info (skonfig, private_data->skin_element_name);
510       XITK_FREE (private_data->fontname);
511       if (info) {
512         private_data->skin = info->pixmap_img;
513         _strlcpy (private_data->normcolor,  info->label_color,       sizeof (private_data->normcolor));
514         _strlcpy (private_data->focuscolor, info->label_color_focus, sizeof (private_data->focuscolor));
515         _strlcpy (private_data->clickcolor, info->label_color_click, sizeof (private_data->clickcolor));
516         private_data->fontname      = strdup (info->label_fontname);
517         private_data->label_visible = info->label_printable;
518         private_data->label_static  = info->label_staticity;
519         private_data->align         = info->label_alignment;
520         w->x      = info->x;
521         w->y      = info->y;
522         w->width  = private_data->skin->width / 3;
523         w->height = private_data->skin->height;
524         w->visible = info->visibility ? 1 : -1;
525         w->enable = info->enability;
526       }
527       xitk_skin_unlock (skonfig);
528 
529       xitk_set_widget_pos(w, w->x, w->y);
530     }
531   }
532 }
533 
534 
notify_event(xitk_widget_t * w,widget_event_t * event,widget_event_result_t * result)535 static int notify_event(xitk_widget_t *w, widget_event_t *event, widget_event_result_t *result) {
536   int retval = 0;
537 
538   switch(event->type) {
539   case WIDGET_EVENT_PAINT:
540     paint_labelbutton(w);
541     break;
542   case WIDGET_EVENT_CLICK:
543     result->value = notify_click_labelbutton(w, event->button,
544 					     event->button_pressed, event->x, event->y);
545     retval = 1;
546     break;
547   case WIDGET_EVENT_FOCUS:
548     notify_focus_labelbutton(w, event->focus);
549     break;
550   case WIDGET_EVENT_INSIDE:
551     result->value = notify_inside(w, event->x, event->y);
552     retval = 1;
553     break;
554   case WIDGET_EVENT_CHANGE_SKIN:
555     notify_change_skin(w, event->skonfig);
556     break;
557   case WIDGET_EVENT_DESTROY:
558     notify_destroy(w);
559     break;
560   case WIDGET_EVENT_GET_SKIN:
561     if(result) {
562       result->image = get_skin(w, event->skin_layer);
563       retval = 1;
564     }
565     break;
566   }
567 
568   return retval;
569 }
570 
571 /*
572  * Return state (ON/OFF) if button is radio button, otherwise -1
573  */
xitk_labelbutton_get_state(xitk_widget_t * w)574 int xitk_labelbutton_get_state(xitk_widget_t *w) {
575   lbutton_private_data_t *private_data;
576 
577   if (w && ((w->type & WIDGET_TYPE_MASK) == WIDGET_TYPE_LABELBUTTON)) {
578     private_data = (lbutton_private_data_t *) w->private_data;
579 
580     if(private_data->bType == RADIO_BUTTON)
581       return private_data->bState;
582   }
583 
584   return -1;
585 }
586 
587 /*
588  * Set label button alignment
589  */
xitk_labelbutton_set_alignment(xitk_widget_t * w,int align)590 void xitk_labelbutton_set_alignment(xitk_widget_t *w, int align) {
591   lbutton_private_data_t *private_data;
592 
593   if(w && ((w->type & WIDGET_TYPE_MASK) == WIDGET_TYPE_LABELBUTTON)) {
594     private_data = (lbutton_private_data_t *) w->private_data;
595     private_data->align = align;
596   }
597 }
598 
599 /*
600  * Get label button alignment
601  */
xitk_labelbutton_get_alignment(xitk_widget_t * w)602 int xitk_labelbutton_get_alignment(xitk_widget_t *w) {
603   lbutton_private_data_t *private_data;
604 
605   if(w && ((w->type & WIDGET_TYPE_MASK) == WIDGET_TYPE_LABELBUTTON)) {
606     private_data = (lbutton_private_data_t *) w->private_data;
607     return private_data->align;
608   }
609 
610   return -1;
611 }
612 
613 /*
614  * Return used font name
615  */
xitk_labelbutton_get_fontname(xitk_widget_t * w)616 char *xitk_labelbutton_get_fontname(xitk_widget_t *w) {
617   lbutton_private_data_t *private_data;
618 
619   if(w && ((w->type & WIDGET_TYPE_MASK) == WIDGET_TYPE_LABELBUTTON)) {
620     private_data = (lbutton_private_data_t *) w->private_data;
621     if(private_data->fontname == NULL)
622       return NULL;
623     return (strdup(private_data->fontname));
624   }
625 
626   return NULL;
627 }
628 
629 /*
630  *
631  */
xitk_labelbutton_set_label_offset(xitk_widget_t * w,int offset)632 void xitk_labelbutton_set_label_offset(xitk_widget_t *w, int offset) {
633   lbutton_private_data_t *private_data;
634 
635   if(w && ((w->type & WIDGET_TYPE_MASK) == WIDGET_TYPE_LABELBUTTON)) {
636     private_data = (lbutton_private_data_t *) w->private_data;
637     private_data->label_offset = offset;
638   }
639 }
xitk_labelbutton_get_label_offset(xitk_widget_t * w)640 int xitk_labelbutton_get_label_offset(xitk_widget_t *w) {
641   lbutton_private_data_t *private_data;
642 
643   if(w && ((w->type & WIDGET_TYPE_MASK) == WIDGET_TYPE_LABELBUTTON)) {
644     private_data = (lbutton_private_data_t *) w->private_data;
645     return private_data->label_offset;
646   }
647   return 0;
648 }
649 
650 /*
651  * Set radio button to state 'state'
652  */
xitk_labelbutton_set_state(xitk_widget_t * w,int state)653 void xitk_labelbutton_set_state(xitk_widget_t *w, int state) {
654   lbutton_private_data_t *private_data;
655   int                     clk, focus;
656 
657   if (w && ((w->type & WIDGET_TYPE_MASK) == WIDGET_TYPE_LABELBUTTON)) {
658 
659     private_data = (lbutton_private_data_t *) w->private_data;
660 
661     if(private_data->bType == RADIO_BUTTON) {
662       if(xitk_labelbutton_get_state(w) != state) {
663 	focus = private_data->focus;
664 	clk = private_data->bClicked;
665 
666 	private_data->focus = FOCUS_RECEIVED;
667 	private_data->bClicked = 1;
668 	private_data->bOldState = private_data->bState;
669 	private_data->bState = state;
670 
671 	paint_labelbutton(w);
672 
673 	private_data->focus = focus;
674 	private_data->bClicked = clk;
675 
676 	paint_labelbutton(w);
677       }
678     }
679   }
680 
681 }
682 
labelbutton_get_user_data(xitk_widget_t * w)683 void *labelbutton_get_user_data(xitk_widget_t *w) {
684   if(w && ((w->type & WIDGET_TYPE_MASK) == WIDGET_TYPE_LABELBUTTON)) {
685     lbutton_private_data_t *private_data = (lbutton_private_data_t *) w->private_data;
686 
687     return private_data->userdata;
688   }
689 
690   return NULL;
691 }
xitk_labelbutton_callback_exec(xitk_widget_t * w)692 void xitk_labelbutton_callback_exec(xitk_widget_t *w) {
693 
694   if(w && ((w->type & WIDGET_TYPE_MASK) == WIDGET_TYPE_LABELBUTTON)) {
695     lbutton_private_data_t *private_data = (lbutton_private_data_t *) w->private_data;
696 
697     if(private_data->bType == RADIO_BUTTON) {
698       if(private_data->state_callback) {
699 	private_data->state_callback(private_data->bWidget,
700 				     private_data->userdata,
701 				     private_data->bState);
702       }
703     }
704     else if(private_data->bType == CLICK_BUTTON) {
705       if(private_data->callback) {
706 	private_data->callback(private_data->bWidget,
707 			       private_data->userdata);
708       }
709     }
710   }
711 }
712 
713 /*
714  * Create the labeled button
715  */
xitk_info_labelbutton_create(xitk_widget_list_t * wl,const xitk_labelbutton_widget_t * b,const xitk_skin_element_info_t * info)716 xitk_widget_t *xitk_info_labelbutton_create (xitk_widget_list_t *wl,
717   const xitk_labelbutton_widget_t *b, const xitk_skin_element_info_t *info) {
718   xitk_widget_t           *mywidget;
719   lbutton_private_data_t *private_data;
720 
721   mywidget = (xitk_widget_t *) xitk_xmalloc (sizeof(xitk_widget_t));
722   if (!mywidget)
723     return NULL;
724   private_data = (lbutton_private_data_t *) xitk_xmalloc (sizeof (lbutton_private_data_t));
725   if (!private_data) {
726     free (mywidget);
727     return NULL;
728   }
729 
730   private_data->imlibdata         = b->imlibdata;
731 
732   private_data->bWidget           = mywidget;
733   private_data->bType             = b->button_type;
734   private_data->bClicked          = 0;
735   private_data->focus             = FOCUS_LOST;
736   private_data->bState            = 0;
737   private_data->bOldState         = 0;
738 
739   private_data->callback          = b->callback;
740   private_data->state_callback    = b->state_callback;
741   private_data->userdata          = b->userdata;
742 
743   private_data->label = private_data->lbuf;
744   _set_label (private_data, b->label);
745 
746   private_data->shortcut_label    = strdup("");
747   private_data->shortcut_font     = strdup (info->label_fontname);
748   private_data->shortcut_pos      = -1;
749   private_data->label_visible     = info->label_printable;
750   private_data->label_static      = info->label_staticity;
751 
752   private_data->skin              = info->pixmap_img;
753 
754   if (info->pixmap_name && (info->pixmap_name[0] == '\x01') && (info->pixmap_name[1] == 0)) {
755     private_data->skin_element_name[0] = '\x01';
756     private_data->skin_element_name[1] = 0;
757   } else {
758     _strlcpy (private_data->skin_element_name, b->skin_element_name, sizeof (private_data->skin_element_name));
759   }
760   _strlcpy (private_data->normcolor, info->label_color, sizeof (private_data->normcolor));
761   _strlcpy (private_data->focuscolor, info->label_color_focus, sizeof (private_data->focuscolor));
762   _strlcpy (private_data->clickcolor, info->label_color_click, sizeof (private_data->clickcolor));
763   private_data->fontname          = strdup (info->label_fontname);
764 
765   private_data->label_offset      = 0;
766   private_data->align             = info->label_alignment;
767 
768   mywidget->private_data          = private_data;
769 
770   mywidget->wl                    = wl;
771 
772   mywidget->enable                = info->enability;
773   mywidget->running               = 1;
774   mywidget->visible               = info->visibility;
775   mywidget->have_focus            = FOCUS_LOST;
776   mywidget->imlibdata             = private_data->imlibdata;
777   mywidget->x                     = info->x;
778   mywidget->y                     = info->y;
779   mywidget->width                 = private_data->skin->width/3;
780   mywidget->height                = private_data->skin->height;
781   mywidget->type                  = WIDGET_TYPE_LABELBUTTON | WIDGET_FOCUSABLE | WIDGET_CLICKABLE | WIDGET_KEYABLE;
782   mywidget->event                 = notify_event;
783   mywidget->tips_timeout          = 0;
784   mywidget->tips_string           = NULL;
785 
786   return mywidget;
787 }
788 
789 /*
790  *
791  */
xitk_labelbutton_create(xitk_widget_list_t * wl,xitk_skin_config_t * skonfig,const xitk_labelbutton_widget_t * b)792 xitk_widget_t *xitk_labelbutton_create (xitk_widget_list_t *wl,
793   xitk_skin_config_t *skonfig, const xitk_labelbutton_widget_t *b) {
794   const xitk_skin_element_info_t *pinfo;
795   xitk_skin_element_info_t info;
796 
797   XITK_CHECK_CONSTITENCY (b);
798   pinfo = xitk_skin_get_info (skonfig, b->skin_element_name);
799   if (pinfo) {
800     if (!pinfo->visibility) {
801       info = *pinfo;
802       info.visibility = 1;
803       pinfo = &info;
804     }
805   } else {
806     memset (&info, 0, sizeof (info));
807     info.label_alignment = b->align;
808     info.visibility = -1;
809     pinfo = &info;
810   }
811 
812   return xitk_info_labelbutton_create (wl, b, pinfo);
813 }
814 
815 /*
816  *
817  */
xitk_noskin_labelbutton_create(xitk_widget_list_t * wl,const xitk_labelbutton_widget_t * b,int x,int y,int width,int height,const char * ncolor,const char * fcolor,const char * ccolor,const char * fname)818 xitk_widget_t *xitk_noskin_labelbutton_create (xitk_widget_list_t *wl,
819   const xitk_labelbutton_widget_t *b, int x, int y, int width, int height,
820   const char *ncolor, const char *fcolor, const char *ccolor, const char *fname) {
821   xitk_skin_element_info_t info;
822 
823   XITK_CHECK_CONSTITENCY(b);
824   info.x                 = x;
825   info.y                 = y;
826   info.label_alignment   = b->align;
827   info.label_printable   = 1;
828   info.label_staticity   = 0;
829   info.visibility        = 0;
830   info.enability         = 0;
831   info.label_color       = (char *)ncolor;
832   info.label_color_focus = (char *)fcolor;
833   info.label_color_click = (char *)ccolor;
834   info.label_fontname    = (char *)fname;
835   info.pixmap_name       = (char *)"\x01";
836   info.pixmap_img        = xitk_image_create_image (b->imlibdata, width * 3, height);
837   if (info.pixmap_img)
838     draw_bevel_three_state (b->imlibdata, info.pixmap_img);
839 
840   return xitk_info_labelbutton_create (wl, b, &info);
841 }
842 
843