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 <sys/time.h>
27 #include <unistd.h>
28 
29 #include "_xitk.h"
30 
31 #define WBUP    0  /*  Position of button up in item_tree  */
32 #define WSLID   1  /*  Position of slider in item_tree  */
33 #define WBDN    2  /*  Position of button down in item_tree  */
34 #define WBLF    3
35 #define WSLIDH  4
36 #define WBRT    5
37 #define WBSTART 6  /*  Position of first item button in item_tree */
38 
39 #define EXTRA_BTNS 50
40 
41 static void notify_change_skin(xitk_widget_t *, xitk_skin_config_t *);
42 /*
43  *
44  */
paint(xitk_widget_t * w)45 static void paint(xitk_widget_t *w) {
46   browser_private_data_t *private_data;
47 
48   if(w && (((w->type & WIDGET_GROUP_MASK) & WIDGET_GROUP_BROWSER) &&
49 	   (w->type & WIDGET_GROUP_WIDGET))) {
50     int i;
51 
52     private_data = (browser_private_data_t *) w->private_data;
53 
54     if(w->visible == 1) {
55       if(!private_data->skin_element_name) {
56 	int x     = w->x;
57 	int y     = w->y;
58 	int itemw = xitk_get_widget_width(private_data->item_tree[WBSTART]);
59 	int itemh = xitk_get_widget_height(private_data->item_tree[WBSTART]);
60 	int iy    = w->y;
61 	int bh;
62 
63 	(void) xitk_set_widget_pos(private_data->item_tree[WBUP], x + itemw, y);
64 	bh = xitk_get_widget_height(private_data->item_tree[WBUP]);
65 	(void) xitk_set_widget_pos(private_data->item_tree[WSLID], x + itemw, y + bh);
66 	bh += xitk_get_widget_height(private_data->item_tree[WSLID]);
67 	(void) xitk_set_widget_pos(private_data->item_tree[WBDN], x + itemw, y + bh);
68 	if(private_data->need_h_slider) {
69 #warning NEED
70 
71 	}
72 
73 	xitk_show_widget(private_data->item_tree[WBUP]);
74 	xitk_show_widget(private_data->item_tree[WSLID]);
75 	xitk_show_widget(private_data->item_tree[WBDN]);
76 
77 	xitk_show_widget(private_data->item_tree[WBLF]);
78 	xitk_show_widget(private_data->item_tree[WSLIDH]);
79 	xitk_show_widget(private_data->item_tree[WBRT]);
80 
81 	if(private_data->need_h_slider) {
82 #warning NEED
83 	}
84 
85 	for(i = WBSTART; i < (private_data->max_length+WBSTART); i++) {
86 	  (void) xitk_set_widget_pos(private_data->item_tree[i], x, iy);
87 	  xitk_show_widget(private_data->item_tree[i]);
88 	  iy += itemh;
89 	}
90       }
91     }
92     else {
93       for(i = 0; i < (private_data->max_length+WBSTART); i++) {
94 	xitk_hide_widget(private_data->item_tree[i]);
95       }
96     }
97   }
98 }
99 
notify_change_skin(xitk_widget_t * w,xitk_skin_config_t * skonfig)100 static void notify_change_skin(xitk_widget_t *w, xitk_skin_config_t *skonfig) {
101   browser_private_data_t *private_data;
102 
103   if(w && (((w->type & WIDGET_GROUP_MASK) & WIDGET_GROUP_BROWSER) &&
104 	   (w->type & WIDGET_GROUP_WIDGET))) {
105 
106     private_data = (browser_private_data_t *) w->private_data;
107 
108     if(private_data->skin_element_name) {
109       int x, y, i = 0;
110 
111       xitk_skin_lock(skonfig);
112 
113       x          = xitk_skin_get_coord_x(skonfig, private_data->skin_element_name);
114       y          = xitk_skin_get_coord_y(skonfig, private_data->skin_element_name);
115       w->visible = (xitk_skin_get_visibility(skonfig, private_data->skin_element_name)) ? 1 : -1;
116       w->enable  = xitk_skin_get_enability(skonfig, private_data->skin_element_name);
117 
118       private_data->max_length = xitk_skin_get_browser_entries(skonfig,
119 							       private_data->skin_element_name);
120 
121       for(i = WBSTART; i < (EXTRA_BTNS + WBSTART); i++) {
122 	xitk_disable_widget(private_data->item_tree[i]);
123 	xitk_hide_widget(private_data->item_tree[i]);
124       }
125 
126       for(i = WBSTART; i < private_data->max_length + WBSTART; i++) {
127 	(void) xitk_set_widget_pos(private_data->item_tree[i], x, y);
128 	y += xitk_get_widget_height(private_data->item_tree[i]) + 1;
129 	xitk_enable_and_show_widget(private_data->item_tree[i]);
130       }
131 
132       xitk_browser_rebuild_browser(w, 0);
133 
134       xitk_skin_unlock(skonfig);
135     }
136   }
137 }
138 
notify_destroy(xitk_widget_t * w)139 static void notify_destroy(xitk_widget_t *w) {
140   browser_private_data_t *private_data;
141 
142   if(w && (((w->type & WIDGET_GROUP_MASK) & WIDGET_GROUP_BROWSER) &&
143            (w->type & WIDGET_GROUP_WIDGET))) {
144     int  i;
145 
146     private_data = (browser_private_data_t *) w->private_data;
147 
148     for(i = WBSTART; i < private_data->max_length + WBSTART + EXTRA_BTNS; i++)
149       XITK_FREE(private_data->bt[i]);
150 
151     XITK_FREE(private_data->skin_element_name);
152     XITK_FREE(private_data);
153   }
154 }
155 
enability(xitk_widget_t * w)156 static void enability(xitk_widget_t *w) {
157   browser_private_data_t *private_data;
158 
159   if(w && (((w->type & WIDGET_GROUP_MASK) & WIDGET_GROUP_BROWSER) &&
160 	   (w->type & WIDGET_GROUP_WIDGET))) {
161     int i;
162     int max;
163 
164     private_data = (browser_private_data_t *) w->private_data;
165 
166     max = WBSTART;
167     max += (private_data->skin_element_name) ? EXTRA_BTNS : private_data->max_length;
168 
169     if(w->enable == WIDGET_ENABLE) {
170       if(private_data->list_length >= private_data->max_length) {
171 	xitk_enable_widget(private_data->item_tree[WBUP]);
172 	xitk_enable_widget(private_data->item_tree[WSLID]);
173 	xitk_enable_widget(private_data->item_tree[WBDN]);
174       }
175       if(private_data->need_h_slider) {
176 	xitk_enable_widget(private_data->item_tree[WBLF]);
177 	xitk_enable_widget(private_data->item_tree[WSLIDH]);
178 	xitk_enable_widget(private_data->item_tree[WBRT]);
179       }
180       for(i = WBSTART; i < max; i++)
181 	xitk_enable_widget(private_data->item_tree[i]);
182     }
183     else {
184       for(i = WBUP; i < max; i++)
185 	xitk_disable_widget(private_data->item_tree[i]);
186     }
187   }
188 }
189 
notify_event(xitk_widget_t * w,widget_event_t * event,widget_event_result_t * result)190 static int notify_event(xitk_widget_t *w, widget_event_t *event, widget_event_result_t *result) {
191   int retval = 0;
192 
193   switch(event->type) {
194   case WIDGET_EVENT_PAINT:
195     paint(w);
196     break;
197   case WIDGET_EVENT_DESTROY:
198     notify_destroy(w);
199     break;
200   case WIDGET_EVENT_CHANGE_SKIN:
201     notify_change_skin(w, event->skonfig);
202     break;
203   case WIDGET_EVENT_ENABLE:
204     enability(w);
205     break;
206   }
207 
208   return retval;
209 }
210 
211 /**
212  * Return the number of displayed entries
213  */
xitk_browser_get_num_entries(xitk_widget_t * w)214 int xitk_browser_get_num_entries(xitk_widget_t *w) {
215   browser_private_data_t *private_data;
216 
217   if(w && (((w->type & WIDGET_GROUP_MASK) & WIDGET_GROUP_BROWSER) &&
218 	   (w->type & WIDGET_GROUP_WIDGET))) {
219     private_data = (browser_private_data_t *) w->private_data;
220     return private_data->max_length;
221   }
222 
223   return -1;
224 }
225 
226 /**
227  * Return the real number of first displayed in list
228  */
xitk_browser_get_current_start(xitk_widget_t * w)229 int xitk_browser_get_current_start(xitk_widget_t *w) {
230   browser_private_data_t *private_data;
231 
232   if(w && (((w->type & WIDGET_GROUP_MASK) & WIDGET_GROUP_BROWSER) &&
233 	   (w->type & WIDGET_GROUP_WIDGET))) {
234     private_data = (browser_private_data_t *) w->private_data;
235     return private_data->current_start;
236   }
237 
238   return -1;
239 }
240 
241 /**
242  * Change browser labels alignment
243  */
xitk_browser_set_alignment(xitk_widget_t * w,int align)244 void xitk_browser_set_alignment(xitk_widget_t *w, int align) {
245   browser_private_data_t *private_data;
246   int i;
247 
248   if(w && (((w->type & WIDGET_GROUP_MASK) & WIDGET_GROUP_BROWSER) &&
249 	   (w->type & WIDGET_GROUP_WIDGET))) {
250 
251     private_data = (browser_private_data_t *) w->private_data;
252 
253     for(i = 0; i < private_data->max_length; i++) {
254       xitk_labelbutton_set_alignment(private_data->item_tree[i+WBSTART], align);
255     }
256 
257     xitk_browser_rebuild_browser(w, -1);
258   }
259 }
260 
261 /**
262  * Return the current selected button (if not, return -1)
263  */
xitk_browser_get_current_selected(xitk_widget_t * w)264 int xitk_browser_get_current_selected(xitk_widget_t *w) {
265   browser_private_data_t *private_data;
266   int                     i;
267 
268   if(w && (((w->type & WIDGET_GROUP_MASK) & WIDGET_GROUP_BROWSER) &&
269 	   (w->type & WIDGET_GROUP_WIDGET))) {
270 
271     private_data = (browser_private_data_t *) w->private_data;
272 
273     for(i = 0; i < private_data->max_length; i++) {
274       if(xitk_labelbutton_get_state(private_data->item_tree[i+WBSTART]))
275 	return (private_data->current_start + i);
276     }
277   }
278 
279   return -1;
280 }
281 
282 /**
283  * Release all enabled buttons
284  */
xitk_browser_release_all_buttons(xitk_widget_t * w)285 void xitk_browser_release_all_buttons(xitk_widget_t *w) {
286   browser_private_data_t *private_data;
287   int                     i;
288 
289   if(w && (((w->type & WIDGET_GROUP_MASK) & WIDGET_GROUP_BROWSER) &&
290 	   (w->type & WIDGET_GROUP_WIDGET))) {
291 
292     private_data = (browser_private_data_t *) w->private_data;
293 
294     for(i = 0; i < private_data->max_length; i++) {
295       xitk_labelbutton_set_state(private_data->item_tree[i+WBSTART], 0);
296     }
297   }
298 }
299 
300 /**
301  * Select the item 'select' in list
302  */
xitk_browser_set_select(xitk_widget_t * w,int select)303 void xitk_browser_set_select(xitk_widget_t *w, int select) {
304   browser_private_data_t *private_data;
305 
306   if(w && (((w->type & WIDGET_GROUP_MASK) & WIDGET_GROUP_BROWSER) &&
307 	   (w->type & WIDGET_GROUP_WIDGET))) {
308 
309     private_data = (browser_private_data_t *) w->private_data;
310 
311     xitk_browser_release_all_buttons(w);
312 
313     xitk_labelbutton_set_state(private_data->item_tree[(select - private_data->current_start) + WBSTART], 1);
314     private_data->current_button_clicked = xitk_browser_get_current_selected(w);
315     gettimeofday(&private_data->click_time, 0);
316   }
317 }
318 
319 /**
320  * Redraw buttons/slider
321  */
xitk_browser_rebuild_browser(xitk_widget_t * w,int start)322 void xitk_browser_rebuild_browser(xitk_widget_t *w, int start) {
323   browser_private_data_t *private_data;
324   int                     i, j, max = 0;
325 
326   if(w && (((w->type & WIDGET_GROUP_MASK) & WIDGET_GROUP_BROWSER) &&
327 	   (w->type & WIDGET_GROUP_WIDGET))) {
328     int           item_width;
329     char         *label_font;
330     xitk_font_t  *fs = NULL;
331     int           old_label_offset;
332 
333     private_data     = (browser_private_data_t *) w->private_data;
334     item_width       = xitk_get_widget_width(private_data->item_tree[WBSTART]);
335     label_font       = xitk_labelbutton_get_fontname(private_data->item_tree[WBSTART]);
336     old_label_offset = private_data->labels_offset;
337 
338     xitk_browser_release_all_buttons(w);
339 
340     j = (private_data->list_length > (private_data->max_length - 1) ?
341 	 (private_data->list_length - 1) : 1);
342 
343     if(j <= (private_data->max_length - 1))
344       max = 0;
345     else if(j > (private_data->max_length - 1))
346       max = j - (private_data->max_length - 1);
347 
348     if(((start >= 0) && max) || ((start == 0) && (max == 0)))
349       private_data->current_start = start;
350 
351     private_data->need_h_slider = 0;
352     private_data->labels_offset = 0;
353 
354     if(label_font) {
355       fs = xitk_font_load_font(private_data->imlibdata->x.disp, label_font);
356       xitk_font_set_font(fs, private_data->parent_wlist->gc);
357     }
358 
359     if(private_data->shortcuts_content) {
360       int maxlen = 0;
361 
362       for(i = 0; i < private_data->max_length; i++) {
363 	char *nshortcut;
364 
365 	if((private_data->shortcuts_content[private_data->current_start + i]) &&
366 	   (nshortcut = private_data->shortcuts_content[private_data->current_start + i])) {
367 	  int nlen = strlen(nshortcut);
368 
369 	  if(nlen > maxlen) {
370 	    maxlen = nlen;
371 	  }
372 	}
373       }
374     }
375 
376     if(fs) {
377       int  label_width;
378       int  j = 0;
379       int  max = 0, offset = 0, len;
380 
381       while(j < private_data->list_length) {
382 	if((len = strlen(private_data->content[j])) > max) {
383 	  max    = len;
384 	  offset = j;
385 	}
386 	j++;
387       }
388 
389       label_width = (private_data->content && private_data->content[offset] && strlen(private_data->content[offset])) ? xitk_font_get_string_length(fs, private_data->content[offset]) : 0;
390 
391       if(label_width > (item_width -2)) {
392 	int diff_width = (label_width - (item_width - 2));
393 
394 	private_data->need_h_slider = 1;
395 
396 	if(private_data->labels_offset < diff_width)
397 	  private_data->labels_offset = diff_width;
398 
399       }
400       else
401 	private_data->need_h_slider = 0;
402     }
403 
404     if(!private_data->need_h_slider) {
405       for(i = 0; i < private_data->max_length; i++)
406 	xitk_labelbutton_set_label_offset(private_data->item_tree[i + WBSTART], 0);
407     }
408 
409     for(i = 0; i < private_data->max_length; i++) {
410       if (((private_data->current_start + i) < private_data->list_length)
411 	  && (private_data->content[private_data->current_start + i] != NULL)) {
412 
413 	xitk_labelbutton_change_label(private_data->item_tree[i + WBSTART],
414 				      private_data->content[private_data->current_start + i]);
415 
416 	if(private_data->shortcuts_content) {
417 	  if(private_data->shortcuts_content[private_data->current_start + i])
418 	    xitk_labelbutton_change_shortcut_label(private_data->item_tree[i + WBSTART],
419 						   private_data->shortcuts_content[private_data->current_start + i],
420 						   item_width - (xitk_font_get_string_length(fs, private_data->shortcuts_content[private_data->current_start + i]) + 10),
421 						   NULL);
422 	  else
423 	    xitk_labelbutton_change_shortcut_label(private_data->item_tree[i + WBSTART], "", -1, NULL);
424 	}
425 
426       }
427       else {
428 	xitk_labelbutton_change_label(private_data->item_tree[i+WBSTART], "");
429 	xitk_labelbutton_change_shortcut_label(private_data->item_tree[i + WBSTART], "", -1, NULL);
430       }
431 
432     }
433 
434     XITK_FREE(label_font);
435 
436     if(fs)
437       xitk_font_unload_font(fs);
438 
439     if(private_data->need_h_slider) {
440       int npos, pos = xitk_slider_get_pos(private_data->item_tree[WSLIDH]);
441 
442       xitk_enable_widget(private_data->item_tree[WSLIDH]);
443       xitk_enable_widget(private_data->item_tree[WBLF]);
444       xitk_enable_widget(private_data->item_tree[WBRT]);
445 
446       if(private_data->labels_offset != old_label_offset) {
447 	int align = xitk_labelbutton_get_alignment(private_data->item_tree[WBSTART]);
448 
449 	switch(align) {
450 	case ALIGN_CENTER:
451 	  xitk_slider_set_min(private_data->item_tree[WSLIDH], -(private_data->labels_offset>>1));
452 	  xitk_slider_set_max(private_data->item_tree[WSLIDH], (private_data->labels_offset>>1));
453 	  break;
454 	case ALIGN_LEFT:
455 	  xitk_slider_set_min(private_data->item_tree[WSLIDH], 0);
456 	  xitk_slider_set_max(private_data->item_tree[WSLIDH], private_data->labels_offset);
457 	  break;
458 	case ALIGN_RIGHT:
459 	  xitk_slider_set_min(private_data->item_tree[WSLIDH], (-private_data->labels_offset) - 3);
460 	  xitk_slider_set_max(private_data->item_tree[WSLIDH], 0);
461 	  break;
462 	}
463       }
464 
465       if((pos > (npos = xitk_slider_get_max(private_data->item_tree[WSLIDH]))) ||
466       	 (pos < (npos = xitk_slider_get_min(private_data->item_tree[WSLIDH]))))
467 	pos = npos;
468 
469       xitk_slider_set_pos(private_data->item_tree[WSLIDH], pos);
470     }
471     else {
472       xitk_disable_widget(private_data->item_tree[WBLF]);
473       xitk_disable_widget(private_data->item_tree[WSLIDH]);
474       xitk_disable_widget(private_data->item_tree[WBRT]);
475 
476       xitk_slider_set_max(private_data->item_tree[WSLIDH], 1);
477       xitk_slider_set_min(private_data->item_tree[WSLIDH], 0);
478       xitk_slider_reset(private_data->item_tree[WSLIDH]);
479     }
480 
481 
482     xitk_slider_set_max(private_data->item_tree[WSLID], max);
483 
484     if(private_data->list_length >= private_data->max_length) {
485       xitk_enable_widget(private_data->item_tree[WBUP]);
486       xitk_enable_widget(private_data->item_tree[WSLID]);
487       xitk_enable_widget(private_data->item_tree[WBDN]);
488     }
489     else {
490       xitk_disable_widget(private_data->item_tree[WBUP]);
491       xitk_disable_widget(private_data->item_tree[WSLID]);
492       xitk_disable_widget(private_data->item_tree[WBDN]);
493     }
494 
495     if(start == 0)
496       xitk_slider_set_to_max(private_data->item_tree[WSLID]);
497     else if(max) {
498       xitk_slider_set_pos(private_data->item_tree[WSLID],
499 			  (xitk_slider_get_max(private_data->item_tree[WSLID])
500 			   - xitk_slider_get_min(private_data->item_tree[WSLID])
501 			   - (private_data->current_start)));
502     }
503 
504   }
505 }
506 
507 /**
508  * Update the list, and rebuild button list
509  */
xitk_browser_update_list(xitk_widget_t * w,const char * const * list,const char * const * shortcut,int len,int start)510 void xitk_browser_update_list(xitk_widget_t *w, const char *const *list, const char *const *shortcut, int len, int start) {
511   browser_private_data_t *private_data;
512 
513   if(w && (((w->type & WIDGET_GROUP_MASK) & WIDGET_GROUP_BROWSER) &&
514 	   (w->type & WIDGET_GROUP_WIDGET))) {
515 
516     private_data = (browser_private_data_t *) w->private_data;
517     private_data->content = (char **)list;
518     private_data->shortcuts_content = (char **)shortcut;
519     private_data->list_length = len;
520     xitk_browser_rebuild_browser(w, start);
521   }
522 }
523 
524 /**
525  * Handle slider movments
526  */
browser_slidmove(xitk_widget_t * w,void * data,int pos)527 static void browser_slidmove(xitk_widget_t *w, void *data, int pos) {
528   browser_private_data_t *private_data;
529   int                     realpos;
530 
531   if(w && ((w->type & WIDGET_GROUP_MASK) & WIDGET_GROUP_BROWSER)) {
532 
533     private_data = (browser_private_data_t *) ((xitk_widget_t*)data)->private_data;
534 
535     if(xitk_browser_get_current_selected(((xitk_widget_t*)data)) > -1)
536       xitk_browser_release_all_buttons(((xitk_widget_t*)data));
537 
538     realpos =
539       xitk_slider_get_max(private_data->item_tree[WSLID])
540       - xitk_slider_get_min(private_data->item_tree[WSLID])
541       - pos;
542 
543     if(private_data->list_length > (private_data->max_length-1))
544       xitk_browser_rebuild_browser(((xitk_widget_t*)data), realpos);
545     else
546       xitk_browser_rebuild_browser(((xitk_widget_t*)data), -1);
547   }
548 }
549 
browser_hslidmove(xitk_widget_t * w,void * data,int pos)550 static void browser_hslidmove(xitk_widget_t *w, void *data, int pos) {
551   browser_private_data_t *private_data;
552 
553   if(w && ((w->type & WIDGET_GROUP_MASK) & WIDGET_GROUP_BROWSER)) {
554     int                  i;
555 
556     private_data = (browser_private_data_t *) ((xitk_widget_t*)data)->private_data;
557 
558     if(private_data->labels_offset) {
559 
560       for(i = 0; i < private_data->max_length; i++) {
561 	if (((private_data->current_start + i) < private_data->list_length)
562 	    && (private_data->content[private_data->current_start + i] != NULL)) {
563 
564 	  xitk_labelbutton_set_label_offset(private_data->item_tree[i + WBSTART], -pos);
565 
566 	  xitk_labelbutton_change_label(private_data->item_tree[i + WBSTART],
567 					private_data->content[private_data->current_start + i]);
568 	  if(private_data->shortcuts_content)
569 	    xitk_labelbutton_change_shortcut_label(private_data->item_tree[i + WBSTART],
570 						   private_data->shortcuts_content[private_data->current_start + i], -1, NULL);
571 
572 	}
573 	else {
574 	  xitk_labelbutton_change_label(private_data->item_tree[i+WBSTART], "");
575 	  xitk_labelbutton_change_shortcut_label(private_data->item_tree[i + WBSTART], "", -1, NULL);
576 	}
577       }
578     }
579     else
580       xitk_slider_reset(private_data->item_tree[WSLIDH]);
581 
582   }
583 }
584 
585 /**
586  * slide up
587  */
browser_up(xitk_widget_t * w,void * data)588 static void browser_up(xitk_widget_t *w, void *data) {
589   browser_private_data_t *private_data;
590 
591   if(w && ((w->type & WIDGET_TYPE_MASK) == WIDGET_TYPE_BUTTON)) {
592     private_data = (browser_private_data_t *) ((xitk_widget_t*)data)->private_data;
593 
594     xitk_slider_make_step(private_data->item_tree[WSLID]);
595     browser_slidmove(w, data, xitk_slider_get_pos(private_data->item_tree[WSLID]));
596 
597   }
598 }
599 
600 /**
601  * slide down
602  */
browser_down(xitk_widget_t * w,void * data)603 static void browser_down(xitk_widget_t *w, void *data) {
604   browser_private_data_t *private_data;
605 
606   if(w && ((w->type & WIDGET_TYPE_MASK) == WIDGET_TYPE_BUTTON)) {
607     private_data = (browser_private_data_t *) ((xitk_widget_t*)data)->private_data;
608 
609     xitk_slider_make_backstep(private_data->item_tree[WSLID]);
610     browser_slidmove(w, data, xitk_slider_get_pos(private_data->item_tree[WSLID]));
611 
612   }
613 }
614 
615 /**
616  * slide up (extern).
617  */
xitk_browser_step_up(xitk_widget_t * w,void * data)618 void xitk_browser_step_up(xitk_widget_t *w, void *data) {
619   browser_private_data_t *private_data;
620 
621   if(w && (((w->type & WIDGET_GROUP_MASK) & WIDGET_GROUP_BROWSER) &&
622 	   (w->type & WIDGET_GROUP_WIDGET))) {
623     private_data = (browser_private_data_t *) w->private_data;
624 
625     xitk_slider_make_backstep(private_data->item_tree[WSLID]);
626     browser_slidmove(w, w, xitk_slider_get_pos(private_data->item_tree[WSLID]));
627 
628   }
629 }
630 
xitk_browser_page_up(xitk_widget_t * w,void * data)631 void xitk_browser_page_up(xitk_widget_t *w, void *data) {
632   browser_private_data_t *private_data;
633 
634   if(w && (((w->type & WIDGET_GROUP_MASK) & WIDGET_GROUP_BROWSER) &&
635 	   (w->type & WIDGET_GROUP_WIDGET))) {
636     int min, pos, npos, vis;
637 
638     private_data = (browser_private_data_t *) w->private_data;
639 
640     min = xitk_slider_get_min(private_data->item_tree[WSLID]);
641     npos = pos = xitk_slider_get_pos(private_data->item_tree[WSLID]);
642     vis = private_data->max_length;
643 
644     if((pos - vis) >= min)
645       npos -= vis;
646     else
647       npos = min;
648 
649     xitk_slider_set_pos(private_data->item_tree[WSLID], npos);
650     browser_slidmove(w, w, xitk_slider_get_pos(private_data->item_tree[WSLID]));
651 
652   }
653 }
xitk_browser_page_down(xitk_widget_t * w,void * data)654 void xitk_browser_page_down(xitk_widget_t *w, void *data) {
655   browser_private_data_t *private_data;
656 
657   if(w && (((w->type & WIDGET_GROUP_MASK) & WIDGET_GROUP_BROWSER) &&
658 	   (w->type & WIDGET_GROUP_WIDGET))) {
659     int max, pos, npos, vis;
660 
661     private_data = (browser_private_data_t *) w->private_data;
662 
663     max = xitk_slider_get_max(private_data->item_tree[WSLID]);
664     npos = pos = xitk_slider_get_pos(private_data->item_tree[WSLID]);
665     vis = private_data->max_length;
666 
667     if((pos + vis) <= max)
668       npos += vis;
669     else
670       npos = max;
671 
672     xitk_slider_set_pos(private_data->item_tree[WSLID], npos);
673     browser_slidmove(w, w, xitk_slider_get_pos(private_data->item_tree[WSLID]));
674 
675   }
676 }
677 
678 /**
679  * slide Down (extern).
680  */
xitk_browser_step_down(xitk_widget_t * w,void * data)681 void xitk_browser_step_down(xitk_widget_t *w, void *data) {
682   browser_private_data_t *private_data;
683 
684   if(w && (((w->type & WIDGET_GROUP_MASK) & WIDGET_GROUP_BROWSER) &&
685 	   (w->type & WIDGET_GROUP_WIDGET))) {
686 
687     private_data = (browser_private_data_t *) w->private_data;
688 
689     xitk_slider_make_step(private_data->item_tree[WSLID]);
690     browser_slidmove(w, w, xitk_slider_get_pos(private_data->item_tree[WSLID]));
691 
692   }
693 }
694 
695 
696 /**
697  * slide left (extern).
698  */
xitk_browser_step_left(xitk_widget_t * w,void * data)699 void xitk_browser_step_left(xitk_widget_t *w, void *data) {
700   browser_private_data_t *private_data;
701 
702   if(w && (((w->type & WIDGET_GROUP_MASK) & WIDGET_GROUP_BROWSER) &&
703 	   (w->type & WIDGET_GROUP_WIDGET))) {
704     private_data = (browser_private_data_t *) w->private_data;
705 
706     xitk_slider_make_backstep(private_data->item_tree[WSLIDH]);
707     browser_hslidmove(w, w, xitk_slider_get_pos(private_data->item_tree[WSLIDH]));
708 
709   }
710 }
711 /**
712  * slide right (extern).
713  */
xitk_browser_step_right(xitk_widget_t * w,void * data)714 void xitk_browser_step_right(xitk_widget_t *w, void *data) {
715   browser_private_data_t *private_data;
716 
717   if(w && (((w->type & WIDGET_GROUP_MASK) & WIDGET_GROUP_BROWSER) &&
718 	   (w->type & WIDGET_GROUP_WIDGET))) {
719 
720     private_data = (browser_private_data_t *) w->private_data;
721 
722     xitk_slider_make_step(private_data->item_tree[WSLIDH]);
723     browser_hslidmove(w, w, xitk_slider_get_pos(private_data->item_tree[WSLIDH]));
724 
725   }
726 }
727 
browser_left(xitk_widget_t * w,void * data)728 static void browser_left(xitk_widget_t *w, void *data) {
729   browser_private_data_t *private_data;
730 
731   if(w && ((w->type & WIDGET_TYPE_MASK) == WIDGET_TYPE_BUTTON)) {
732     private_data = (browser_private_data_t *) ((xitk_widget_t*)data)->private_data;
733 
734     xitk_slider_make_backstep(private_data->item_tree[WSLIDH]);
735     browser_hslidmove(w, data, xitk_slider_get_pos(private_data->
736 						   item_tree[WSLIDH]));
737   }
738 }
browser_right(xitk_widget_t * w,void * data)739 static void browser_right(xitk_widget_t *w, void *data) {
740   browser_private_data_t *private_data;
741 
742   if(w && ((w->type & WIDGET_TYPE_MASK) == WIDGET_TYPE_BUTTON)) {
743     private_data = (browser_private_data_t *) ((xitk_widget_t*)data)->private_data;
744 
745     xitk_slider_make_step(private_data->item_tree[WSLIDH]);
746     browser_hslidmove(w, data, xitk_slider_get_pos(private_data->
747 						   item_tree[WSLIDH]));
748   }
749 }
750 
751 /**
752  * Handle list selections
753  */
browser_select(xitk_widget_t * w,void * data,int state)754 static void browser_select(xitk_widget_t *w, void *data, int state) {
755   browser_private_data_t *private_data;
756   int                     i, btn_selected;
757 
758   if(w && ((w->type & WIDGET_TYPE_MASK) == WIDGET_TYPE_LABELBUTTON)) {
759 
760     private_data = (browser_private_data_t*) ((btnlist_t*)data)->itemlist->private_data;
761 
762     if(private_data->dbl_click_callback || private_data->callback) {
763       if(!strcasecmp((xitk_labelbutton_get_label(private_data-> item_tree[(int)((btnlist_t*)data)->sel])), "")) {
764 	xitk_labelbutton_set_state((xitk_widget_t*)(private_data->item_tree[(int)((btnlist_t*)data)->sel]), 0);
765       }
766 
767       for(i = WBSTART; i < private_data->max_length+WBSTART; i++) {
768 	if((xitk_labelbutton_get_state(private_data->item_tree[i])) && (i != ((btnlist_t*)data)->sel)) {
769 	  xitk_labelbutton_set_state(private_data->item_tree[i], 0);
770 	}
771       }
772 
773       if((btn_selected = xitk_browser_get_current_selected(((btnlist_t*)data)->itemlist)) > -1) {
774 	int cb2 = 0;
775 	/*  Callback call */
776 	private_data->jumped = btn_selected;
777 
778 	/* A button is currently selected */
779 	private_data->current_button_clicked = btn_selected;
780 
781 	if(private_data->last_button_clicked == private_data->current_button_clicked) {
782 	  struct timeval old_click_time, tm_diff;
783 	  long int click_diff;
784 
785 	  private_data->last_button_clicked = -1;
786 
787 	  timercpy(&private_data->click_time, &old_click_time);
788 	  gettimeofday(&private_data->click_time, 0);
789 	  timersub(&private_data->click_time, &old_click_time, &tm_diff);
790 	  click_diff = (tm_diff.tv_sec * 1000) + (tm_diff.tv_usec / 1000.0);
791 
792 	  /* Ok, double click occur, call cb */
793 	  if(click_diff < private_data->dbl_click_time) {
794 	    private_data->click_time.tv_sec -= (xitk_get_timer_dbl_click() / 1000.0);
795 	    private_data->click_time.tv_usec -= (xitk_get_timer_dbl_click() * 1000.0);
796 	    if(private_data->dbl_click_callback)
797 	      cb2 = 1;
798 	  }
799 
800 	}
801 	else {
802 	  private_data->last_button_clicked = private_data->current_button_clicked;
803 	}
804 
805 	gettimeofday(&private_data->click_time, 0);
806 
807 	if(private_data->callback)
808 	  private_data->callback(((btnlist_t*)data)->itemlist, private_data->userdata, btn_selected);
809 	if(cb2) {
810 	  private_data->dbl_click_callback(((btnlist_t*)data)->itemlist/*w*/,
811 					   private_data->userdata,
812 					   private_data->current_button_clicked);
813 	}
814 	/*
815 	  if(private_data->last_button_clicked == -1)
816 	  private_data->last_button_clicked = private_data->current_button_clicked;
817 	*/
818 
819       }
820       else if((xitk_browser_get_current_selected(((btnlist_t*)data)->itemlist) < 0)
821 	      && (private_data->current_button_clicked > -1)) {
822 	struct timeval old_click_time, tm_diff;
823 	long int click_diff;
824 	int      cur_clicked = private_data->current_button_clicked;
825 
826 	timercpy(&private_data->click_time, &old_click_time);
827 	gettimeofday(&private_data->click_time, 0);
828 	timersub(&private_data->click_time, &old_click_time, &tm_diff);
829 	click_diff = (tm_diff.tv_sec * 1000) + (tm_diff.tv_usec / 1000.0);
830 
831 	private_data->last_button_clicked = private_data->current_button_clicked;
832 	private_data->current_button_clicked = -1;
833 
834 	gettimeofday(&private_data->click_time, 0);
835 
836 	/* Ok, double click occur, call cb */
837 	if(click_diff < private_data->dbl_click_time) {
838 	  private_data->click_time.tv_sec -= (xitk_get_timer_dbl_click() / 1000.0);
839 	  private_data->click_time.tv_usec -= (xitk_get_timer_dbl_click() * 1000.0);
840 	  if(private_data->dbl_click_callback)
841 	    private_data->dbl_click_callback(((btnlist_t*)data)->itemlist,
842 					     private_data->userdata, cur_clicked);
843 	}
844       }
845 
846     }
847     else {
848       /* If there no callback, release selected button */
849       if((btn_selected = xitk_browser_get_current_selected(((btnlist_t*)data)->itemlist)) > -1) {
850 	xitk_labelbutton_set_state(private_data->item_tree[(int)((btnlist_t*)data)->sel], 0);
851       }
852     }
853   }
854 }
855 
856 /*
857  *
858  */
xitk_browser_get_browser(xitk_widget_t * w)859 xitk_widget_t *xitk_browser_get_browser(xitk_widget_t *w) {
860   xitk_widget_t       *widget = NULL;
861 
862   if(w && ((w->type & WIDGET_GROUP_MASK) & WIDGET_GROUP_BROWSER)) {
863     xitk_widget_list_t  *wl = w->wl;
864 
865     widget = (xitk_widget_t *)wl->list.head.next;
866     while (widget->node.next && (widget != w)) {
867       widget = (xitk_widget_t *)widget->node.next;
868     }
869     while (widget->node.next && (!(((widget->type & WIDGET_GROUP_MASK) & WIDGET_GROUP_BROWSER) &&
870 		       (widget->type & WIDGET_GROUP_WIDGET)))) {
871       widget = (xitk_widget_t *)widget->node.next;
872     }
873   }
874 
875   return widget;
876 }
877 
878 /*
879  * Jump to entry in list which match with the alphanum char key.
880  */
xitk_browser_warp_jump(xitk_widget_t * w,const char * key,int modifier)881 void xitk_browser_warp_jump(xitk_widget_t *w, const char *key, int modifier) {
882   browser_private_data_t *private_data;
883 
884   if(w && (((w->type & WIDGET_GROUP_MASK) & WIDGET_GROUP_BROWSER) &&
885 	   (w->type & WIDGET_GROUP_WIDGET))) {
886 
887     private_data = (browser_private_data_t *) w->private_data;
888 
889     if(((modifier & 0xFFFFFFEF) == MODIFIER_NOMOD) || (modifier & MODIFIER_SHIFT)) {
890       int            jumped;
891       int            start, end, mark;
892       int            focus;
893       widget_event_t event;
894 
895       /* Jump wasn't happend yet */
896       if(private_data->jumped == -1)
897 	jumped = 0;
898       else {
899 	if((private_data->jumped + 1) < private_data->list_length)
900 	  jumped = private_data->jumped + 1;
901 	else
902 	  jumped = 0;
903       }
904 
905       start = jumped;
906       end = ((start - 1) > 0) ? (start - 1) : 0;
907       mark = private_data->list_length;
908 
909 
910       for(; start < mark; start++) {
911 
912 	if(!strncasecmp(private_data->content[start], key, strlen(key))) {
913 
914 	  private_data->jumped = start;
915 
916 	  focus = 0;
917 	  if((private_data->list_length - start) <= private_data->max_length) {
918 
919 	    if(private_data->list_length >= private_data->max_length) {
920 	      focus = private_data->max_length - (private_data->list_length - start);
921 	      start = (private_data->list_length - private_data->max_length);
922 	    }
923 	    else
924 	      focus = start;
925 
926 	  }
927 
928 	  xitk_browser_rebuild_browser(w, start);
929 
930 	  if(private_data->parent_wlist->widget_focused) {
931 
932 	    if((private_data->parent_wlist->widget_focused->type & WIDGET_FOCUSABLE) &&
933 	       private_data->parent_wlist->widget_focused->enable == WIDGET_ENABLE) {
934 
935 	      event.type = WIDGET_EVENT_FOCUS;
936 	      event.focus = FOCUS_LOST;
937 
938 	      (void) private_data->parent_wlist->widget_focused->event(private_data->parent_wlist->widget_focused, &event, NULL);
939 
940 	      private_data->parent_wlist->widget_focused->have_focus = FOCUS_LOST;
941 	    }
942 
943 	    event.type = WIDGET_EVENT_PAINT;
944 
945 	    (void) private_data->parent_wlist->widget_focused->event(private_data->parent_wlist->widget_focused, &event, NULL);
946 
947 	  }
948 
949 	  xitk_browser_set_select(w, focus + start);
950 
951 	  private_data->parent_wlist->widget_focused = private_data->item_tree[WBSTART + focus];
952 
953 	  if((private_data->parent_wlist->widget_focused->type & WIDGET_FOCUSABLE) &&
954 	     private_data->parent_wlist->widget_focused->enable == WIDGET_ENABLE) {
955 
956 	    event.type = WIDGET_EVENT_FOCUS;
957 	    event.focus = FOCUS_RECEIVED;
958 
959 	    (void) private_data->parent_wlist->widget_focused->event(private_data->parent_wlist->widget_focused, &event, NULL);
960 
961 	    private_data->parent_wlist->widget_focused->have_focus = FOCUS_RECEIVED;
962 
963 	  }
964 
965 	  event.type = WIDGET_EVENT_PAINT;
966 	  (void) private_data->parent_wlist->widget_focused->event(private_data->parent_wlist->widget_focused, &event, NULL);
967 
968 	  return;
969 	}
970 
971 	if(((start + 1) == mark) && end) {
972 	  mark = end;
973 	  start = end = -1;
974 	}
975       }
976 
977       private_data->jumped = -1;
978     }
979   }
980 }
981 
982 /**
983  * Create the list browser
984  */
_xitk_browser_create(xitk_widget_list_t * wl,xitk_skin_config_t * skonfig,xitk_browser_widget_t * br,int x,int y,int width,int height,const char * skin_element_name,xitk_widget_t * mywidget,browser_private_data_t * _private_data,int visible,int enable)985 static xitk_widget_t *_xitk_browser_create(xitk_widget_list_t *wl,
986 					   xitk_skin_config_t *skonfig, xitk_browser_widget_t *br,
987 					   int x, int y, int width, int height,
988 					   const char *skin_element_name,
989 					   xitk_widget_t *mywidget,
990 					   browser_private_data_t *_private_data,
991 					   int visible, int enable) {
992   browser_private_data_t        *private_data = _private_data;
993   xitk_button_widget_t           b;
994   xitk_labelbutton_widget_t      lb;
995   xitk_slider_widget_t           sl;
996 
997   XITK_CHECK_CONSTITENCY(br);
998 
999   XITK_WIDGET_INIT(&b, br->imlibdata);
1000   XITK_WIDGET_INIT(&lb, br->imlibdata);
1001   XITK_WIDGET_INIT(&sl, br->imlibdata);
1002 
1003   private_data->bWidget              = mywidget;
1004   private_data->imlibdata            = br->imlibdata;
1005   private_data->skin_element_name    = (skin_element_name == NULL) ? NULL : strdup(br->browser.skin_element_name);
1006   private_data->jumped               = -1;
1007   private_data->content              = (char **)br->browser.entries;
1008   private_data->shortcuts_content    = NULL;
1009   private_data->list_length          = br->browser.num_entries;
1010   private_data->max_length           = br->browser.max_displayed_entries;
1011 
1012   private_data->dbl_click_time       = xitk_get_timer_dbl_click();
1013   gettimeofday(&private_data->click_time, 0);
1014 
1015   if(br->dbl_click_callback)
1016     private_data->dbl_click_callback = br->dbl_click_callback;
1017   else
1018     private_data->dbl_click_callback = NULL;
1019 
1020   private_data->current_button_clicked = -1;
1021   private_data->last_button_clicked    = -1;
1022 
1023   private_data->parent_wlist           = br->parent_wlist;
1024 
1025   private_data->callback               = br->callback;
1026   private_data->userdata               = br->userdata;
1027 
1028   private_data->need_h_slider          = 0;
1029   private_data->labels_offset          = 0;
1030 
1031   mywidget->private_data               = private_data;
1032 
1033   mywidget->wl                         = wl;
1034 
1035   mywidget->enable                     = enable;
1036   mywidget->running                    = 1;
1037   mywidget->visible                    = visible;
1038   mywidget->have_focus                 = FOCUS_LOST;
1039 
1040   mywidget->imlibdata                  = private_data->imlibdata;
1041   mywidget->x                          = x;
1042   mywidget->y                          = y;
1043   mywidget->width                      = width;
1044   mywidget->height                     = height;
1045   mywidget->type                       = WIDGET_GROUP | WIDGET_GROUP_WIDGET | WIDGET_GROUP_BROWSER;
1046   mywidget->event                      = notify_event;
1047   mywidget->tips_timeout               = 0;
1048   mywidget->tips_string                = NULL;
1049 
1050   return mywidget;
1051 }
1052 
1053 /**
1054  * Create the list browser
1055  */
xitk_browser_create(xitk_widget_list_t * wl,xitk_skin_config_t * skonfig,xitk_browser_widget_t * br)1056 xitk_widget_t *xitk_browser_create(xitk_widget_list_t *wl,
1057 				   xitk_skin_config_t *skonfig, xitk_browser_widget_t *br) {
1058   xitk_widget_t                 *mywidget;
1059   browser_private_data_t        *private_data;
1060   xitk_button_widget_t           b;
1061   xitk_labelbutton_widget_t      lb;
1062   xitk_slider_widget_t           sl;
1063 
1064   XITK_CHECK_CONSTITENCY(br);
1065 
1066   XITK_WIDGET_INIT(&b, br->imlibdata);
1067   XITK_WIDGET_INIT(&lb, br->imlibdata);
1068   XITK_WIDGET_INIT(&sl, br->imlibdata);
1069 
1070   mywidget = (xitk_widget_t *) xitk_xmalloc(sizeof(xitk_widget_t));
1071   private_data = (browser_private_data_t *) xitk_xmalloc(sizeof(browser_private_data_t));
1072   private_data->skonfig = skonfig;
1073 
1074 
1075   br->browser.max_displayed_entries = xitk_skin_get_browser_entries(skonfig,
1076 								    br->browser.skin_element_name);
1077 
1078   {
1079 
1080     int x, y, i;
1081 
1082     x = xitk_skin_get_coord_x(skonfig, br->browser.skin_element_name);
1083     y = xitk_skin_get_coord_y(skonfig, br->browser.skin_element_name);
1084 
1085     for(i = WBSTART; i < (EXTRA_BTNS + WBSTART); i++) {
1086 
1087       private_data->bt[i]           = (btnlist_t *) xitk_xmalloc(sizeof(btnlist_t));
1088       private_data->bt[i]->itemlist = mywidget;
1089       private_data->bt[i]->sel      = i;
1090 
1091       lb.button_type       = RADIO_BUTTON;
1092       lb.align             = ALIGN_DEFAULT;
1093       lb.label             = "";
1094       lb.callback          = NULL;
1095       lb.state_callback    = browser_select;
1096       lb.userdata          = (void *)(private_data->bt[i]);
1097       lb.skin_element_name = br->browser.skin_element_name;
1098       private_data->item_tree[i] = xitk_labelbutton_create (br->parent_wlist, skonfig, &lb);
1099       xitk_dlist_add_tail (&br->parent_wlist->list, &private_data->item_tree[i]->node);
1100       private_data->item_tree[i]->type |= WIDGET_GROUP | WIDGET_GROUP_BROWSER;
1101 
1102       xitk_disable_widget(private_data->item_tree[i]);
1103       xitk_hide_widget(private_data->item_tree[i]);
1104 
1105       (void) xitk_set_widget_pos(private_data->item_tree[i], x, y);
1106 
1107       y += xitk_get_widget_height(private_data->item_tree[i]) + 1;
1108     }
1109 
1110     for(i = WBSTART; i < (br->browser.max_displayed_entries + WBSTART); i++)
1111       xitk_enable_and_show_widget(private_data->item_tree[i]);
1112 
1113   }
1114 
1115   b.skin_element_name = br->arrow_up.skin_element_name;
1116   b.callback          = browser_up;
1117   b.userdata          = (void *)mywidget;
1118   private_data->item_tree[WBUP] = xitk_button_create (br->parent_wlist, skonfig, &b);
1119   xitk_dlist_add_tail (&br->parent_wlist->list, &private_data->item_tree[WBUP]->node);
1120   private_data->item_tree[WBUP]->type |= WIDGET_GROUP | WIDGET_GROUP_BROWSER;
1121 
1122   sl.min                      = 0;
1123   sl.max                      = (br->browser.num_entries > (br->browser.max_displayed_entries-1) ? br->browser.num_entries-1 : 0);
1124   sl.step                     = 1;
1125   sl.skin_element_name        = br->slider.skin_element_name;
1126   sl.callback                 = browser_slidmove;
1127   sl.userdata                 = (void*)mywidget;
1128   sl.motion_callback          = browser_slidmove;
1129   sl.motion_userdata          = (void*)mywidget;
1130   private_data->item_tree[WSLID] = xitk_slider_create (br->parent_wlist, skonfig, &sl);
1131   xitk_dlist_add_tail (&br->parent_wlist->list, &private_data->item_tree[WSLID]->node);
1132   private_data->item_tree[WSLID]->type |= WIDGET_GROUP | WIDGET_GROUP_BROWSER;
1133 
1134   xitk_slider_set_to_max(private_data->item_tree[WSLID]);
1135 
1136   b.skin_element_name = br->arrow_dn.skin_element_name;
1137   b.callback          = browser_down;
1138   b.userdata          = (void *)mywidget;
1139   private_data->item_tree[WBDN] = xitk_button_create (br->parent_wlist, skonfig, &b);
1140   xitk_dlist_add_tail (&br->parent_wlist->list, &private_data->item_tree[WBDN]->node);
1141   private_data->item_tree[WBDN]->type |= WIDGET_GROUP | WIDGET_GROUP_BROWSER;
1142 
1143   b.skin_element_name = br->arrow_left.skin_element_name;
1144   b.callback          = browser_left;
1145   b.userdata          = (void *)mywidget;
1146   private_data->item_tree[WBLF] = xitk_button_create (br->parent_wlist, skonfig, &b);
1147   xitk_dlist_add_tail (&br->parent_wlist->list, &private_data->item_tree[WBLF]->node);
1148   private_data->item_tree[WBLF]->type |= WIDGET_GROUP | WIDGET_GROUP_BROWSER;
1149 
1150   sl.min                      = 0;
1151   sl.max                      = 1;
1152   sl.step                     = 1;
1153   sl.skin_element_name        = br->slider_h.skin_element_name;
1154   sl.callback                 = browser_hslidmove;
1155   sl.userdata                 = (void*)mywidget;
1156   sl.motion_callback          = browser_hslidmove;
1157   sl.motion_userdata          = (void*)mywidget;
1158   private_data->item_tree[WSLIDH] = xitk_slider_create (br->parent_wlist, skonfig, &sl);
1159   xitk_dlist_add_tail (&br->parent_wlist->list, &private_data->item_tree[WSLIDH]->node);
1160   private_data->item_tree[WSLIDH]->type |= WIDGET_GROUP | WIDGET_GROUP_BROWSER;
1161 
1162   xitk_slider_reset(private_data->item_tree[WSLIDH]);
1163 
1164   b.skin_element_name = br->arrow_right.skin_element_name;
1165   b.callback          = browser_right;
1166   b.userdata          = (void *)mywidget;
1167   private_data->item_tree[WBRT] = xitk_button_create (br->parent_wlist, skonfig, &b);
1168   xitk_dlist_add_tail (&br->parent_wlist->list, &private_data->item_tree[WBRT]->node);
1169   private_data->item_tree[WBRT]->type |= WIDGET_GROUP | WIDGET_GROUP_BROWSER;
1170 
1171   return _xitk_browser_create(wl, skonfig, br,
1172 			      0, 0, 0, 0, br->browser.skin_element_name, mywidget, private_data,
1173 			      (xitk_skin_get_visibility(skonfig, br->browser.skin_element_name)) ? 1 : -1,
1174 			      xitk_skin_get_enability(skonfig, br->browser.skin_element_name));
1175 }
1176 
1177 /*
1178  *
1179  */
xitk_noskin_browser_create(xitk_widget_list_t * wl,xitk_browser_widget_t * br,GC gc,int x,int y,int itemw,int itemh,int slidw,const char * fontname)1180 xitk_widget_t *xitk_noskin_browser_create(xitk_widget_list_t *wl,
1181 					  xitk_browser_widget_t *br, GC gc, int x, int y,
1182 					  int itemw, int itemh, int slidw, const char *fontname) {
1183   xitk_widget_t              *mywidget;
1184   browser_private_data_t     *private_data;
1185   xitk_button_widget_t        b;
1186   xitk_labelbutton_widget_t   lb;
1187   xitk_slider_widget_t        sl;
1188   int                         btnh = (itemh - (itemh /2)) < slidw ? slidw : (itemh - (itemh /2));
1189 
1190   XITK_CHECK_CONSTITENCY(br);
1191   XITK_WIDGET_INIT(&b, br->imlibdata);
1192   XITK_WIDGET_INIT(&lb, br->imlibdata);
1193   XITK_WIDGET_INIT(&sl, br->imlibdata);
1194 
1195   mywidget = (xitk_widget_t *) xitk_xmalloc(sizeof(xitk_widget_t));
1196   private_data = (browser_private_data_t *) xitk_xmalloc(sizeof(browser_private_data_t));
1197   private_data->skonfig = NULL;
1198 
1199   {
1200     int            ix = x, iy = y, i;
1201     xitk_image_t  *wimage;
1202 
1203     for(i = WBSTART; i < (br->browser.max_displayed_entries+WBSTART); i++) {
1204 
1205       private_data->bt[i]           = (btnlist_t *) xitk_xmalloc(sizeof(btnlist_t));
1206       private_data->bt[i]->itemlist = mywidget;
1207       private_data->bt[i]->sel      = i;
1208 
1209       lb.button_type       = RADIO_BUTTON;
1210       lb.label             = "";
1211       lb.align             = ALIGN_LEFT;
1212       lb.callback          = NULL;
1213       lb.state_callback    = browser_select;
1214       lb.userdata          = (void *)(private_data->bt[i]);
1215       lb.skin_element_name = NULL;
1216       private_data->item_tree[i] = xitk_noskin_labelbutton_create (br->parent_wlist, &lb,
1217         ix, iy, itemw, itemh, "Black", "Black", "White", fontname);
1218       xitk_dlist_add_tail (&br->parent_wlist->list, &private_data->item_tree[i]->node);
1219       private_data->item_tree[i]->type |= WIDGET_GROUP | WIDGET_GROUP_BROWSER;
1220 
1221       wimage = xitk_get_widget_foreground_skin(private_data->item_tree[i]);
1222       if(wimage)
1223 	draw_flat_three_state(br->imlibdata, wimage);
1224 
1225       (void) xitk_set_widget_pos(private_data->item_tree[i], ix, iy);
1226 
1227       iy += itemh;
1228 
1229     }
1230   }
1231 
1232   b.skin_element_name = NULL;
1233   b.callback          = browser_up;
1234   b.userdata          = (void *)mywidget;
1235   private_data->item_tree[WBUP] = xitk_noskin_button_create (br->parent_wlist, &b,
1236     x + itemw, y + 0, slidw, btnh);
1237   xitk_dlist_add_tail (&br->parent_wlist->list, &private_data->item_tree[WBUP]->node);
1238   private_data->item_tree[WBUP]->type |= WIDGET_GROUP | WIDGET_GROUP_BROWSER;
1239 
1240   { /* Draw arrow in button */
1241     xitk_image_t *wimage = xitk_get_widget_foreground_skin(private_data->item_tree[WBUP]);
1242 
1243     if(wimage)
1244       draw_arrow_up(b.imlibdata, wimage);
1245 
1246   }
1247 
1248   sl.min                      = 0;
1249   sl.max                      = (br->browser.num_entries > (br->browser.max_displayed_entries-1) ? br->browser.num_entries-1 : 0);
1250   sl.step                     = 1;
1251   sl.skin_element_name        = NULL;
1252   sl.callback                 = browser_slidmove;
1253   sl.userdata                 = (void*)mywidget;
1254   sl.motion_callback          = browser_slidmove;
1255   sl.motion_userdata          = (void*)mywidget;
1256   private_data->item_tree[WSLID] = xitk_noskin_slider_create (br->parent_wlist, &sl,
1257     x + itemw, y + btnh, slidw, (itemh * br->browser.max_displayed_entries) - (btnh * 2), XITK_VSLIDER);
1258   xitk_dlist_add_tail (&br->parent_wlist->list, &private_data->item_tree[WSLID]->node);
1259   private_data->item_tree[WSLID]->type |= WIDGET_GROUP | WIDGET_GROUP_BROWSER;
1260 
1261   xitk_slider_set_to_max(private_data->item_tree[WSLID]);
1262 
1263   b.skin_element_name = NULL;
1264   b.callback          = browser_down;
1265   b.userdata          = (void *)mywidget;
1266   private_data->item_tree[WBDN] = xitk_noskin_button_create (br->parent_wlist, &b,
1267     x + itemw, y + ((itemh * br->browser.max_displayed_entries) - btnh), slidw, btnh);
1268   xitk_dlist_add_tail (&br->parent_wlist->list, &private_data->item_tree[WBDN]->node);
1269   private_data->item_tree[WBDN]->type |= WIDGET_GROUP | WIDGET_GROUP_BROWSER;
1270 
1271   { /* Draw arrow in button */
1272     xitk_image_t *wimage = xitk_get_widget_foreground_skin(private_data->item_tree[WBDN]);
1273 
1274     if(wimage)
1275       draw_arrow_down(b.imlibdata, wimage);
1276 
1277   }
1278 
1279   b.skin_element_name = NULL;
1280   b.callback          = browser_left;
1281   b.userdata          = (void *)mywidget;
1282   private_data->item_tree[WBLF] = xitk_noskin_button_create (br->parent_wlist, &b,
1283     x, y + (itemh * br->browser.max_displayed_entries), slidw, btnh);
1284   xitk_dlist_add_tail (&br->parent_wlist->list, &private_data->item_tree[WBLF]->node);
1285   private_data->item_tree[WBLF]->type |= WIDGET_GROUP | WIDGET_GROUP_BROWSER;
1286 
1287   { /* Draw arrow in button */
1288     xitk_image_t *wimage = xitk_get_widget_foreground_skin(private_data->item_tree[WBLF]);
1289 
1290     if(wimage)
1291       draw_arrow_left(b.imlibdata, wimage);
1292 
1293   }
1294 
1295   sl.min                      = 0;
1296   sl.max                      = 1;
1297   sl.step                     = 1;
1298   sl.skin_element_name        = NULL;
1299   sl.callback                 = browser_hslidmove;
1300   sl.userdata                 = (void*)mywidget;
1301   sl.motion_callback          = browser_hslidmove;
1302   sl.motion_userdata          = (void*)mywidget;
1303   private_data->item_tree[WSLIDH] = xitk_noskin_slider_create (br->parent_wlist, &sl,
1304     x + btnh, y + (itemh * br->browser.max_displayed_entries), (itemw - (btnh * 2)), slidw, XITK_HSLIDER);
1305   xitk_dlist_add_tail (&br->parent_wlist->list, &private_data->item_tree[WSLIDH]->node);
1306   private_data->item_tree[WSLIDH]->type |= WIDGET_GROUP | WIDGET_GROUP_BROWSER;
1307 
1308   xitk_slider_reset(private_data->item_tree[WSLIDH]);
1309 
1310   b.skin_element_name = NULL;
1311   b.callback          = browser_right;
1312   b.userdata          = (void *)mywidget;
1313   private_data->item_tree[WBRT] = xitk_noskin_button_create (br->parent_wlist, &b,
1314     x + (itemw - btnh), y + (itemh * br->browser.max_displayed_entries), slidw, btnh);
1315   xitk_dlist_add_tail (&br->parent_wlist->list, &private_data->item_tree[WBRT]->node);
1316   private_data->item_tree[WBRT]->type |= WIDGET_GROUP | WIDGET_GROUP_BROWSER;
1317 
1318   { /* Draw arrow in button */
1319     xitk_image_t *wimage = xitk_get_widget_foreground_skin(private_data->item_tree[WBRT]);
1320 
1321     if(wimage)
1322       draw_arrow_right(b.imlibdata, wimage);
1323 
1324   }
1325 
1326   return _xitk_browser_create(wl, NULL, br, x, y,
1327 			      (itemw + slidw), (itemh * br->browser.max_displayed_entries) + slidw,
1328 			      NULL, mywidget, private_data, 0, 0);
1329 }
1330 
1331