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 <stdarg.h>
27 #include <X11/Xlib.h>
28 #include <X11/keysym.h>
29 
30 #include "_xitk.h"
31 #include "xitk.h"
32 
33 #define DIALOG_TYPE_UNKNOWN        0
34 #define DIALOG_TYPE_OK             1
35 #define DIALOG_TYPE_YESNO          2
36 #define DIALOG_TYPE_YESNOCANCEL    3
37 #define DIALOG_TYPE_BUTTONLESS     4
38 
39 static void _xitk_window_destroy_window(xitk_widget_t *, void *);
40 
41 #define TITLE_BAR_HEIGHT 20
42 
_xitk_window_set_focus(Display * display,Window window)43 static void _xitk_window_set_focus(Display *display, Window window) {
44   int t = 0;
45 
46   while((!xitk_is_window_visible(display, window)) && (++t < 3))
47     xitk_usec_sleep(5000);
48 
49   if(xitk_is_window_visible(display, window)) {
50     xitk_x_lock_display (display);
51     XSetInputFocus(display, window, RevertToParent, CurrentTime);
52     xitk_x_unlock_display (display);
53   }
54 }
55 
56 /*
57  *
58  */
xitk_is_window_iconified(Display * display,Window window)59 int xitk_is_window_iconified(Display *display, Window window) {
60   unsigned char *prop_return = NULL;
61   unsigned long  nitems_return;
62   unsigned long  bytes_after_return;
63   int            format_return;
64   Atom           type_return, atom;
65   int            retval = 0;
66 
67   xitk_x_lock_display (display);
68   atom = XInternAtom(display, "WM_STATE", False);
69   XGetWindowProperty (display, window, atom, 0, 0x7fffffff, False,
70 		      atom, &type_return, &format_return, &nitems_return, &bytes_after_return, &prop_return);
71 
72   if(prop_return) {
73     if (prop_return[0] == IconicState)
74       retval = 1;
75     XFree(prop_return);
76   }
77   xitk_x_unlock_display (display);
78 
79   return retval;
80 }
81 
82 /*
83  * Is window is size match with given args
84  */
xitk_is_window_visible(Display * display,Window window)85 int xitk_is_window_visible(Display *display, Window window) {
86   XWindowAttributes  wattr;
87   Status             status;
88 
89   if((display == NULL) || (window == None))
90     return -1;
91 
92   xitk_x_lock_display (display);
93   status = XGetWindowAttributes(display, window, &wattr);
94   xitk_x_unlock_display (display);
95 
96   if((status != BadDrawable) && (status != BadWindow) && (wattr.map_state == IsViewable))
97     return 1;
98 
99   return 0;
100 }
101 
102 /*
103  * Is window is size match with given args
104  */
xitk_is_window_size(Display * display,Window window,int width,int height)105 int xitk_is_window_size(Display *display, Window window, int width, int height) {
106   XWindowAttributes  wattr;
107 
108   if((display == NULL) || (window == None))
109     return -1;
110 
111   xitk_x_lock_display (display);
112   if(!XGetWindowAttributes(display, window, &wattr)) {
113     XITK_WARNING("XGetWindowAttributes() failed.n");
114     xitk_x_unlock_display (display);
115     return -1;
116   }
117   xitk_x_unlock_display (display);
118 
119   if((wattr.width == width) && (wattr.height == height))
120     return 1;
121 
122   return 0;
123 }
124 
125 /*
126  * Set/Change window title.
127  */
xitk_set_window_title(Display * display,Window window,const char * title)128 void xitk_set_window_title(Display *display, Window window, const char *title) {
129 
130   if((display == NULL) || (window == None) || (title == NULL))
131     return;
132 
133   xitk_x_lock_display (display);
134   XmbSetWMProperties(display, window, title, title, NULL, 0, NULL, NULL, NULL);
135   xitk_x_unlock_display (display);
136 }
137 
138 /*
139  * Set/Change window title.
140  */
xitk_window_set_window_title(ImlibData * im,xitk_window_t * w,const char * title)141 void xitk_window_set_window_title(ImlibData *im, xitk_window_t *w, const char *title) {
142 
143   if((im == NULL) || (w == NULL) || (title == NULL))
144     return;
145 
146   xitk_set_window_title(im->x.disp, w->window, title);
147 }
148 
149 /*
150  * Get (safely) window pos.
151  */
xitk_get_window_position(Display * display,Window window,int * x,int * y,int * width,int * height)152 void xitk_get_window_position(Display *display, Window window,
153 			      int *x, int *y, int *width, int *height) {
154   XWindowAttributes  wattr;
155   Window             wdummy;
156   int                xx = 0, yy = 0;
157 
158   if((display == NULL) || (window == None))
159     return;
160 
161   xitk_x_lock_display (display);
162   if(!XGetWindowAttributes(display, window, &wattr)) {
163     XITK_WARNING("XGetWindowAttributes() failed.n");
164     wattr.width = wattr.height = 0;
165     goto __failure;
166   }
167 
168   (void) XTranslateCoordinates (display, window, wattr.root,
169 				-wattr.border_width, -wattr.border_width,
170                                 &xx, &yy, &wdummy);
171 
172  __failure:
173 
174   xitk_x_unlock_display (display);
175 
176   if(x)
177     *x = xx;
178   if(y)
179     *y = yy;
180   if(width)
181     *width = wattr.width;
182   if(height)
183     *height = wattr.height;
184 }
185 
186 /*
187  * Get (safely) window pos.
188  */
xitk_window_get_window_position(ImlibData * im,xitk_window_t * w,int * x,int * y,int * width,int * height)189 void xitk_window_get_window_position(ImlibData *im, xitk_window_t *w,
190 				     int *x, int *y, int *width, int *height) {
191 
192   if((im == NULL) || (w == NULL))
193     return;
194 
195   xitk_get_window_position(im->x.disp, w->window, x, y, width, height);
196 }
197 
198 /*
199  * Center a window in root window.
200  */
xitk_window_move_window(ImlibData * im,xitk_window_t * w,int x,int y)201 void xitk_window_move_window(ImlibData *im, xitk_window_t *w, int x, int y) {
202 
203   if((im == NULL) || (w == NULL))
204     return;
205 
206   XLOCK (im->x.x_lock_display, im->x.disp);
207   XMoveResizeWindow (im->x.disp, w->window, x, y, w->width, w->height);
208   XUNLOCK (im->x.x_unlock_display, im->x.disp);
209 
210 }
211 
212 /*
213  * Center a window in root window.
214  */
xitk_window_center_window(ImlibData * im,xitk_window_t * w)215 void xitk_window_center_window(ImlibData *im, xitk_window_t *w) {
216   Window        rootwin;
217   int           xwin, ywin;
218   unsigned int  wwin, hwin, bwin, dwin;
219   int           xx = 0, yy = 0;
220 
221   if((im == NULL) || (w == NULL))
222     return;
223 
224   XLOCK (im->x.x_lock_display, im->x.disp);
225   if(XGetGeometry(im->x.disp, im->x.root, &rootwin,
226 		  &xwin, &ywin, &wwin, &hwin, &bwin, &dwin) != BadDrawable) {
227 
228     xx = (wwin / 2) - (w->width / 2);
229     yy = (hwin / 2) - (w->height / 2);
230   }
231 
232   XMoveResizeWindow (im->x.disp, w->window, xx, yy, w->width, w->height);
233   XUNLOCK (im->x.x_unlock_display, im->x.disp);
234 }
235 
236 /*
237  * Create a simple (empty) window.
238  */
xitk_window_create_window(ImlibData * im,int x,int y,int width,int height)239 xitk_window_t *xitk_window_create_window(ImlibData *im, int x, int y, int width, int height) {
240   xitk_window_t         *xwin;
241   const char             title[] = {"xiTK Window"};
242   XSizeHints             hint;
243   XWMHints              *wm_hint;
244   XSetWindowAttributes   attr;
245   Atom                   prop, XA_WIN_LAYER, XA_DELETE_WINDOW;
246   XColor                 black, dummy;
247   MWMHints               mwmhints;
248   XClassHint            *xclasshint;
249   long                   data[1];
250 
251   if((im == NULL) || (width == 0 || height == 0))
252     return NULL;
253 
254   xwin                  = (xitk_window_t *) xitk_xmalloc(sizeof(xitk_window_t));
255   xwin->win_parent      = None;
256   xwin->background      = NULL;
257   xwin->background_mask = NULL;
258   xwin->width           = width;
259   xwin->height          = height;
260   xwin->parent          = NULL;
261 
262   memset(&hint, 0, sizeof(hint));
263   hint.x               = x;
264   hint.y               = y;
265   hint.width           = width;
266   hint.base_width      = width;
267   hint.min_width       = width;
268   hint.max_width       = width;
269   hint.height          = height;
270   hint.base_height     = height;
271   hint.min_height      = height;
272   hint.max_height      = height;
273   hint.win_gravity     = NorthWestGravity;
274   hint.flags           = PWinGravity | PBaseSize | PMinSize | PMaxSize | USSize | USPosition;
275 
276   XLOCK (im->x.x_lock_display, im->x.disp);
277   XAllocNamedColor(im->x.disp, Imlib_get_colormap(im), "black", &black, &dummy);
278   XUNLOCK (im->x.x_unlock_display, im->x.disp);
279 
280   attr.override_redirect = False;
281   attr.background_pixel  = black.pixel;
282   attr.border_pixel      = black.pixel;
283   attr.colormap          = Imlib_get_colormap(im);
284   attr.win_gravity       = NorthWestGravity;
285 
286   XLOCK (im->x.x_lock_display, im->x.disp);
287   xwin->window = XCreateWindow(im->x.disp, im->x.root, hint.x, hint.y, hint.width, hint.height,
288 			       0, im->x.depth,  InputOutput, im->x.visual,
289 			       CWBackPixel | CWBorderPixel | CWColormap
290 			       | CWOverrideRedirect | CWWinGravity ,
291 			       &attr);
292 
293   XmbSetWMProperties(im->x.disp, xwin->window, title, title, NULL, 0, &hint, NULL, NULL);
294 
295   XSelectInput(im->x.disp, xwin->window, INPUT_MOTION | KeymapStateMask);
296 
297   XA_WIN_LAYER = XInternAtom(im->x.disp, "_WIN_LAYER", False);
298 
299   data[0] = 10;
300   XChangeProperty(im->x.disp, xwin->window, XA_WIN_LAYER,
301 		  XA_CARDINAL, 32, PropModeReplace, (unsigned char *)data,
302 		  1);
303 
304   memset(&mwmhints, 0, sizeof(mwmhints));
305   prop = XInternAtom(im->x.disp, "_MOTIF_WM_HINTS", False);
306   mwmhints.flags = MWM_HINTS_DECORATIONS;
307   mwmhints.decorations = 0;
308 
309   XChangeProperty(im->x.disp, xwin->window, prop, prop, 32,
310                   PropModeReplace, (unsigned char *) &mwmhints,
311                   PROP_MWM_HINTS_ELEMENTS);
312 
313   XA_DELETE_WINDOW = XInternAtom(im->x.disp, "WM_DELETE_WINDOW", False);
314   XSetWMProtocols(im->x.disp, xwin->window, &XA_DELETE_WINDOW, 1);
315 
316   if((xclasshint = XAllocClassHint()) != NULL) {
317     xclasshint->res_name = (char *)"Xine Window";
318     xclasshint->res_class = (char *)"Xitk";
319     XSetClassHint(im->x.disp, xwin->window, xclasshint);
320     XFree(xclasshint);
321   }
322 
323   wm_hint = XAllocWMHints();
324   if (wm_hint != NULL) {
325     wm_hint->input         = True;
326     wm_hint->initial_state = NormalState;
327     wm_hint->flags         = InputHint | StateHint;
328     XSetWMHints(im->x.disp, xwin->window, wm_hint);
329     XFree(wm_hint);
330   }
331 
332   XUNLOCK (im->x.x_unlock_display, im->x.disp);
333 
334   return xwin;
335 }
336 
337 /*
338  * Create a simple painted window.
339  */
xitk_window_create_simple_window(ImlibData * im,int x,int y,int width,int height)340 xitk_window_t *xitk_window_create_simple_window(ImlibData *im, int x, int y, int width, int height) {
341   xitk_window_t *xwin;
342 
343   if((im == NULL) || (width == 0 || height == 0))
344     return NULL;
345 
346   xwin = xitk_window_create_window(im, x, y, width, height);
347   xwin->width = width;
348   xwin->height = height;
349 
350   xwin->background = xitk_image_create_xitk_pixmap(im, width, height);
351   draw_outter(im, xwin->background, width, height);
352   xitk_window_apply_background(im, xwin);
353 
354   xitk_window_move_window(im, xwin, x, y);
355 
356   return xwin;
357 }
358 
359 /*
360  * Create a simple, with title bar, window.
361  */
xitk_window_create_dialog_window(ImlibData * im,const char * title,int x,int y,int width,int height)362 xitk_window_t *xitk_window_create_dialog_window(ImlibData *im, const char *title,
363 						int x, int y, int width, int height) {
364   xitk_window_t *xwin;
365   xitk_pixmap_t  *bar, *pix_bg;
366   unsigned int   colorblack, colorwhite, colorgray, colordgray;
367   xitk_font_t   *fs = NULL;
368   int            lbear, rbear, wid, asc, des;
369   int            bar_style = xitk_get_barstyle_feature();
370 
371   if((im == NULL) || (title == NULL) || (width == 0 || height == 0))
372     return NULL;
373 
374   xwin = xitk_window_create_simple_window(im, x, y, width, height);
375 
376   xitk_window_set_window_title(im, xwin, title);
377 
378   bar = xitk_image_create_xitk_pixmap(im, width, TITLE_BAR_HEIGHT);
379   pix_bg = xitk_image_create_xitk_pixmap(im, width, height);
380 
381   fs = xitk_font_load_font(im->x.disp, DEFAULT_BOLD_FONT_12);
382   xitk_font_set_font(fs, bar->gc);
383   xitk_font_string_extent(fs, (title && strlen(title)) ? title : "Window", &lbear, &rbear, &wid, &asc, &des);
384 
385   XLOCK (im->x.x_lock_display, im->x.disp);
386   XCopyArea(im->x.disp, xwin->background->pixmap, pix_bg->pixmap, xwin->background->gc,
387 	    0, 0, width, height, 0, 0);
388   XUNLOCK (im->x.x_unlock_display, im->x.disp);
389 
390   colorblack = xitk_get_pixel_color_black(im);
391   colorwhite = xitk_get_pixel_color_white(im);
392   colorgray = xitk_get_pixel_color_gray(im);
393   colordgray = xitk_get_pixel_color_darkgray(im);
394 
395  /* Draw window title bar background */
396   if(bar_style) {
397     int s, bl = 255;
398     unsigned int colorblue;
399 
400     colorblue = xitk_get_pixel_color_from_rgb(im, 0, 0, bl);
401     XLOCK (im->x.x_lock_display, im->x.disp);
402     for(s = 0; s <= TITLE_BAR_HEIGHT; s++, bl -= 8) {
403       XSetForeground(im->x.disp, bar->gc, colorblue);
404       XDrawLine(im->x.disp, bar->pixmap, bar->gc, 0, s, width, s);
405       colorblue = xitk_get_pixel_color_from_rgb(im, 0, 0, bl);
406     }
407     XUNLOCK (im->x.x_unlock_display, im->x.disp);
408   }
409   else {
410     int s;
411     unsigned int c, cd;
412 
413     cd = xitk_get_pixel_color_from_rgb(im, 115, 12, 206);
414     c = xitk_get_pixel_color_from_rgb(im, 135, 97, 168);
415 
416     draw_flat_with_color(im, bar, width, TITLE_BAR_HEIGHT, colorgray);
417     draw_rectangular_inner_box(im, bar, 2, 2, width - 6, (TITLE_BAR_HEIGHT - 1 - 4));
418 
419     XLOCK (im->x.x_lock_display, im->x.disp);
420     for(s = 6; s <= (TITLE_BAR_HEIGHT - 6); s += 3) {
421       XSetForeground(im->x.disp, bar->gc, c);
422       XDrawLine(im->x.disp, bar->pixmap, bar->gc, 5, s, (width - 8), s);
423       XSetForeground(im->x.disp, bar->gc, cd);
424       XDrawLine(im->x.disp, bar->pixmap, bar->gc, 5, s+1, (width - 8), s+1);
425     }
426 
427     XSetForeground(im->x.disp, bar->gc, colorgray);
428     XFillRectangle(im->x.disp, bar->pixmap, bar->gc,
429 		   ((width - wid) - TITLE_BAR_HEIGHT) - 10, 6,
430 		   wid + 20, TITLE_BAR_HEIGHT - 1 - 8);
431     XUNLOCK (im->x.x_unlock_display, im->x.disp);
432   }
433 
434   XLOCK (im->x.x_lock_display, im->x.disp);
435   XSetForeground(im->x.disp, bar->gc, colorwhite);
436   XDrawLine(im->x.disp, bar->pixmap, bar->gc, 0, 0, width, 0);
437   XDrawLine(im->x.disp, bar->pixmap, bar->gc, 0, 0, 0, TITLE_BAR_HEIGHT - 1);
438   XUNLOCK (im->x.x_unlock_display, im->x.disp);
439 
440   XLOCK (im->x.x_lock_display, im->x.disp);
441   XSetForeground(im->x.disp, bar->gc, colorblack);
442   XDrawLine(im->x.disp, bar->pixmap, bar->gc, width - 1, 0, width - 1, TITLE_BAR_HEIGHT - 1);
443 
444   XDrawLine(im->x.disp, bar->pixmap, bar->gc, 2, TITLE_BAR_HEIGHT - 1, width - 2, TITLE_BAR_HEIGHT - 1);
445   XUNLOCK (im->x.x_unlock_display, im->x.disp);
446 
447   XLOCK (im->x.x_lock_display, im->x.disp);
448   XSetForeground(im->x.disp, bar->gc, colordgray);
449   XDrawLine(im->x.disp, bar->pixmap, bar->gc, width - 2, 2, width - 2, TITLE_BAR_HEIGHT - 1);
450   XUNLOCK (im->x.x_unlock_display, im->x.disp);
451 
452   XLOCK (im->x.x_lock_display, im->x.disp);
453   XSetForeground(im->x.disp, bar->gc, colorblack);
454   XDrawLine(im->x.disp, pix_bg->pixmap, bar->gc, width - 1, 0, width - 1, height - 1);
455   XDrawLine(im->x.disp, pix_bg->pixmap, bar->gc, 0, height - 1, width - 1, height - 1);
456   XUNLOCK (im->x.x_unlock_display, im->x.disp);
457 
458   XLOCK (im->x.x_lock_display, im->x.disp);
459   XSetForeground(im->x.disp, bar->gc, colordgray);
460   XDrawLine(im->x.disp, pix_bg->pixmap, bar->gc, width - 2, 0, width - 2, height - 2);
461   XDrawLine(im->x.disp, pix_bg->pixmap, bar->gc, 2, height - 2, width - 2, height - 2);
462   XUNLOCK (im->x.x_unlock_display, im->x.disp);
463 
464   XLOCK (im->x.x_lock_display, im->x.disp);
465   if(bar_style)
466     XSetForeground(im->x.disp, bar->gc, colorwhite);
467   else
468     XSetForeground(im->x.disp, bar->gc, (xitk_get_pixel_color_from_rgb(im, 85, 12, 135)));
469   XUNLOCK (im->x.x_unlock_display, im->x.disp);
470 
471   xitk_font_draw_string(fs, bar->pixmap, bar->gc,
472 			(width - wid) - TITLE_BAR_HEIGHT, ((TITLE_BAR_HEIGHT+asc+des) >> 1) - des, title, strlen(title));
473 
474   xitk_font_unload_font(fs);
475 
476   XLOCK (im->x.x_lock_display, im->x.disp);
477   XCopyArea(im->x.disp, bar->pixmap, pix_bg->pixmap, bar->gc, 0, 0, width, TITLE_BAR_HEIGHT, 0, 0);
478   XUNLOCK (im->x.x_unlock_display, im->x.disp);
479 
480   xitk_window_change_background(im, xwin, pix_bg->pixmap, width, height);
481 
482   xitk_image_destroy_xitk_pixmap(bar);
483   xitk_image_destroy_xitk_pixmap(pix_bg);
484 
485   return xwin;
486 }
487 
488 /*
489  * Get window sizes.
490  */
xitk_window_get_window_size(xitk_window_t * w,int * width,int * height)491 void xitk_window_get_window_size(xitk_window_t *w, int *width, int *height) {
492 
493   if (w == NULL) {
494     *width = 0;
495     *height = 0;
496     return;
497   }
498 
499   *width = w->width;
500   *height = w->height;
501 }
502 
503 /*
504  * Get window (X) id.
505  */
xitk_window_get_window(xitk_window_t * w)506 Window xitk_window_get_window(xitk_window_t *w) {
507 
508   if(w == NULL)
509     return None;
510 
511   return w->window;
512 }
513 
514 /*
515  * Return window background pixmap.
516  */
xitk_window_get_background(xitk_window_t * w)517 Pixmap xitk_window_get_background(xitk_window_t *w) {
518 
519   if(w == NULL)
520     return None;
521 
522   return w->background->pixmap;
523 }
524 
525 /*
526  * Return window background pixmap.
527  */
xitk_window_get_background_mask(xitk_window_t * w)528 Pixmap xitk_window_get_background_mask(xitk_window_t *w) {
529 
530   if(w == NULL)
531     return None;
532 
533   if(w->background_mask == NULL)
534     return None;
535 
536   return w->background->pixmap;
537 }
538 
539 /*
540  * Apply (draw) window background.
541  */
xitk_window_apply_background(ImlibData * im,xitk_window_t * w)542 void xitk_window_apply_background(ImlibData *im, xitk_window_t *w) {
543 
544   if((im == NULL) || (w == NULL))
545     return;
546 
547   XLOCK (im->x.x_lock_display, im->x.disp);
548 
549   XSetWindowBackgroundPixmap(im->x.disp, w->window, w->background->pixmap);
550 
551   if(w->background_mask)
552     XShapeCombineMask(im->x.disp, w->window, ShapeBounding, 0, 0, w->background_mask->pixmap, ShapeSet);
553   else
554     XShapeCombineMask(im->x.disp, w->window, ShapeBounding, 0, 0, 0, ShapeSet);
555 
556   XClearWindow(im->x.disp, w->window);
557   XUNLOCK (im->x.x_unlock_display, im->x.disp);
558 }
559 
560 /*
561  * Change window background with 'bg', then draw it.
562  */
xitk_window_change_background(ImlibData * im,xitk_window_t * w,Pixmap bg,int width,int height)563 int xitk_window_change_background(ImlibData *im,
564 				  xitk_window_t *w, Pixmap bg, int width, int height) {
565   Window        rootwin;
566   int           xwin, ywin;
567   unsigned int  wwin, hwin, bwin, dwin;
568 
569   if((im == NULL) || (w == NULL) || (bg == None) || (width == 0 || height == 0))
570     return 0;
571 
572   xitk_image_destroy_xitk_pixmap(w->background);
573   if(w->background_mask)
574     xitk_image_destroy_xitk_pixmap(w->background_mask);
575 
576   w->background      = xitk_image_create_xitk_pixmap(im, width, height);
577   w->background_mask = NULL;
578 
579   XLOCK (im->x.x_lock_display, im->x.disp);
580   if(XGetGeometry(im->x.disp, w->window, &rootwin,
581 		  &xwin, &ywin, &wwin, &hwin, &bwin, &dwin) != BadDrawable) {
582 
583     XResizeWindow (im->x.disp, w->window, wwin, hwin);
584   }
585   else {
586     XUNLOCK (im->x.x_unlock_display, im->x.disp);
587     return 0;
588   }
589 
590   XCopyArea(im->x.disp, bg, w->background->pixmap, w->background->gc, 0, 0, width, height, 0, 0);
591   XUNLOCK (im->x.x_unlock_display, im->x.disp);
592 
593   xitk_window_apply_background(im, w);
594 
595   return 1;
596 }
597 
598 /*
599  * Change window background with img, then draw it.
600  */
xitk_window_change_background_with_image(ImlibData * im,xitk_window_t * w,xitk_image_t * img,int width,int height)601 int xitk_window_change_background_with_image(ImlibData *im, xitk_window_t *w, xitk_image_t *img, int width, int height) {
602   Window        rootwin;
603   int           xwin, ywin;
604   unsigned int  wwin, hwin, bwin, dwin;
605 
606   if((im == NULL) || (w == NULL) || (img == NULL) || (width == 0 || height == 0))
607     return 0;
608 
609   xitk_image_destroy_xitk_pixmap(w->background);
610   if(w->background_mask)
611     xitk_image_destroy_xitk_pixmap(w->background_mask);
612 
613   w->background      = xitk_image_create_xitk_pixmap(im, width, height);
614   w->background_mask = NULL;
615 
616   if(img->mask)
617     w->background_mask = xitk_image_create_xitk_mask_pixmap(im, width, height);
618 
619   XLOCK (im->x.x_lock_display, im->x.disp);
620   if(XGetGeometry(im->x.disp, w->window, &rootwin,
621 		  &xwin, &ywin, &wwin, &hwin, &bwin, &dwin) != BadDrawable) {
622 
623     XResizeWindow (im->x.disp, w->window, wwin, hwin);
624   }
625   else {
626     XUNLOCK (im->x.x_unlock_display, im->x.disp);
627     return 0;
628   }
629 
630   XCopyArea(im->x.disp, img->image->pixmap, w->background->pixmap, w->background->gc, 0, 0, width, height, 0, 0);
631   if(w->background_mask)
632     XCopyArea(im->x.disp, img->mask->pixmap, w->background_mask->pixmap, w->background_mask->gc, 0, 0, width, height, 0, 0);
633 
634   XUNLOCK (im->x.x_unlock_display, im->x.disp);
635   xitk_window_apply_background(im, w);
636 
637   return 1;
638 }
639 
640 /*
641  * Local XEvent handling.
642  */
_window_handle_event(XEvent * event,void * data)643 static void _window_handle_event(XEvent *event, void *data) {
644   xitk_dialog_t *wd = (xitk_dialog_t *)data;
645 
646   switch(event->type) {
647 
648   case Expose:
649     if(wd->widget_list) {
650       wd->widget_list->widget_focused = wd->default_button;
651       if ((wd->widget_list->widget_focused->type & WIDGET_FOCUSABLE) &&
652 	  wd->widget_list->widget_focused->enable == WIDGET_ENABLE) {
653 	xitk_widget_t *w = wd->widget_list->widget_focused;
654 	widget_event_t event;
655 
656 	event.type = WIDGET_EVENT_FOCUS;
657 	event.focus = FOCUS_RECEIVED;
658 
659 	(void) w->event(w, &event, NULL);
660 	w->have_focus = FOCUS_RECEIVED;
661 
662 	event.type = WIDGET_EVENT_PAINT;
663 	(void) w->event(w, &event, NULL);
664       }
665     }
666     break;
667 
668   case MappingNotify:
669     XLOCK (wd->imlibdata->x.x_lock_display, wd->imlibdata->x.disp);
670     XRefreshKeyboardMapping((XMappingEvent *) event);
671     XUNLOCK (wd->imlibdata->x.x_unlock_display, wd->imlibdata->x.disp);
672     break;
673 
674   case KeyPress: {
675     XKeyEvent  mykeyevent;
676     KeySym     mykey;
677     char       kbuf[256];
678 
679     mykeyevent = event->xkey;
680 
681     XLOCK (wd->imlibdata->x.x_lock_display, wd->imlibdata->x.disp);
682     XLookupString(&mykeyevent, kbuf, sizeof(kbuf), &mykey, NULL);
683     XUNLOCK (wd->imlibdata->x.x_unlock_display, wd->imlibdata->x.disp);
684 
685     switch (mykey) {
686 
687     case XK_Return:
688       if(wd->default_button)
689 	_xitk_window_destroy_window(wd->default_button, (void *)wd);
690       break;
691 
692     case XK_Escape:
693       if((wd->type == DIALOG_TYPE_YESNO) || (wd->type == DIALOG_TYPE_YESNOCANCEL)) {
694 	if(wd->default_button)
695 	  _xitk_window_destroy_window(wd->default_button, (void *)wd);
696       }
697       else {
698 	if(wd->type != DIALOG_TYPE_BUTTONLESS)
699 	  _xitk_window_destroy_window(NULL, (void *)wd);
700       }
701       break;
702 
703     }
704 
705   }
706   break;
707   }
708 }
709 
xitk_window_set_modal(xitk_window_t * w)710 void xitk_window_set_modal(xitk_window_t *w) {
711   xitk_modal_window(w->window);
712 }
xitk_window_dialog_set_modal(xitk_window_t * w)713 void xitk_window_dialog_set_modal(xitk_window_t *w) {
714   xitk_dialog_t *wd = w->parent;
715   xitk_window_set_modal(wd->xwin);
716 }
xitk_window_destroy_window(ImlibData * im,xitk_window_t * w)717 void xitk_window_destroy_window(ImlibData *im, xitk_window_t *w) {
718 
719   XLOCK (im->x.x_lock_display, im->x.disp);
720   XUnmapWindow(im->x.disp, w->window);
721   XUNLOCK (im->x.x_unlock_display, im->x.disp);
722 
723   if(w->background)
724     xitk_image_destroy_xitk_pixmap(w->background);
725 
726   w->width = -1;
727   w->height = -1;
728 
729   xitk_unmodal_window(w->window);
730 
731   XLOCK (im->x.x_lock_display, im->x.disp);
732   XDestroyWindow(im->x.disp, w->window);
733 
734   if((w->win_parent != None) && xitk_is_window_visible(im->x.disp, w->win_parent))
735     XSetInputFocus(im->x.disp, w->win_parent, RevertToParent, CurrentTime);
736 
737   XUNLOCK (im->x.x_unlock_display, im->x.disp);
738 
739   XITK_FREE(w);
740 }
741 
742 /**
743  *
744  * @TODO Should be split on a different unit, as it's only used with TAR support
745  *       enabled.
746  */
xitk_window_dialog_destroy(xitk_window_t * w)747 void xitk_window_dialog_destroy(xitk_window_t *w) {
748   xitk_dialog_t *wd = w->parent;
749 
750   if(wd) {
751     xitk_window_destroy_window(wd->imlibdata, wd->xwin);
752     xitk_unregister_event_handler(&wd->key);
753 
754     if(wd->widget_list) {
755       xitk_destroy_widgets(wd->widget_list);
756       XLOCK (wd->imlibdata->x.x_lock_display, wd->imlibdata->x.disp);
757       XFreeGC(wd->imlibdata->x.disp, wd->widget_list->gc);
758       XUNLOCK (wd->imlibdata->x.x_unlock_display, wd->imlibdata->x.disp);
759 
760       /* xitk_dlist_init (&wd->widget_list->list); */
761 
762      XITK_WIDGET_LIST_FREE(wd->widget_list);
763     }
764     XITK_FREE(wd);
765   }
766 }
767 
768 /*
769  * Unmap and free window components.
770  */
_xitk_window_destroy_window(xitk_widget_t * w,void * data)771 static void _xitk_window_destroy_window(xitk_widget_t *w, void *data) {
772   xitk_dialog_t *wd = (xitk_dialog_t *)data;
773 
774   xitk_window_destroy_window(wd->imlibdata, wd->xwin);
775 
776   switch(wd->type) {
777 
778   case DIALOG_TYPE_OK:
779     if(wd->yescallback)
780       wd->yescallback(NULL, wd->userdata, XITK_WINDOW_ANSWER_OK);
781     break;
782 
783   case DIALOG_TYPE_YESNO:
784   case DIALOG_TYPE_YESNOCANCEL:
785     if(w == wd->wyes) {
786       if(wd->yescallback)
787 	wd->yescallback(NULL, wd->userdata, XITK_WINDOW_ANSWER_YES);
788     }
789     else if(w == wd->wno) {
790       if(wd->nocallback)
791 	wd->nocallback(NULL, wd->userdata, XITK_WINDOW_ANSWER_NO);
792     }
793     else if(w == wd->wcancel) {
794       if(wd->cancelcallback)
795 	wd->cancelcallback(NULL, wd->userdata, XITK_WINDOW_ANSWER_CANCEL);
796     }
797     break;
798 
799   case DIALOG_TYPE_BUTTONLESS:
800     /* NOOP */
801     break;
802 
803   default:
804     XITK_WARNING("window dialog type unknown: %d\n", wd->type);
805     break;
806 
807   }
808 
809   xitk_unregister_event_handler(&wd->key);
810 
811   if(wd->widget_list) {
812     xitk_destroy_widgets(wd->widget_list);
813 
814     XLOCK (wd->imlibdata->x.x_lock_display, wd->imlibdata->x.disp);
815     XFreeGC(wd->imlibdata->x.disp, wd->widget_list->gc);
816     XUNLOCK (wd->imlibdata->x.x_unlock_display, wd->imlibdata->x.disp);
817 
818     /* xitk_dlist_init (&wd->widget_list->list); */
819 
820     XITK_WIDGET_LIST_FREE(wd->widget_list);
821   }
822 
823   XITK_FREE(wd);
824 
825 }
826 
827 /**
828  *
829  * @TODO Should be split on a different unit, as it's only used with TAR support
830  *       enabled.
831  */
xitk_window_dialog_button_free_with_width(ImlibData * im,const char * title,int window_width,int align,const char * message,...)832 xitk_window_t *xitk_window_dialog_button_free_with_width(ImlibData *im, const char *title,
833                                                          int window_width, int align, const char *message, ...) {
834   xitk_dialog_t              *wd;
835   int                         windoww = window_width, windowh;
836   xitk_image_t               *image;
837 
838   if((im == NULL) || (window_width == 0) || (message == NULL))
839     return NULL;
840 
841   {
842     va_list   args;
843     char     *buf;
844 
845     va_start(args, message);
846     buf = xitk_vasprintf(message, args);
847     va_end(args);
848 
849     if (!buf)
850       return NULL;
851 
852     image = xitk_image_create_image_from_string(im, DEFAULT_FONT_12, windoww - 40, align, buf);
853     XITK_FREE(buf);
854   }
855 
856   if (!image) {
857     return NULL;
858   }
859 
860   windowh = (image->height) + (TITLE_BAR_HEIGHT + 40);
861 
862   wd = (xitk_dialog_t *) xitk_xmalloc(sizeof(xitk_dialog_t));
863 
864   wd->imlibdata = im;
865   wd->type = DIALOG_TYPE_BUTTONLESS;
866   wd->wyes = wd->wno = wd->wcancel = wd->default_button = NULL;
867   wd->widget_list = NULL;
868   wd->xwin = xitk_window_create_dialog_window(im, ((title != NULL) ? title : "Notice"),
869 					      0, 0, windoww, windowh);
870   wd->xwin->parent = wd;
871 
872   xitk_window_center_window(im, wd->xwin);
873 
874   wd->widget_list = NULL;
875 
876   /* Draw text area */
877   {
878     xitk_pixmap_t  *bg;
879     int             width, height;
880     GC              gc;
881 
882     xitk_window_get_window_size(wd->xwin, &width, &height);
883     bg = xitk_image_create_xitk_pixmap(im, width, height);
884 
885     XLOCK (im->x.x_lock_display, im->x.disp);
886     gc = XCreateGC(im->x.disp, (xitk_window_get_background(wd->xwin)), None, None);
887     XCopyArea(im->x.disp, (xitk_window_get_background(wd->xwin)), bg->pixmap,
888 	      gc, 0, 0, width, height, 0, 0);
889     XCopyArea(im->x.disp, image->image->pixmap, bg->pixmap,
890 	      image->image->gc, 0, 0, image->width, image->height, 20, (TITLE_BAR_HEIGHT + 20));
891     XUNLOCK (im->x.x_unlock_display, im->x.disp);
892 
893     xitk_window_change_background(im, wd->xwin, bg->pixmap, width, height);
894 
895     xitk_image_destroy_xitk_pixmap(bg);
896 
897     XLOCK (im->x.x_lock_display, im->x.disp);
898     XFreeGC(im->x.disp, gc);
899     XUNLOCK (im->x.x_unlock_display, im->x.disp);
900 
901     xitk_image_free_image(im, &image);
902 
903   }
904 
905   XLOCK (im->x.x_lock_display, im->x.disp);
906   XMapRaised(im->x.disp, (xitk_window_get_window(wd->xwin)));
907   XUNLOCK (im->x.x_unlock_display, im->x.disp);
908 
909   wd->key = xitk_register_event_handler("xitk_nobtn",
910 					(xitk_window_get_window(wd->xwin)),
911 					_window_handle_event,
912 					NULL,
913 					NULL,
914 					NULL,
915 					(void *)wd);
916 
917   _xitk_window_set_focus(im->x.disp, (xitk_window_get_window(wd->xwin)));
918 
919   return wd->xwin;
920 }
921 /*
922  * Create a window error, containing an error message.
923  */
xitk_window_dialog_one_button_with_width(ImlibData * im,const char * title,const char * button_label,xitk_state_callback_t cb,void * userdata,int window_width,int align,const char * message,...)924 xitk_window_t *xitk_window_dialog_one_button_with_width(ImlibData *im, const char *title,
925                                                         const char *button_label,
926 							xitk_state_callback_t cb, void *userdata,
927                                                         int window_width, int align,
928                                                         const char *message, ...) {
929   xitk_dialog_t              *wd;
930   xitk_labelbutton_widget_t   lb;
931   int                         windoww = window_width, windowh;
932   xitk_image_t               *image;
933   int                         bwidth = 100, bx, by;
934 
935   if((im == NULL) || (window_width == 0) || (message == NULL))
936     return NULL;
937 
938   {
939     va_list   args;
940     char     *buf;
941 
942     va_start(args, message);
943     buf = xitk_vasprintf(message, args);
944     va_end(args);
945 
946     if (!buf)
947       return NULL;
948 
949     image = xitk_image_create_image_from_string(im, DEFAULT_FONT_12, windoww - 40, align, buf);
950     XITK_FREE(buf);
951   }
952 
953   windowh = (image->height + 50) + (TITLE_BAR_HEIGHT + 40);
954 
955   wd = (xitk_dialog_t *) xitk_xmalloc(sizeof(xitk_dialog_t));
956 
957   wd->imlibdata = im;
958   wd->type = DIALOG_TYPE_OK;
959   wd->yescallback = cb;
960   wd->userdata = userdata;
961   wd->xwin = xitk_window_create_dialog_window(im, ((title != NULL) ? title : "Notice"),
962 					      0, 0, windoww, windowh);
963   wd->xwin->parent = wd;
964 
965   xitk_window_center_window(im, wd->xwin);
966 
967   wd->widget_list                = xitk_widget_list_new();
968   xitk_dlist_init (&wd->widget_list->list);
969   wd->widget_list->win           = (xitk_window_get_window(wd->xwin));
970 
971   XLOCK (wd->imlibdata->x.x_lock_display, wd->imlibdata->x.disp);
972   wd->widget_list->gc            = (XCreateGC(im->x.disp, (xitk_window_get_window(wd->xwin)),
973 					      None, None));
974   XUNLOCK (wd->imlibdata->x.x_unlock_display, wd->imlibdata->x.disp);
975 
976   /* OK button */
977   if(bwidth > windoww)
978     bwidth = (windoww - 4);
979 
980   bx = ((windoww - bwidth) / 2);
981   by = windowh - 50;
982 
983   XITK_WIDGET_INIT(&lb, im);
984   lb.button_type       = CLICK_BUTTON;
985   lb.label             = button_label;
986   lb.align             = ALIGN_CENTER;
987   lb.callback          = _xitk_window_destroy_window;
988   lb.state_callback    = NULL;
989   lb.userdata          = (void*)wd;
990   lb.skin_element_name = NULL;
991   wd->wyes = xitk_noskin_labelbutton_create (wd->widget_list, &lb,
992     bx, by, bwidth, 30, "Black", "Black", "White", DEFAULT_BOLD_FONT_12);
993   xitk_dlist_add_tail (&wd->widget_list->list, &wd->wyes->node);
994   wd->default_button = wd->wyes;
995 
996   /* Draw text area */
997   {
998     xitk_pixmap_t  *bg;
999     int             width, height;
1000     GC              gc;
1001 
1002     xitk_window_get_window_size(wd->xwin, &width, &height);
1003     bg = xitk_image_create_xitk_pixmap(im, width, height);
1004 
1005     XLOCK (im->x.x_lock_display, im->x.disp);
1006     gc = XCreateGC(im->x.disp, (xitk_window_get_background(wd->xwin)), None, None);
1007     XCopyArea(im->x.disp, (xitk_window_get_background(wd->xwin)), bg->pixmap,
1008 	      gc, 0, 0, width, height, 0, 0);
1009     XCopyArea(im->x.disp, image->image->pixmap, bg->pixmap,
1010 	      image->image->gc, 0, 0, image->width, image->height, 20, (TITLE_BAR_HEIGHT + 20));
1011     XUNLOCK (im->x.x_unlock_display, im->x.disp);
1012 
1013     xitk_window_change_background(im, wd->xwin, bg->pixmap, width, height);
1014 
1015     xitk_image_destroy_xitk_pixmap(bg);
1016 
1017     XLOCK (im->x.x_lock_display, im->x.disp);
1018     XFreeGC(im->x.disp, gc);
1019     XUNLOCK (im->x.x_unlock_display, im->x.disp);
1020 
1021     xitk_image_free_image(im, &image);
1022 
1023   }
1024 
1025   XLOCK (im->x.x_lock_display, im->x.disp);
1026   XMapRaised(im->x.disp, (xitk_window_get_window(wd->xwin)));
1027   XUNLOCK (im->x.x_unlock_display, im->x.disp);
1028 
1029   wd->key = xitk_register_event_handler("xitk_1btn",
1030 					(xitk_window_get_window(wd->xwin)),
1031 					_window_handle_event,
1032 					NULL,
1033 					NULL,
1034 					wd->widget_list,
1035 					(void *)wd);
1036 
1037   xitk_enable_and_show_widget(wd->wyes);
1038 
1039   _xitk_window_set_focus(im->x.disp, (xitk_window_get_window(wd->xwin)));
1040 
1041   return wd->xwin;
1042 }
1043 
xitk_window_dialog_ok_with_width(ImlibData * im,const char * title,xitk_state_callback_t cb,void * userdata,int window_width,int align,const char * message,...)1044 xitk_window_t *xitk_window_dialog_ok_with_width(ImlibData *im, const char *title,
1045 						xitk_state_callback_t cb, void *userdata,
1046                                                 int window_width, int align,
1047                                                 const char *message, ...) {
1048 
1049   va_list        args;
1050   char          *buf;
1051   xitk_window_t *xw = NULL;
1052 
1053   va_start(args, message);
1054   buf = xitk_vasprintf(message, args);
1055   va_end(args);
1056 
1057   if (!buf)
1058     return NULL;
1059 
1060   xw = xitk_window_dialog_one_button_with_width(im, title, _("OK"), cb, userdata, window_width,
1061                                                 align, "%s", buf);
1062   XITK_FREE(buf);
1063   return xw;
1064 }
1065 
_checkbox_label_click(xitk_widget_t * w,void * data)1066 static void _checkbox_label_click(xitk_widget_t *w, void *data) {
1067   xitk_dialog_t *wd = (xitk_dialog_t *) data;
1068 
1069   xitk_checkbox_set_state(wd->checkbox,
1070     (!xitk_checkbox_get_state(wd->checkbox)));
1071   xitk_checkbox_callback_exec(wd->checkbox);
1072 }
1073 
1074 /*
1075  * Create an interactive window, containing 'yes', 'no', 'cancel' buttons.
1076  */
xitk_window_dialog_checkbox_two_buttons_with_width(ImlibData * im,const char * title,const char * button1_label,const char * button2_label,xitk_state_callback_t cb1,xitk_state_callback_t cb2,const char * checkbox_label,int checkbox_state,xitk_state_callback_t cb3,void * userdata,int window_width,int align,const char * message,...)1077 xitk_window_t *xitk_window_dialog_checkbox_two_buttons_with_width(ImlibData *im, const char *title,
1078                                                                   const char *button1_label,
1079                                                                   const char *button2_label,
1080                                                                   xitk_state_callback_t cb1,
1081                                                                   xitk_state_callback_t cb2,
1082                                                                   const char *checkbox_label,
1083                                                                   int checkbox_state,
1084                                                                   xitk_state_callback_t cb3,
1085                                                                   void *userdata,
1086                                                                   int window_width, int align,
1087                                                                   const char *message, ...) {
1088   xitk_dialog_t              *wd;
1089   xitk_labelbutton_widget_t   lb;
1090   int                         windoww = window_width, windowh;
1091   xitk_image_t               *image;
1092   int                         bwidth = 150, bx1, bx2, by;
1093   int                         checkbox_height = 0;
1094 
1095   if((im == NULL) || (window_width == 0) || (message == NULL))
1096     return NULL;
1097 
1098   {
1099     va_list   args;
1100     char     *buf;
1101 
1102     va_start(args, message);
1103     buf = xitk_vasprintf(message, args);
1104     va_end(args);
1105 
1106     if (!buf)
1107       return NULL;
1108 
1109     image = xitk_image_create_image_from_string(im, DEFAULT_FONT_12, windoww - 40, align, buf);
1110     free(buf);
1111   }
1112 
1113   if( checkbox_label )
1114     checkbox_height = 50;
1115 
1116   windowh = (image->height + 50 + checkbox_height) + (TITLE_BAR_HEIGHT + 40);
1117 
1118   wd = (xitk_dialog_t *) xitk_xmalloc(sizeof(xitk_dialog_t));
1119 
1120   wd->imlibdata = im;
1121   wd->type = DIALOG_TYPE_YESNO;
1122   wd->yescallback = cb1;
1123   wd->nocallback = cb2;
1124   wd->userdata = userdata;
1125   wd->xwin = xitk_window_create_dialog_window(im, ((title != NULL) ? title : _("Question?")),
1126 					      0, 0, windoww, windowh);
1127   wd->xwin->parent = wd;
1128   xitk_window_center_window(im, wd->xwin);
1129 
1130   wd->widget_list                = xitk_widget_list_new();
1131   xitk_dlist_init (&wd->widget_list->list);
1132   wd->widget_list->win           = (xitk_window_get_window(wd->xwin));
1133   XLOCK (wd->imlibdata->x.x_lock_display, wd->imlibdata->x.disp);
1134   wd->widget_list->gc            = (XCreateGC(im->x.disp, (xitk_window_get_window(wd->xwin)),
1135 					      None, None));
1136   XUNLOCK (wd->imlibdata->x.x_unlock_display, wd->imlibdata->x.disp);
1137 
1138   /* Checkbox */
1139   if( checkbox_label ) {
1140     int x = 25, y = windowh - 50 - checkbox_height;
1141     xitk_checkbox_widget_t cb;
1142     xitk_label_widget_t lbl;
1143 
1144     XITK_WIDGET_INIT(&cb, im);
1145     XITK_WIDGET_INIT(&lbl, im);
1146 
1147     cb.skin_element_name = NULL;
1148     cb.callback          = cb3;
1149     cb.userdata          = userdata;
1150     wd->checkbox = xitk_noskin_checkbox_create (wd->widget_list, &cb, x, y+5, 10, 10);
1151     xitk_dlist_add_tail (&wd->widget_list->list, &wd->checkbox->node);
1152     xitk_checkbox_set_state(wd->checkbox, checkbox_state);
1153 
1154     lbl.window            = xitk_window_get_window(wd->xwin);
1155     lbl.gc                = (XITK_WIDGET_LIST_GC(wd->widget_list));
1156     lbl.skin_element_name = NULL;
1157     lbl.label             = checkbox_label;
1158     lbl.callback          = _checkbox_label_click;
1159     lbl.userdata          = wd;
1160     wd->checkbox_label = xitk_noskin_label_create (wd->widget_list, &lbl, x + 15, y, windoww - x - 40, 20, DEFAULT_FONT_12);
1161     xitk_dlist_add_tail (&wd->widget_list->list, &wd->checkbox_label->node);
1162   }
1163 
1164   /* Buttons */
1165   if((bwidth * 2) > windoww)
1166     bwidth = (windoww / 2) - 8;
1167 
1168   bx1 = ((windoww - (bwidth * 2)) / 3);
1169   bx2 = (bx1 + bwidth) + bx1;
1170   by = windowh - 50;
1171 
1172   XITK_WIDGET_INIT(&lb, im);
1173   lb.button_type       = CLICK_BUTTON;
1174   lb.label             = button1_label;
1175   lb.align             = ALIGN_CENTER;
1176   lb.callback          = _xitk_window_destroy_window;
1177   lb.state_callback    = NULL;
1178   lb.userdata          = (void*)wd;
1179   lb.skin_element_name = NULL;
1180   wd->wyes = xitk_noskin_labelbutton_create (wd->widget_list, &lb,
1181     bx1, by, bwidth, 30, "Black", "Black", "White", DEFAULT_BOLD_FONT_12);
1182   xitk_dlist_add_tail (&wd->widget_list->list, &wd->wyes->node);
1183 
1184   lb.button_type       = CLICK_BUTTON;
1185   lb.label             = button2_label;
1186   lb.align             = ALIGN_CENTER;
1187   lb.callback          = _xitk_window_destroy_window;
1188   lb.state_callback    = NULL;
1189   lb.userdata          = (void*)wd;
1190   lb.skin_element_name = NULL;
1191   wd->wno = xitk_noskin_labelbutton_create (wd->widget_list, &lb,
1192     bx2, by, bwidth, 30, "Black", "Black", "White", DEFAULT_BOLD_FONT_12);
1193   xitk_dlist_add_tail (&wd->widget_list->list, &wd->wno->node);
1194 
1195   wd->default_button = wd->wno;
1196 
1197   /* Draw text area */
1198   {
1199     xitk_pixmap_t *bg;
1200     int            width, height;
1201     GC             gc;
1202 
1203     xitk_window_get_window_size(wd->xwin, &width, &height);
1204     bg = xitk_image_create_xitk_pixmap(im, width, height);
1205 
1206     XLOCK (im->x.x_lock_display, im->x.disp);
1207     gc = XCreateGC(im->x.disp, (xitk_window_get_background(wd->xwin)), None, None);
1208     XCopyArea(im->x.disp, (xitk_window_get_background(wd->xwin)), bg->pixmap,
1209 	      gc, 0, 0, width, height, 0, 0);
1210     XCopyArea(im->x.disp, image->image->pixmap, bg->pixmap,
1211 	      image->image->gc, 0, 0, image->width, image->height, 20, (TITLE_BAR_HEIGHT + 20));
1212     XUNLOCK (im->x.x_unlock_display, im->x.disp);
1213 
1214     xitk_window_change_background(im, wd->xwin, bg->pixmap, width, height);
1215 
1216     xitk_image_destroy_xitk_pixmap(bg);
1217 
1218     XLOCK (im->x.x_lock_display, im->x.disp);
1219     XFreeGC(im->x.disp, gc);
1220     XUNLOCK (im->x.x_unlock_display, im->x.disp);
1221 
1222     xitk_image_free_image(im, &image);
1223 
1224   }
1225 
1226   XLOCK (im->x.x_lock_display, im->x.disp);
1227   XMapRaised(im->x.disp, (xitk_window_get_window(wd->xwin)));
1228   XUNLOCK (im->x.x_unlock_display, im->x.disp);
1229 
1230   wd->key = xitk_register_event_handler("xitk_2btns",
1231 					(xitk_window_get_window(wd->xwin)),
1232 					_window_handle_event,
1233 					NULL,
1234 					NULL,
1235 					wd->widget_list,
1236 					(void *)wd);
1237   xitk_enable_and_show_widget(wd->wyes);
1238   xitk_enable_and_show_widget(wd->wno);
1239   if( checkbox_label ) {
1240     xitk_enable_and_show_widget(wd->checkbox);
1241     xitk_enable_and_show_widget(wd->checkbox_label);
1242   }
1243 
1244   _xitk_window_set_focus(im->x.disp, (xitk_window_get_window(wd->xwin)));
1245 
1246   return wd->xwin;
1247 }
1248 
1249 /*
1250  *
1251  */
xitk_window_dialog_yesno_with_width(ImlibData * im,const char * title,xitk_state_callback_t ycb,xitk_state_callback_t ncb,void * userdata,int window_width,int align,const char * message,...)1252 xitk_window_t *xitk_window_dialog_yesno_with_width(ImlibData *im, const char *title,
1253 						   xitk_state_callback_t ycb,
1254 						   xitk_state_callback_t ncb,
1255 						   void *userdata,
1256                                                    int window_width, int align,
1257                                                    const char *message, ...) {
1258   va_list        args;
1259   char          *buf;
1260   xitk_window_t *xw = NULL;
1261 
1262   va_start(args, message);
1263   buf = xitk_vasprintf(message, args);
1264   va_end(args);
1265 
1266   if (!buf)
1267     return NULL;
1268 
1269   xw = xitk_window_dialog_two_buttons_with_width(im, title, _("Yes"), _("No"),
1270                                                  ycb, ncb, userdata, window_width, align, "%s", buf);
1271   free(buf);
1272   return xw;
1273 }
1274 
1275 /*
1276  * Create an interactive window, containing 'yes', 'no', 'cancel' buttons.
1277  */
xitk_window_dialog_three_buttons_with_width(ImlibData * im,const char * title,const char * button1_label,const char * button2_label,const char * button3_label,xitk_state_callback_t cb1,xitk_state_callback_t cb2,xitk_state_callback_t cb3,void * userdata,int window_width,int align,const char * message,...)1278 xitk_window_t *xitk_window_dialog_three_buttons_with_width(ImlibData *im, const char *title,
1279                                                            const char *button1_label,
1280                                                            const char *button2_label,
1281                                                            const char *button3_label,
1282 							   xitk_state_callback_t cb1,
1283 							   xitk_state_callback_t cb2,
1284 							   xitk_state_callback_t cb3,
1285 							   void *userdata,
1286                                                            int window_width, int align,
1287                                                            const char *message, ...) {
1288   xitk_dialog_t              *wd;
1289   xitk_labelbutton_widget_t   lb;
1290   int                         windoww = window_width, windowh;
1291   xitk_image_t               *image;
1292   int                         bwidth = 100, bx1, bx2, bx3, by;
1293 
1294   if((im == NULL) || (window_width == 0) || (message == NULL))
1295     return NULL;
1296 
1297   {
1298     va_list   args;
1299     char     *buf;
1300 
1301     va_start(args, message);
1302     buf = xitk_vasprintf(message, args);
1303     va_end(args);
1304 
1305     if (!buf)
1306       return NULL;
1307 
1308     image = xitk_image_create_image_from_string(im, DEFAULT_FONT_12, windoww - 40, align, buf);
1309     XITK_FREE(buf);
1310   }
1311 
1312   windowh = (image->height + 50) + (TITLE_BAR_HEIGHT + 40);
1313 
1314   wd = (xitk_dialog_t *) xitk_xmalloc(sizeof(xitk_dialog_t));
1315 
1316   wd->imlibdata      = im;
1317   wd->type           = DIALOG_TYPE_YESNOCANCEL;
1318   wd->yescallback    = cb1;
1319   wd->nocallback     = cb2;
1320   wd->cancelcallback = cb3;
1321   wd->userdata       = userdata;
1322   wd->xwin           = xitk_window_create_dialog_window(im, ((title != NULL)
1323 							     ? title : _("Question?")),
1324 							0, 0, windoww, windowh);
1325   wd->xwin->parent = wd;
1326 
1327   xitk_window_center_window(im, wd->xwin);
1328 
1329   wd->widget_list                = xitk_widget_list_new();
1330   xitk_dlist_init (&wd->widget_list->list);
1331   wd->widget_list->win           = (xitk_window_get_window(wd->xwin));
1332   XLOCK (wd->imlibdata->x.x_lock_display, wd->imlibdata->x.disp);
1333   wd->widget_list->gc            = (XCreateGC(im->x.disp, (xitk_window_get_window(wd->xwin)),
1334 					      None, None));
1335   XUNLOCK (wd->imlibdata->x.x_unlock_display, wd->imlibdata->x.disp);
1336 
1337   /* Buttons */
1338   if((bwidth * 3) > windoww)
1339     bwidth = (windoww / 3) - 12;
1340 
1341   bx1 = ((windoww - (bwidth * 3)) / 4);
1342   bx2 = (bx1 + bwidth) + bx1;
1343   bx3 = (bx2 + bwidth) + bx1;
1344   by = windowh - 50;
1345 
1346   XITK_WIDGET_INIT(&lb, im);
1347   lb.button_type       = CLICK_BUTTON;
1348   lb.label             = button1_label;
1349   lb.align             = ALIGN_CENTER;
1350   lb.callback          = _xitk_window_destroy_window;
1351   lb.state_callback    = NULL;
1352   lb.userdata          = (void*)wd;
1353   lb.skin_element_name = NULL;
1354   wd->wyes = xitk_noskin_labelbutton_create (wd->widget_list, &lb,
1355     bx1, by, bwidth, 30, "Black", "Black", "White", DEFAULT_BOLD_FONT_12);
1356   xitk_dlist_add_tail (&wd->widget_list->list, &wd->wyes->node);
1357 
1358   lb.button_type       = CLICK_BUTTON;
1359   lb.label             = button2_label;
1360   lb.align             = ALIGN_CENTER;
1361   lb.callback          = _xitk_window_destroy_window;
1362   lb.state_callback    = NULL;
1363   lb.userdata          = (void*)wd;
1364   lb.skin_element_name = NULL;
1365   wd->wno = xitk_noskin_labelbutton_create (wd->widget_list, &lb,
1366     bx2, by, bwidth, 30, "Black", "Black", "White", DEFAULT_BOLD_FONT_12);
1367   xitk_dlist_add_tail (&wd->widget_list->list, &wd->wno->node);
1368 
1369   lb.button_type       = CLICK_BUTTON;
1370   lb.label             = button3_label;
1371   lb.align             = ALIGN_CENTER;
1372   lb.callback          = _xitk_window_destroy_window;
1373   lb.state_callback    = NULL;
1374   lb.userdata          = (void*)wd;
1375   lb.skin_element_name = NULL;
1376   wd->wcancel = xitk_noskin_labelbutton_create (wd->widget_list, &lb,
1377     bx3, by, bwidth, 30, "Black", "Black", "White", DEFAULT_BOLD_FONT_12);
1378   xitk_dlist_add_tail (&wd->widget_list->list, &wd->wcancel->node);
1379 
1380   wd->default_button = wd->wcancel;
1381 
1382   /* Draw text area */
1383   {
1384     xitk_pixmap_t *bg;
1385     int            width, height;
1386     GC             gc;
1387 
1388     xitk_window_get_window_size(wd->xwin, &width, &height);
1389     bg = xitk_image_create_xitk_pixmap(im, width, height);
1390 
1391     XLOCK (im->x.x_lock_display, im->x.disp);
1392     gc = XCreateGC(im->x.disp, (xitk_window_get_background(wd->xwin)), None, None);
1393     XCopyArea(im->x.disp, (xitk_window_get_background(wd->xwin)), bg->pixmap,
1394 	      gc, 0, 0, width, height, 0, 0);
1395     XCopyArea(im->x.disp, image->image->pixmap, bg->pixmap,
1396 	      image->image->gc, 0, 0, image->width, image->height, 20, (TITLE_BAR_HEIGHT + 20));
1397     XUNLOCK (im->x.x_unlock_display, im->x.disp);
1398 
1399     xitk_window_change_background(im, wd->xwin, bg->pixmap, width, height);
1400 
1401     xitk_image_destroy_xitk_pixmap(bg);
1402     XLOCK (im->x.x_lock_display, im->x.disp);
1403     XFreeGC(im->x.disp, gc);
1404     XUNLOCK (im->x.x_unlock_display, im->x.disp);
1405 
1406     xitk_image_free_image(im, &image);
1407 
1408   }
1409 
1410   XLOCK (im->x.x_lock_display, im->x.disp);
1411   XMapRaised(im->x.disp, (xitk_window_get_window(wd->xwin)));
1412   XUNLOCK (im->x.x_unlock_display, im->x.disp);
1413 
1414   wd->key = xitk_register_event_handler("xitk_3btns",
1415 					(xitk_window_get_window(wd->xwin)),
1416 					_window_handle_event,
1417 					NULL,
1418 					NULL,
1419 					wd->widget_list,
1420 					(void *)wd);
1421   xitk_enable_and_show_widget(wd->wyes);
1422   xitk_enable_and_show_widget(wd->wno);
1423   xitk_enable_and_show_widget(wd->wcancel);
1424 
1425   _xitk_window_set_focus(im->x.disp, (xitk_window_get_window(wd->xwin)));
1426 
1427   return wd->xwin;
1428 }
1429 
xitk_window_dialog_yesnocancel_with_width(ImlibData * im,const char * title,xitk_state_callback_t ycb,xitk_state_callback_t ncb,xitk_state_callback_t ccb,void * userdata,int window_width,int align,const char * message,...)1430 xitk_window_t *xitk_window_dialog_yesnocancel_with_width(ImlibData *im, const char *title,
1431 							 xitk_state_callback_t ycb,
1432 							 xitk_state_callback_t ncb,
1433 							 xitk_state_callback_t ccb,
1434 							 void *userdata,
1435                                                          int window_width, int align,
1436                                                          const char *message, ...) {
1437   va_list        args;
1438   char          *buf;
1439   xitk_window_t *xw = NULL;
1440 
1441   va_start(args, message);
1442   buf = xitk_vasprintf(message, args);
1443   va_end(args);
1444 
1445   if (!buf)
1446     return NULL;
1447 
1448   xw = xitk_window_dialog_three_buttons_with_width(im, title, _("Yes"), _("No"), _("Cancel"),
1449                                                    ycb, ncb, ccb, userdata, window_width, align, "%s", buf);
1450   free(buf);
1451   return xw;
1452 }
1453 
xitk_window_set_parent_window(xitk_window_t * xwin,Window parent)1454 void xitk_window_set_parent_window(xitk_window_t *xwin, Window parent) {
1455   if(xwin)
1456     xwin->win_parent = parent;
1457 }
1458