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  */
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25 
26 #include <stdio.h>
27 #include <X11/Xlib.h>
28 #include <X11/Xutil.h>
29 #include <X11/keysym.h>
30 
31 #include "common.h"
32 
33 #include <xine/list.h>
34 #ifdef HAVE_XINE_LIST_NEXT_VALUE
35 #  define _xine_list_next_value(_xlnv_list,_xlnv_ite) xine_list_next_value (_xlnv_list, _xlnv_ite)
36 #else
_xine_list_next_value(xine_list_t * list,xine_list_iterator_t * ite)37 static inline void *_xine_list_next_value (xine_list_t *list, xine_list_iterator_t *ite) {
38   if (*ite)
39     *ite = xine_list_next (list, *ite);
40   else
41     *ite = xine_list_front (list);
42   return *ite ? xine_list_get_value (list, *ite) : NULL;
43 }
44 #endif
45 
46 
47 #define WINDOW_WIDTH             630
48 #define WINDOW_HEIGHT            530
49 
50 #define FRAME_WIDTH              541
51 #define FRAME_HEIGHT             44
52 
53 #define MAX_DISPLAY_WIDGETS      8
54 
55 #define NORMAL_CURS              0
56 #define WAIT_CURS                1
57 
58 #define DISABLE_ME(wtriplet) do {                                                               \
59     if((wtriplet)->frame)                                                                       \
60       xitk_disable_and_hide_widget((wtriplet)->frame);                                          \
61                                                                                                 \
62     if((wtriplet)->label) {                                                                     \
63       xitk_disable_and_hide_widget((wtriplet)->label);                                          \
64       xitk_disable_widget_tips((wtriplet)->label);		 	                        \
65     }                                                                                           \
66     if((wtriplet)->widget) {                                                                    \
67       xitk_disable_and_hide_widget((wtriplet)->widget);                                         \
68       xitk_disable_widget_tips((wtriplet)->widget);			                        \
69     }                                                                                           \
70   } while(0)
71 
72 
73 typedef struct {
74   xitk_widget_t    *frame;
75   xitk_widget_t    *label;
76   xitk_widget_t    *widget;
77   int               changed;
78   xine_cfg_entry_t  cfg;
79 } widget_triplet_t;
80 
81 struct xui_setup_st {
82   gGui_t               *gui;
83 
84   xitk_window_t        *xwin;
85   xitk_widget_list_t   *widget_list;
86 
87   int                   running;
88   int                   visible;
89 
90   xitk_widget_t        *tabs;
91   xitk_widget_t        *ok;
92 
93   char                 *sections[20];
94   int                   num_sections;
95 
96   /* Store widgets, this is needed to free them on tabs switching */
97   xine_list_t          *widgets;
98 
99   xitk_widget_t        *slider_wg;
100   widget_triplet_t     *wg[1024]; /* I hope that will not be reached, never */
101   int                   num_wg;
102   int                   first_displayed;
103 
104   xitk_register_key_t   kreg;
105 
106   int                   th; /* Tabs height */
107   int                   fh; /* Font height */
108 };
109 
110 static void setup_change_section (xitk_widget_t *, void *, int);
111 
add_widget_to_list(xui_setup_t * setup,xitk_widget_t * w)112 static void add_widget_to_list (xui_setup_t *setup, xitk_widget_t *w) {
113   xine_list_push_back (setup->widgets, w);
114 }
115 
116 /*
117  * Leaving setup panel, release memory.
118  */
setup_exit(xitk_widget_t * w,void * data)119 static void setup_exit (xitk_widget_t *w, void *data) {
120   xui_setup_t *setup = data;
121   window_info_t wi;
122 
123   (void)w;
124   if (!setup)
125     return;
126   /*
127   if (!setup->running)
128     return;
129   */
130   setup->running = 0;
131   setup->visible = 0;
132 
133   if ((xitk_get_window_info (setup->kreg, &wi))) {
134     config_update_num ("gui.setup_x", wi.x);
135     config_update_num ("gui.setup_y", wi.y);
136     WINDOW_INFO_ZERO (&wi);
137   }
138 
139   xitk_unregister_event_handler (&setup->kreg);
140 
141   xitk_destroy_widgets (setup->widget_list);
142   xitk_window_destroy_window (setup->gui->imlib_data, setup->xwin);
143 
144   setup->xwin = NULL;
145   /* xitk_dlist_init (&setup->widget_list->list); */
146   xine_list_delete (setup->widgets);
147 
148   setup->gui->x_lock_display (setup->gui->display);
149   XFreeGC (setup->gui->display, (XITK_WIDGET_LIST_GC (setup->widget_list)));
150   setup->gui->x_unlock_display (setup->gui->display);
151 
152   XITK_WIDGET_LIST_FREE (setup->widget_list);
153 
154   try_to_set_input_focus (setup->gui->video_window);
155 
156   setup->gui->setup = NULL;
157   free (setup);
158 }
159 
setup_show_tips(xui_setup_t * setup,int enabled,unsigned long timeout)160 void setup_show_tips (xui_setup_t *setup, int enabled, unsigned long timeout) {
161   if (!setup)
162     return;
163   if (setup->running) {
164     if (enabled)
165       xitk_set_widgets_tips_timeout (setup->widget_list, timeout);
166     else
167       xitk_disable_widgets_tips (setup->widget_list);
168   }
169 }
170 
setup_update_tips_timeout(xui_setup_t * setup,unsigned long timeout)171 void setup_update_tips_timeout (xui_setup_t *setup, unsigned long timeout) {
172   if (!setup)
173     return;
174   if (setup->running)
175     xitk_set_widgets_tips_timeout (setup->widget_list, timeout);
176 }
177 
178 /*
179  * return 1 if setup panel is ON
180  */
setup_is_running(xui_setup_t * setup)181 int setup_is_running (xui_setup_t *setup) {
182   return setup ? setup->running : 0;
183 }
184 
185 /*
186  * Return 1 if setup panel is visible
187  */
setup_is_visible(xui_setup_t * setup)188 int setup_is_visible (xui_setup_t *setup) {
189   if (!setup)
190     return 0;
191   if (setup->running) {
192     if (setup->gui->use_root_window)
193       return xitk_is_window_visible (setup->gui->display, xitk_window_get_window (setup->xwin));
194     else
195       return setup->visible && xitk_is_window_visible (setup->gui->display, xitk_window_get_window (setup->xwin));
196   }
197   return 0;
198 }
199 
200 /*
201  * Raise setup->xwin
202  */
setup_raise_window(xui_setup_t * setup)203 void setup_raise_window (xui_setup_t *setup) {
204   if (!setup)
205     return;
206   if (setup->running)
207     raise_window (xitk_window_get_window (setup->xwin), setup->visible, setup->running);
208 }
209 
210 /*
211  * Hide/show the setup panel
212  */
setup_toggle_visibility(xitk_widget_t * w,void * data)213 void setup_toggle_visibility (xitk_widget_t *w, void *data) {
214   xui_setup_t *setup = data;
215   (void)w;
216   if (!setup)
217     return;
218   if (setup->running)
219     toggle_window (xitk_window_get_window (setup->xwin), setup->widget_list,
220       &setup->visible, setup->running);
221 }
222 
setup_apply(xitk_widget_t * w,void * data)223 static void setup_apply (xitk_widget_t *w, void *data) {
224   xui_setup_t *setup = data;
225   int need_restart = 0;
226 
227   (void)w;
228   if (setup->num_wg > 0) {
229     int i;
230 
231     for (i = 0; i < setup->num_wg; i++) {
232 
233       if (setup->wg[i]->widget) {
234         int type = xitk_get_widget_type (setup->wg[i]->widget);
235 
236         if (setup->wg[i]->changed ||
237           ((type & WIDGET_TYPE_MASK) == WIDGET_TYPE_INPUTTEXT) || (type & WIDGET_GROUP_INTBOX)) {
238           xitk_widget_t *w = setup->wg[i]->widget;
239           int            numval = 0;
240           const char    *strval = NULL;
241 
242 	  if(!need_restart) {
243             if (setup->wg[i]->changed && (!setup->wg[i]->cfg.callback_data && !setup->wg[i]->cfg.callback))
244 	      need_restart = 1;
245 	  }
246 
247           setup->wg[i]->changed = 0;
248 
249 	  switch(type & WIDGET_TYPE_MASK) {
250 	  case WIDGET_TYPE_SLIDER:
251 	    numval = xitk_slider_get_pos(w);
252 	    break;
253 
254 	  case WIDGET_TYPE_CHECKBOX:
255 	    numval = xitk_checkbox_get_state(w);
256 	    break;
257 
258 	  case WIDGET_TYPE_INPUTTEXT:
259 	    strval = xitk_inputtext_get_text(w);
260 	    if(!strcmp(strval, setup->wg[i]->cfg.str_value))
261 	      continue;
262 	    break;
263 
264 	  default:
265 	    if(type & WIDGET_GROUP_COMBO)
266 	      numval = xitk_combo_get_current_selected(w);
267 	    else if(type & WIDGET_GROUP_INTBOX) {
268 	      numval = xitk_intbox_get_value(w);
269               if (numval == setup->wg[i]->cfg.num_value)
270 		continue;
271 	    }
272 
273 	    break;
274 	  }
275 
276           switch (setup->wg[i]->cfg.type) {
277 	  case XINE_CONFIG_TYPE_STRING:
278             config_update_string ((char *)setup->wg[i]->cfg.key, strval);
279 	    break;
280 	  case XINE_CONFIG_TYPE_ENUM:
281 	  case XINE_CONFIG_TYPE_NUM:
282 	  case XINE_CONFIG_TYPE_BOOL:
283 	  case XINE_CONFIG_TYPE_RANGE:
284             config_update_num ((char *)setup->wg[i]->cfg.key, numval);
285 	    break;
286 	  case XINE_CONFIG_TYPE_UNKNOWN:
287 	    break;
288 	  }
289 	}
290       }
291     }
292     xine_config_save (setup->gui->xine, __xineui_global_config_file);
293 
294     if(w != setup->ok) {
295       int section = xitk_tabs_get_current_selected (setup->tabs);
296       if (section >= 0) {
297         setup_change_section (setup->tabs, setup, section);
298       }
299     }
300 
301     if(need_restart) {
302       xitk_window_t *xw;
303 
304       xw = xitk_window_dialog_ok (setup->gui->imlib_data, _("Important Notice"),
305 				 NULL, NULL,
306 				 ALIGN_CENTER,
307 				 _("You changed some configuration value which require"
308 				   " to restart xine to take effect."));
309       if (!setup->gui->use_root_window && setup->gui->video_display == setup->gui->display) {
310         setup->gui->x_lock_display (setup->gui->display);
311         XSetTransientForHint (setup->gui->display, xitk_window_get_window(xw), setup->gui->video_window);
312         setup->gui->x_unlock_display (setup->gui->display);
313       }
314       layer_above_video(xitk_window_get_window(xw));
315     }
316 
317   }
318 }
319 
setup_set_cursor(xui_setup_t * setup,int state)320 static void setup_set_cursor (xui_setup_t *setup, int state) {
321   if (setup->running) {
322     if(state == WAIT_CURS)
323       xitk_cursors_define_window_cursor (setup->gui->display, (xitk_window_get_window (setup->xwin)), xitk_cursor_watch);
324     else
325       xitk_cursors_restore_window_cursor (setup->gui->display, (xitk_window_get_window (setup->xwin)));
326   }
327 }
328 
setup_ok(xitk_widget_t * w,void * data)329 static void setup_ok (xitk_widget_t *w, void *data) {
330   setup_apply(w, data);
331   setup_exit(w, data);
332 }
333 
334 /*
335  *
336  */
setup_clear_tab(xui_setup_t * setup)337 static void setup_clear_tab (xui_setup_t *setup) {
338   xitk_image_t *im;
339 
340   im = xitk_image_create_image (setup->gui->imlib_data, (WINDOW_WIDTH - 30),
341     (MAX_DISPLAY_WIDGETS * (FRAME_HEIGHT + 3) - 3 + 3 + 30));
342 
343   draw_outter (setup->gui->imlib_data, im->image, im->width, im->height);
344 
345   setup->gui->x_lock_display (setup->gui->display);
346   XCopyArea (setup->gui->display, im->image->pixmap, (xitk_window_get_window(setup->xwin)),
347     (XITK_WIDGET_LIST_GC (setup->widget_list)), 0, 0, im->width, im->height, 15, (24 + setup->th));
348   setup->gui->x_unlock_display (setup->gui->display);
349 
350   xitk_image_free_image (setup->gui->imlib_data, &im);
351 }
352 
353 /*
354  *
355  */
setup_paint_widgets(xui_setup_t * setup)356 static void setup_paint_widgets (xui_setup_t *setup) {
357   int i;
358   int last;
359   int wx, wy, y = (24 + setup->th + 13);
360   int tips_timeout;
361 
362   tips_timeout = !panel_get_tips_enable (setup->gui->panel) ? 0
363                : panel_get_tips_timeout (setup->gui->panel);
364 
365   last = setup->num_wg <= (setup->first_displayed + MAX_DISPLAY_WIDGETS)
366     ? setup->num_wg : (setup->first_displayed + MAX_DISPLAY_WIDGETS);
367 
368   /* First, disable all widgets */
369   for (i = 0; i < setup->num_wg; i++)
370     DISABLE_ME (setup->wg[i]);
371 
372   /* Move widgets to new position, then display them */
373   for (i = setup->first_displayed; i < last; i++) {
374     widget_triplet_t *t = setup->wg[i];
375 
376     if (t->frame) {
377       xitk_get_widget_pos (t->frame, &wx, &wy);
378       xitk_set_widget_pos (t->frame, wx, y);
379     }
380 
381     y += FRAME_HEIGHT >> 1;
382 
383     if (t->label) {
384       xitk_get_widget_pos (t->label, &wx, &wy);
385       xitk_set_widget_pos (t->label,
386         wx, y + 4 - xitk_get_widget_height (t->label) / 2);
387     }
388 
389     if (t->widget) {
390       xitk_get_widget_pos (t->widget, &wx, &wy);
391       xitk_set_widget_pos (t->widget,
392         wx, y + 4 - xitk_get_widget_height (t->widget) / 2);
393     }
394 
395     if (t->frame)
396       xitk_enable_and_show_widget (t->frame);
397 
398     if (t->label) {
399       xitk_enable_and_show_widget (t->label);
400       if (tips_timeout)
401         xitk_set_widget_tips_timeout (t->label, tips_timeout);
402       else
403         xitk_disable_widget_tips (t->label);
404     }
405     if (t->widget) {
406       xitk_enable_and_show_widget (t->widget);
407       if (tips_timeout)
408         xitk_set_widget_tips_timeout (t->widget, tips_timeout);
409       else
410         xitk_disable_widget_tips (t->widget);
411     }
412 
413     y += (FRAME_HEIGHT >> 1) + 3;
414   }
415 
416   /* Repaint them now */
417   xitk_paint_widget_list (setup->widget_list);
418   setup_set_cursor (setup, NORMAL_CURS);
419 }
420 
421 /*
422  * Handle X events here.
423  */
setup_handle_event(XEvent * event,void * data)424 static void setup_handle_event(XEvent *event, void *data) {
425   xui_setup_t *setup = data;
426 
427   switch(event->type) {
428 
429   case ButtonPress:
430     if(event->xbutton.button == Button4) {
431       xitk_slider_make_step (setup->slider_wg);
432       xitk_slider_callback_exec (setup->slider_wg);
433     }
434     else if(event->xbutton.button == Button5) {
435       xitk_slider_make_backstep (setup->slider_wg);
436       xitk_slider_callback_exec (setup->slider_wg);
437     }
438     break;
439 
440   case KeyPress:
441     {
442       KeySym         mkey;
443       int            modifier;
444 
445       xitk_get_key_modifier(event, &modifier);
446       mkey = xitk_get_key_pressed(event);
447 
448       switch(mkey) {
449 
450       case XK_Up:
451         if (xitk_is_widget_enabled (setup->slider_wg) &&
452 	   (modifier & 0xFFFFFFEF) == MODIFIER_NOMOD) {
453           xitk_slider_make_step (setup->slider_wg);
454           xitk_slider_callback_exec (setup->slider_wg);
455 	  return;
456 	}
457 	break;
458 
459       case XK_Down:
460         if (xitk_is_widget_enabled (setup->slider_wg) &&
461 	   (modifier & 0xFFFFFFEF) == MODIFIER_NOMOD) {
462           xitk_slider_make_backstep (setup->slider_wg);
463           xitk_slider_callback_exec (setup->slider_wg);
464 	  return;
465 	}
466 	break;
467 
468       case XK_Next:
469         if (xitk_is_widget_enabled(setup->slider_wg)) {
470           int pos, max = xitk_slider_get_max (setup->slider_wg);
471 
472           pos = max - (setup->first_displayed + MAX_DISPLAY_WIDGETS);
473           xitk_slider_set_pos (setup->slider_wg, (pos >= 0) ? pos : 0);
474           xitk_slider_callback_exec (setup->slider_wg);
475 	  return;
476 	}
477 	break;
478 
479       case XK_Prior:
480         if (xitk_is_widget_enabled(setup->slider_wg)) {
481           int pos, max = xitk_slider_get_max (setup->slider_wg);
482 
483           pos = max - (setup->first_displayed - MAX_DISPLAY_WIDGETS);
484           xitk_slider_set_pos (setup->slider_wg, (pos <= max) ? pos : max);
485           xitk_slider_callback_exec (setup->slider_wg);
486 	  return;
487 	}
488 	break;
489 
490       case XK_Escape:
491         setup_exit (NULL, setup);
492 	return;
493       }
494       gui_handle_event (event, setup->gui);
495     }
496     break;
497   }
498 }
499 
500 /*
501  *
502  */
setup_add_label(xui_setup_t * setup,int x,int y,int w,const char * str,xitk_simple_callback_t cb,void * data)503 static xitk_widget_t *setup_add_label (xui_setup_t *setup,
504   int x, int y, int w, const char *str, xitk_simple_callback_t cb, void *data) {
505   xitk_label_widget_t   lb;
506   xitk_widget_t        *label;
507 
508   XITK_WIDGET_INIT (&lb, setup->gui->imlib_data);
509 
510   lb.window              = xitk_window_get_window (setup->xwin);
511   lb.gc                  = (XITK_WIDGET_LIST_GC (setup->widget_list));
512   lb.skin_element_name   = NULL;
513   lb.label               = (char *)str;
514   lb.callback            = cb;
515   lb.userdata            = data;
516   label =  xitk_noskin_label_create (setup->widget_list, &lb, x, y, w, setup->fh, fontname);
517   xitk_add_widget (setup->widget_list, label);
518   add_widget_to_list (setup, label);
519 
520   return label;
521 }
522 
523 /*
524  *
525  */
numtype_update(xitk_widget_t * w,void * data,int value)526 static void numtype_update(xitk_widget_t *w, void *data, int value) {
527   widget_triplet_t *triplet = (widget_triplet_t *) data;
528 
529   (void)w;
530   (void)value;
531   triplet->changed = 1;
532 }
533 
534 /*
535  *
536  */
stringtype_update(xitk_widget_t * w,void * data,const char * str)537 static void stringtype_update(xitk_widget_t *w, void *data, const char *str) {
538   widget_triplet_t *triplet = (widget_triplet_t *) data;
539 
540   (void)w;
541   (void)str;
542   triplet->changed = 1;
543 }
544 
setup_add_nothing_available(xui_setup_t * setup,const char * title,int x,int y)545 static widget_triplet_t *setup_add_nothing_available (xui_setup_t *setup, const char *title, int x, int y) {
546   static widget_triplet_t *wt;
547   xitk_widget_t           *frame = NULL;
548   xitk_image_t            *image;
549   xitk_image_widget_t      im;
550 
551   wt = (widget_triplet_t *) calloc(1, sizeof(widget_triplet_t));
552 
553   image = xitk_image_create_image_from_string (setup->gui->imlib_data, tabsfontname,
554     FRAME_WIDTH, ALIGN_CENTER, (char *)title);
555 
556   XITK_WIDGET_INIT (&im, setup->gui->imlib_data);
557   im.skin_element_name = NULL;
558   frame =  xitk_noskin_image_create (setup->widget_list, &im, image, x, y);
559   xitk_add_widget (setup->widget_list, frame);
560   add_widget_to_list (setup, frame);
561 
562   wt->frame = frame;
563   wt->label = NULL;
564   wt->widget = NULL;
565 
566   return wt;
567 }
568 
label_cb(xitk_widget_t * w,void * data)569 static void label_cb(xitk_widget_t *w, void *data) {
570   xitk_widget_t  *checkbox = (xitk_widget_t *) data;
571 
572   (void)w;
573   xitk_checkbox_set_state(checkbox, !(xitk_checkbox_get_state(checkbox)));
574   xitk_checkbox_callback_exec(checkbox);
575 }
576 
577 #define ADD_LABEL(widget,cb,data) do { \
578     int wx, wy; \
579     xitk_widget_t *lbl; \
580     char b[200], *p = b, *e = b + sizeof (b); \
581     p += strlcpy (p, labelkey, e - p); \
582     if (!entry.callback_data && !entry.callback && (p < e)) \
583       strlcpy (p, " (*)", e - p); \
584     xitk_get_widget_pos (widget, &wx, &wy); \
585     wx += xitk_get_widget_width (widget); \
586     lbl = setup_add_label (setup, wx + 20, 0, \
587       (FRAME_WIDTH - (xitk_get_widget_width (widget) + 35)), b, cb, data); \
588     wt->label = lbl; \
589   } while(0)
590 
591 #define _SET_HELP do { \
592   char *help = entry.help ? (char *)entry.help : _("No help available"); \
593   xitk_set_widget_tips_and_timeout (wt->widget, help, tips_timeout); \
594   xitk_set_widget_tips_and_timeout (wt->label, help, tips_timeout); \
595 } while(0)
596 
597 /*
598  *
599  */
setup_section_widgets(xui_setup_t * setup,int s)600 static void setup_section_widgets (xui_setup_t *setup, int s) {
601   int                  y = 0; /* Position will be defined when painting widgets */
602   int                  cfg_err_result;
603   int                  len;
604   char                *section;
605   int                  slidmax = 1;
606   unsigned int         known_types;
607   int                  tips_timeout = panel_get_tips_timeout (setup->gui->panel);
608   xine_cfg_entry_t     entry;
609 
610   known_types = (1 << XINE_CONFIG_TYPE_RANGE)
611               | (1 << XINE_CONFIG_TYPE_STRING)
612               | (1 << XINE_CONFIG_TYPE_ENUM)
613               | (1 << XINE_CONFIG_TYPE_NUM)
614               | (1 << XINE_CONFIG_TYPE_BOOL);
615 
616   xitk_disable_widget (setup->slider_wg);
617   xitk_hide_widget (setup->slider_wg);
618 
619   section = setup->sections[s];
620   len     = strlen (section);
621   memset (&entry, 0, sizeof (entry));
622   cfg_err_result   = xine_config_get_first_entry (setup->gui->xine, &entry);
623 
624   while (cfg_err_result) {
625 
626     if ((entry.exp_level <= setup->gui->experience_level)
627       && !strncmp (entry.key, section, len)
628       && entry.description
629       && ((1 << entry.type) & known_types)) {
630       widget_triplet_t    *wt;
631       xitk_widget_t       *frame = NULL;
632       xitk_image_t        *image;
633       xitk_image_widget_t  im;
634       const char          *labelkey = entry.key + len + 1;
635       int                  x = (WINDOW_WIDTH >> 1) - (FRAME_WIDTH >> 1) - 11;
636 
637       wt = calloc (1, sizeof (*wt));
638       setup->wg[setup->num_wg++] = wt;
639       wt->cfg = entry;
640 
641       image = xitk_image_create_image (setup->gui->imlib_data, FRAME_WIDTH + 1, FRAME_HEIGHT + 1);
642       setup->gui->x_lock_display (setup->gui->display);
643       XSetForeground (setup->gui->display, (XITK_WIDGET_LIST_GC (setup->widget_list)),
644         xitk_get_pixel_color_gray (setup->gui->imlib_data));
645       XFillRectangle (setup->gui->display, image->image->pixmap,
646         (XITK_WIDGET_LIST_GC (setup->widget_list)), 0, 0, image->width, image->height);
647       setup->gui->x_unlock_display (setup->gui->display);
648       draw_inner_frame (setup->gui->imlib_data, image->image, (char *)entry.description,
649         boldfontname, 0, 0, FRAME_WIDTH, FRAME_HEIGHT);
650       XITK_WIDGET_INIT (&im, setup->gui->imlib_data);
651       im.skin_element_name = NULL;
652       frame = xitk_noskin_image_create (setup->widget_list, &im, image, x, y);
653       xitk_add_widget (setup->widget_list, frame);
654       add_widget_to_list (setup, frame);
655       wt->frame = frame;
656       x += 10;
657       y += FRAME_HEIGHT >> 1;
658 
659       switch (entry.type) {
660 
661         case XINE_CONFIG_TYPE_RANGE: /* slider */
662           {
663             xitk_slider_widget_t sl;
664             xitk_widget_t *slider;
665 
666             XITK_WIDGET_INIT (&sl, setup->gui->imlib_data);
667             sl.min                      = entry.range_min;
668             sl.max                      = entry.range_max;
669             sl.step                     = 1;
670             sl.skin_element_name        = NULL;
671             sl.callback                 = NULL;
672             sl.userdata                 = NULL;
673             sl.motion_callback          = numtype_update;
674             sl.motion_userdata          = wt;
675             slider = xitk_noskin_slider_create (setup->widget_list, &sl, x, y, 150, 16, XITK_HSLIDER);
676             xitk_add_widget (setup->widget_list, slider);
677             xitk_slider_set_pos (slider, entry.num_value);
678             ADD_LABEL (slider, NULL, NULL);
679             add_widget_to_list (setup, slider);
680             wt->widget = slider;
681           };
682           _SET_HELP;
683           break;
684 
685         case XINE_CONFIG_TYPE_STRING:
686           {
687             xitk_inputtext_widget_t inp;
688             xitk_widget_t *input;
689 
690             XITK_WIDGET_INIT (&inp, setup->gui->imlib_data);
691             inp.skin_element_name = NULL;
692             inp.text              = entry.str_value;
693             inp.max_length        = 256;
694             inp.callback          = stringtype_update;
695             inp.userdata          = wt;
696             input = xitk_noskin_inputtext_create (setup->widget_list, &inp,
697               x, y, 260, 20, "Black", "Black", fontname);
698             xitk_add_widget (setup->widget_list, input);
699             ADD_LABEL (input, NULL, NULL);
700             add_widget_to_list (setup, input);
701             wt->widget = input;
702           }
703           _SET_HELP;
704           break;
705 
706         case XINE_CONFIG_TYPE_ENUM:
707           {
708             xitk_combo_widget_t cmb;
709             xitk_widget_t *combo, *lw, *bw;
710 
711             XITK_WIDGET_INIT (&cmb, setup->gui->imlib_data);
712             cmb.skin_element_name = NULL;
713             cmb.layer_above       = (is_layer_above ());
714             cmb.parent_wlist      = setup->widget_list;
715             cmb.entries           = (const char **)entry.enum_values;
716             cmb.parent_wkey       = &setup->kreg;
717             cmb.callback          = numtype_update;
718             cmb.userdata          = wt;
719             combo = xitk_noskin_combo_create (setup->widget_list, &cmb, x, y, 260, &lw, &bw);
720             xitk_add_widget (setup->widget_list, combo);
721             xitk_combo_set_select (combo, entry.num_value);
722             ADD_LABEL (combo, NULL, NULL);
723             add_widget_to_list (setup, combo);
724             add_widget_to_list (setup, lw);
725             add_widget_to_list (setup, bw);
726             wt->widget = combo;
727           }
728           _SET_HELP;
729           break;
730 
731         case XINE_CONFIG_TYPE_NUM:
732           {
733             xitk_intbox_widget_t ib;
734             xitk_widget_t *intbox, *wi, *wbu, *wbd;
735 
736             XITK_WIDGET_INIT (&ib, setup->gui->imlib_data);
737             ib.skin_element_name = NULL;
738             ib.value             = entry.num_value;
739             ib.step              = 1;
740             ib.parent_wlist      = setup->widget_list;
741             ib.callback          = numtype_update;
742             ib.userdata          = wt;
743             intbox = xitk_noskin_intbox_create (setup->widget_list, &ib, x, y, 60, 20, &wi, &wbu, &wbd);
744             xitk_add_widget (setup->widget_list, intbox);
745             ADD_LABEL (intbox, NULL, NULL);
746             add_widget_to_list (setup, intbox);
747             add_widget_to_list (setup, wi);
748             add_widget_to_list (setup, wbu);
749             add_widget_to_list (setup, wbd);
750             wt->widget = intbox;
751           }
752           _SET_HELP;
753           break;
754 
755         case XINE_CONFIG_TYPE_BOOL:
756           {
757             xitk_checkbox_widget_t cb;
758             xitk_widget_t *checkbox;
759 
760             XITK_WIDGET_INIT (&cb, setup->gui->imlib_data);
761             cb.skin_element_name = NULL;
762             cb.callback          = numtype_update;
763             cb.userdata          = wt;
764             checkbox = xitk_noskin_checkbox_create (setup->widget_list, &cb, x, y, 12, 12);
765             xitk_add_widget (setup->widget_list, checkbox);
766             xitk_checkbox_set_state (checkbox, entry.num_value);
767             ADD_LABEL (checkbox, label_cb, (void *)checkbox);
768             add_widget_to_list (setup, checkbox);
769             wt->widget = checkbox;
770           }
771           _SET_HELP;
772           break;
773       }
774 
775       DISABLE_ME (wt);
776     }
777 
778     memset (&entry, 0, sizeof (entry));
779     cfg_err_result = xine_config_get_next_entry (setup->gui->xine, &entry);
780   }
781 
782 
783   if(setup->num_wg == 0) {
784     int x = (WINDOW_WIDTH >> 1) - (FRAME_WIDTH >> 1) - 11;
785     setup->wg[setup->num_wg++] = setup_add_nothing_available (setup,
786       _("There is no configuration option available in this user experience level."), x, y);
787   }
788 
789 
790   if (setup->num_wg > MAX_DISPLAY_WIDGETS) {
791     slidmax = setup->num_wg - MAX_DISPLAY_WIDGETS;
792     xitk_show_widget (setup->slider_wg);
793     xitk_enable_widget (setup->slider_wg);
794   }
795   else
796     slidmax = 1;
797 
798   xitk_slider_set_max (setup->slider_wg, slidmax);
799   xitk_slider_set_pos (setup->slider_wg, slidmax);
800 
801 }
802 
803 /*
804  *
805  */
setup_change_section(xitk_widget_t * wx,void * data,int section)806 static void setup_change_section(xitk_widget_t *wx, void *data, int section) {
807   xui_setup_t *setup = data;
808   int i;
809 
810   (void)wx;
811   setup_set_cursor (setup, WAIT_CURS);
812 
813   for (i = 0; i < setup->num_wg; i++ )
814     free (setup->wg[i]);
815   setup->num_wg = 0;
816   setup->first_displayed = 0;
817 
818   /* remove old widgets */
819   {
820     xitk_widget_t *sw;
821     xine_list_iterator_t ite = NULL;
822     while (1) {
823       sw = _xine_list_next_value (setup->widgets, &ite);
824       if (!ite)
825         break;
826       xitk_destroy_widget (sw);
827     }
828   }
829   xine_list_clear (setup->widgets);
830 
831   setup_section_widgets (setup, section);
832 
833   setup_clear_tab (setup);
834   setup_paint_widgets (setup);
835 }
836 
837 /*
838  * collect config categories, setup tab widget
839  */
setup_sections(xui_setup_t * setup)840 static void setup_sections (xui_setup_t *setup) {
841   xitk_pixmap_t       *bg;
842   xine_cfg_entry_t  entry;
843   int                  cfg_err_result;
844   xitk_tabs_widget_t   tab;
845 
846   setup->num_sections = 0;
847   cfg_err_result = xine_config_get_first_entry (setup->gui->xine, &entry);
848   while (cfg_err_result) {
849 
850     char *point;
851 
852     point = strchr(entry.key, '.');
853 
854     if (entry.type != XINE_CONFIG_TYPE_UNKNOWN && point) {
855       int found ;
856       int i;
857       int len;
858 
859       len = point - entry.key;
860       found = 0;
861 
862       for (i = 0; i < setup->num_sections; i++) {
863         if (!strncmp (setup->sections[i], entry.key, len)) {
864 	  found = 1;
865 	  break;
866 	}
867       }
868 
869       if (!found) {
870         setup->sections[setup->num_sections] = strndup (entry.key, len);
871         setup->num_sections++;
872       }
873     }
874 
875     cfg_err_result = xine_config_get_next_entry (setup->gui->xine, &entry);
876   }
877 
878   XITK_WIDGET_INIT (&tab, setup->gui->imlib_data);
879 
880   tab.skin_element_name = NULL;
881   tab.num_entries       = setup->num_sections;
882   tab.entries           = setup->sections;
883   tab.parent_wlist      = setup->widget_list;
884   tab.callback          = setup_change_section;
885   tab.userdata          = setup;
886   setup->tabs = xitk_noskin_tabs_create (setup->widget_list, &tab, 15, 24, WINDOW_WIDTH - 30, tabsfontname);
887   xitk_add_widget (setup->widget_list, setup->tabs);
888 
889   setup->th = xitk_get_widget_height (setup->tabs) - 1;
890 
891   xitk_enable_and_show_widget (setup->tabs);
892 
893   bg = xitk_image_create_xitk_pixmap (setup->gui->imlib_data, WINDOW_WIDTH, WINDOW_HEIGHT);
894 
895   setup->gui->x_lock_display (setup->gui->display);
896   XCopyArea (setup->gui->display, (xitk_window_get_background (setup->xwin)), bg->pixmap,
897     bg->gc, 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT, 0, 0);
898   setup->gui->x_unlock_display (setup->gui->display);
899 
900   draw_rectangular_outter_box (setup->gui->imlib_data, bg, 15, (24 + setup->th),
901     (WINDOW_WIDTH - 30 - 1), (MAX_DISPLAY_WIDGETS * (FRAME_HEIGHT + 3) - 3 + 3 + 30 - 1));
902   xitk_window_change_background (setup->gui->imlib_data, setup->xwin, bg->pixmap,
903     WINDOW_WIDTH, WINDOW_HEIGHT);
904 
905   xitk_image_destroy_xitk_pixmap(bg);
906 
907   setup->widgets = xine_list_new ();
908 
909   setup->num_wg = 0;
910   setup->first_displayed = 0;
911 }
912 
913 /*
914  *
915  */
setup_end(xui_setup_t * setup)916 void setup_end (xui_setup_t *setup) {
917   setup_exit (NULL, setup);
918 }
919 
920 /*
921  *
922  */
setup_nextprev_wg(xitk_widget_t * w,void * data,int pos)923 static void setup_nextprev_wg(xitk_widget_t *w, void *data, int pos) {
924   xui_setup_t *setup = data;
925   int rpos = (xitk_slider_get_max (setup->slider_wg)) - pos;
926 
927   (void)w;
928   if (rpos != setup->first_displayed) {
929     setup->first_displayed = rpos;
930     setup_clear_tab (setup);
931     setup_paint_widgets (setup);
932   }
933 }
934 
setup_reparent(xui_setup_t * setup)935 void setup_reparent (xui_setup_t *setup) {
936   if (!setup)
937     return;
938   if (setup->running)
939     reparent_window ((xitk_window_get_window (setup->xwin)));
940 }
941 
942 /*
943  * Create setup panel window
944  */
setup_panel(gGui_t * gui)945 xui_setup_t *setup_panel (gGui_t *gui) {
946   xui_setup_t   *setup;
947   xitk_widget_t *w;
948   xitk_font_t   *fs;
949 
950   if (!gui)
951     return NULL;
952   setup = calloc (1, sizeof (*setup));
953   if (!setup)
954     return NULL;
955 
956   setup->gui = gui;
957 
958   {
959     Window win;
960     GC gc;
961     int x, y;
962 
963     x = xine_config_register_num (setup->gui->xine, "gui.setup_x", 80,
964       CONFIG_NO_DESC, CONFIG_NO_HELP, CONFIG_LEVEL_DEB, CONFIG_NO_CB, CONFIG_NO_DATA);
965     y = xine_config_register_num (setup->gui->xine, "gui.setup_y", 80,
966       CONFIG_NO_DESC, CONFIG_NO_HELP, CONFIG_LEVEL_DEB, CONFIG_NO_CB, CONFIG_NO_DATA);
967     /* Create window */
968     setup->xwin = xitk_window_create_dialog_window (setup->gui->imlib_data,
969       _("xine Setup"), x, y, WINDOW_WIDTH, WINDOW_HEIGHT);
970     win = xitk_window_get_window (setup->xwin);
971     set_window_states_start (win);
972 
973     setup->gui->x_lock_display (setup->gui->display);
974     gc = XCreateGC (setup->gui->display, win, None, None);
975     setup->gui->x_unlock_display (setup->gui->display);
976 
977     setup->widget_list = xitk_widget_list_new ();
978     xitk_widget_list_set (setup->widget_list, WIDGET_LIST_WINDOW, (void *)win);
979     xitk_widget_list_set (setup->widget_list, WIDGET_LIST_GC, gc);
980 
981     fs = xitk_font_load_font (setup->gui->display, fontname);
982     xitk_font_set_font (fs, gc);
983     setup->fh = xitk_font_get_string_height (fs, " ");
984   }
985 
986   setup_sections (setup);
987 
988   {
989     xitk_slider_widget_t sl;
990 
991     XITK_WIDGET_INIT (&sl, setup->gui->imlib_data);
992     sl.min               = 0;
993     sl.max               = 1;
994     sl.step              = 1;
995     sl.skin_element_name = NULL;
996     sl.callback          = NULL;
997     sl.userdata          = NULL;
998     sl.motion_callback   = setup_nextprev_wg;
999     sl.motion_userdata   = setup;
1000     setup->slider_wg =  xitk_noskin_slider_create (setup->widget_list, &sl,
1001       (WINDOW_WIDTH - 15 - 16 - 4 - 1), (24 + setup->th + 15),
1002       16, (MAX_DISPLAY_WIDGETS * (FRAME_HEIGHT + 3) - 3 + 3), XITK_VSLIDER);
1003   }
1004   xitk_add_widget (setup->widget_list, setup->slider_wg);
1005 
1006   setup_section_widgets (setup, 0);
1007   setup_paint_widgets (setup);
1008 
1009   {
1010     xitk_label_widget_t lbl;
1011     char *label = _("(*)  you need to restart xine for this setting to take effect");
1012     int           len;
1013 
1014     len = xitk_font_get_string_length (fs, label);
1015 
1016     XITK_WIDGET_INIT(&lbl, gui->imlib_data);
1017     lbl.window              = xitk_window_get_window (setup->xwin);
1018     lbl.gc                  = (XITK_WIDGET_LIST_GC (setup->widget_list));
1019     lbl.skin_element_name   = NULL;
1020     lbl.label               = label;
1021     lbl.callback            = NULL;
1022     lbl.userdata            = setup;
1023     w =  xitk_noskin_label_create (setup->widget_list, &lbl,
1024       (WINDOW_WIDTH - len) >> 1, (24 + setup->th + MAX_DISPLAY_WIDGETS * (FRAME_HEIGHT + 3) - 3 + 3 + 30), len + 3, 18, fontname);
1025   }
1026   xitk_add_widget (setup->widget_list, w);
1027   xitk_enable_and_show_widget(w);
1028 
1029   xitk_font_unload_font(fs);
1030 
1031   {
1032     xitk_labelbutton_widget_t lb;
1033 
1034     XITK_WIDGET_INIT (&lb, setup->gui->imlib_data);
1035     lb.button_type       = CLICK_BUTTON;
1036     lb.align             = ALIGN_CENTER;
1037     lb.state_callback    = NULL;
1038     lb.skin_element_name = NULL;
1039     lb.userdata          = setup;
1040 
1041     lb.label             = _("OK");
1042     lb.callback          = setup_ok;
1043     setup->ok = xitk_noskin_labelbutton_create (setup->widget_list, &lb,
1044       15, WINDOW_HEIGHT - (23 + 15), 100, 23, "Black", "Black", "White", tabsfontname);
1045     xitk_add_widget (setup->widget_list, setup->ok);
1046     xitk_enable_and_show_widget(setup->ok);
1047 
1048     lb.label             = _("Apply");
1049     lb.callback          = setup_apply;
1050     w = xitk_noskin_labelbutton_create (setup->widget_list, &lb,
1051       (WINDOW_WIDTH - 100) >> 1, WINDOW_HEIGHT - (23 + 15), 100, 23, "Black", "Black", "White", tabsfontname);
1052     xitk_add_widget (setup->widget_list, w);
1053     xitk_enable_and_show_widget(w);
1054 
1055     lb.label             = _("Close");
1056     lb.callback          = setup_exit;
1057     w =  xitk_noskin_labelbutton_create (setup->widget_list, &lb,
1058       WINDOW_WIDTH - (100 + 15), WINDOW_HEIGHT - (23 + 15), 100, 23, "Black", "Black", "White", tabsfontname);
1059     xitk_add_widget (setup->widget_list, w);
1060     xitk_enable_and_show_widget(w);
1061   }
1062   setup_show_tips (setup, panel_get_tips_enable (setup->gui->panel), panel_get_tips_timeout (setup->gui->panel));
1063 
1064   setup->kreg = xitk_register_event_handler ("setup",
1065     xitk_window_get_window (setup->xwin),
1066     setup_handle_event, NULL, NULL,
1067     setup->widget_list, setup);
1068 
1069   setup->visible = 1;
1070   setup->running = 1;
1071   setup_raise_window (setup);
1072 
1073   try_to_set_input_focus (xitk_window_get_window (setup->xwin));
1074 
1075   setup->gui->setup = setup;
1076   return setup;
1077 }
1078