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 <sys/stat.h>
26 #include <errno.h>
27
28 #include <X11/keysym.h>
29
30 #include "common.h"
31 #include "skins_internal.h"
32
33
34 #define NORMAL_CURS 0
35 #define WAIT_CURS 1
36
37 #define MAX_DISP_ENTRIES 5
38
39 #define WINDOW_WIDTH 630
40 #define WINDOW_HEIGHT 446
41
42 #define PREVIEW_WIDTH (WINDOW_WIDTH - 30)
43 #define PREVIEW_HEIGHT 220
44 #define PREVIEW_RATIO ((float)PREVIEW_WIDTH / (float)PREVIEW_HEIGHT)
45
46 typedef struct {
47 char *name;
48 struct {
49 char *name;
50 char *email;
51 } author;
52 struct {
53 char *href;
54 char *preview;
55 int version;
56 int maintained;
57 } skin;
58 } slx_entry_t;
59
60 static struct {
61 xitk_window_t *xwin;
62
63 xitk_widget_t *browser;
64
65 xitk_image_t *preview_image;
66
67 xitk_widget_list_t *widget_list;
68 char **entries;
69 int num;
70
71 slx_entry_t **slxs;
72
73 xitk_register_key_t widget_key;
74
75 int running;
76 } skdloader;
77
skins_get_slx_entries(char * url)78 static slx_entry_t **skins_get_slx_entries(char *url) {
79 int result;
80 slx_entry_t **slxs = NULL, slx;
81 xml_node_t *xml_tree, *skin_entry, *skin_ref;
82 xml_property_t *skin_prop;
83 download_t download;
84
85 download.buf = NULL;
86 download.error = NULL;
87 download.size = 0;
88 download.status = 0;
89
90 if((network_download(url, &download))) {
91 int entries_slx = 0;
92
93 xml_parser_init_R(xml_parser_t *xml, download.buf, download.size, XML_PARSER_CASE_INSENSITIVE);
94 if((result = xml_parser_build_tree_R(xml, &xml_tree)) != XML_PARSER_OK)
95 goto __failure;
96
97 if(!strcasecmp(xml_tree->name, "SLX")) {
98
99 skin_prop = xml_tree->props;
100
101 while((skin_prop) && (strcasecmp(skin_prop->name, "VERSION")))
102 skin_prop = skin_prop->next;
103
104 if(skin_prop) {
105 int version_major, version_minor = 0;
106
107 if((((sscanf(skin_prop->value, "%d.%d", &version_major, &version_minor)) == 2) ||
108 ((sscanf(skin_prop->value, "%d", &version_major)) == 1)) &&
109 ((version_major >= 2) && (version_minor >= 0))) {
110
111 skin_entry = xml_tree->child;
112
113 slx.name = slx.author.name = slx.author.email = slx.skin.href = slx.skin.preview = NULL;
114 slx.skin.version = slx.skin.maintained = 0;
115
116 while(skin_entry) {
117
118 if(!strcasecmp(skin_entry->name, "SKIN")) {
119 skin_ref = skin_entry->child;
120
121 while(skin_ref) {
122
123 if(!strcasecmp(skin_ref->name, "NAME")) {
124 slx.name = strdup(skin_ref->data);
125 }
126 else if(!strcasecmp(skin_ref->name, "AUTHOR")) {
127 for(skin_prop = skin_ref->props; skin_prop; skin_prop = skin_prop->next) {
128 if(!strcasecmp(skin_prop->name, "NAME")) {
129 slx.author.name = strdup(skin_prop->value);
130 }
131 else if(!strcasecmp(skin_prop->name, "EMAIL")) {
132 slx.author.email = strdup(skin_prop->value);
133 }
134 }
135 }
136 else if(!strcasecmp(skin_ref->name, "REF")) {
137 for(skin_prop = skin_ref->props; skin_prop; skin_prop = skin_prop->next) {
138 if(!strcasecmp(skin_prop->name, "HREF")) {
139 slx.skin.href = strdup(skin_prop->value);
140 }
141 else if(!strcasecmp(skin_prop->name, "VERSION")) {
142 slx.skin.version = atoi(skin_prop->value);
143 }
144 else if(!strcasecmp(skin_prop->name, "MAINTAINED")) {
145 slx.skin.maintained = get_bool_value(skin_prop->value);
146 }
147 }
148 }
149 else if(!strcasecmp(skin_ref->name, "PREVIEW")) {
150 for(skin_prop = skin_ref->props; skin_prop; skin_prop = skin_prop->next) {
151 if(!strcasecmp(skin_prop->name, "HREF")) {
152 slx.skin.preview = strdup(skin_prop->value);
153 }
154 }
155 }
156
157 skin_ref = skin_ref->next;
158 }
159
160 if(slx.name && slx.skin.href &&
161 ((slx.skin.version >= SKIN_IFACE_VERSION) && slx.skin.maintained)) {
162
163 #if 0
164 printf("get slx: Skin number %d:\n", entries_slx);
165 printf(" Name: %s\n", slx.name);
166 printf(" Author Name: %s\n", slx.author.name);
167 printf(" Author email: %s\n", slx.author.email);
168 printf(" Href: %s\n", slx.skin.href);
169 printf(" Preview: %s\n", slx.skin.preview);
170 printf(" Version: %d\n", slx.skin.version);
171 printf(" Maintained: %d\n", slx.skin.maintained);
172 printf("--\n");
173 #endif
174
175 slxs = (slx_entry_t **) realloc(slxs, sizeof(slx_entry_t *) * (entries_slx + 2));
176
177 slxs[entries_slx] = (slx_entry_t *) calloc(1, sizeof(slx_entry_t));
178 slxs[entries_slx]->name = strdup(slx.name);
179 slxs[entries_slx]->author.name = slx.author.name ? strdup(slx.author.name) : NULL;
180 slxs[entries_slx]->author.email = slx.author.email ? strdup(slx.author.email) : NULL;
181 slxs[entries_slx]->skin.href = strdup(slx.skin.href);
182 slxs[entries_slx]->skin.preview = slx.skin.preview ? strdup(slx.skin.preview) : NULL;
183 slxs[entries_slx]->skin.version = slx.skin.version;
184 slxs[entries_slx]->skin.maintained = slx.skin.maintained;
185
186 entries_slx++;
187
188 slxs[entries_slx] = NULL;
189
190 }
191
192 SAFE_FREE(slx.name);
193 SAFE_FREE(slx.author.name);
194 SAFE_FREE(slx.author.email);
195 SAFE_FREE(slx.skin.href);
196 SAFE_FREE(slx.skin.preview);
197 slx.skin.version = 0;
198 slx.skin.maintained = 0;
199 }
200
201 skin_entry = skin_entry->next;
202 }
203 }
204 }
205 }
206
207 xml_parser_free_tree(xml_tree);
208 xml_parser_finalize_R(xml);
209
210 if(entries_slx)
211 slxs[entries_slx] = NULL;
212
213 }
214 else
215 xine_error(_("Unable to retrieve skin list from %s: %s"), url, download.error);
216
217 __failure:
218
219 free(download.buf);
220 free(download.error);
221
222 return slxs;
223 }
224
225 /*
226 * Remote skin loader
227 */
download_set_cursor_state(int state)228 static void download_set_cursor_state(int state) {
229 if(state == WAIT_CURS)
230 xitk_cursors_define_window_cursor(gGui->display, (xitk_window_get_window(skdloader.xwin)), xitk_cursor_watch);
231 else
232 xitk_cursors_restore_window_cursor(gGui->display, (xitk_window_get_window(skdloader.xwin)));
233 }
234
download_skin_exit(xitk_widget_t * w,void * data)235 static void download_skin_exit(xitk_widget_t *w, void *data) {
236 int i;
237
238 if(skdloader.running) {
239 xitk_unregister_event_handler(&skdloader.widget_key);
240
241 if(skdloader.preview_image)
242 xitk_image_free_image(gGui->imlib_data, &skdloader.preview_image);
243
244 xitk_destroy_widgets(skdloader.widget_list);
245 xitk_window_destroy_window(gGui->imlib_data, skdloader.xwin);
246
247 skdloader.xwin = NULL;
248
249 /* xitk_dlist_init (&skdloader.widget_list->list); */
250
251 gGui->x_lock_display (gGui->display);
252 XFreeGC(gGui->display, (XITK_WIDGET_LIST_GC(skdloader.widget_list)));
253 gGui->x_unlock_display (gGui->display);
254
255 XITK_WIDGET_LIST_FREE(skdloader.widget_list);
256
257 for(i = 0; i < skdloader.num; i++) {
258 SAFE_FREE(skdloader.slxs[i]->name);
259 SAFE_FREE(skdloader.slxs[i]->author.name);
260 SAFE_FREE(skdloader.slxs[i]->author.email);
261 SAFE_FREE(skdloader.slxs[i]->skin.href);
262 SAFE_FREE(skdloader.slxs[i]->skin.preview);
263 free(skdloader.slxs[i]);
264 free(skdloader.entries[i]);
265 }
266
267 free(skdloader.slxs);
268 free(skdloader.entries);
269
270 skdloader.num = 0;
271
272 skdloader.running = 0;
273
274 try_to_set_input_focus(gGui->video_window);
275 }
276 }
277
download_update_blank_preview(void)278 static void download_update_blank_preview(void) {
279
280 gGui->x_lock_display (gGui->display);
281 XSetForeground(gGui->display,(XITK_WIDGET_LIST_GC(skdloader.widget_list)),
282 (xitk_get_pixel_color_from_rgb(gGui->imlib_data, 52, 52, 52)));
283 XFillRectangle(gGui->display,
284 (XITK_WIDGET_LIST_WINDOW(skdloader.widget_list)),
285 (XITK_WIDGET_LIST_GC(skdloader.widget_list)), 15, 34, PREVIEW_WIDTH, PREVIEW_HEIGHT);
286 gGui->x_unlock_display (gGui->display);
287
288 }
289
redraw_preview(void)290 static void redraw_preview(void) {
291 int x, y;
292
293 x = 15 + ((PREVIEW_WIDTH - skdloader.preview_image->image->width) >> 1);
294 y = 34 + ((PREVIEW_HEIGHT - skdloader.preview_image->image->height) >> 1);
295
296 if(skdloader.preview_image->mask && skdloader.preview_image->mask->pixmap) {
297 gGui->x_lock_display (gGui->display);
298 XSetClipOrigin(gGui->display, (XITK_WIDGET_LIST_GC(skdloader.widget_list)), x, y);
299 XSetClipMask(gGui->display, (XITK_WIDGET_LIST_GC(skdloader.widget_list)), skdloader.preview_image->mask->pixmap);
300 gGui->x_unlock_display (gGui->display);
301 }
302
303 gGui->x_lock_display (gGui->display);
304 XCopyArea (gGui->display, skdloader.preview_image->image->pixmap,
305 (XITK_WIDGET_LIST_WINDOW(skdloader.widget_list)), (XITK_WIDGET_LIST_GC(skdloader.widget_list)), 0, 0,
306 skdloader.preview_image->image->width, skdloader.preview_image->image->height, x, y);
307 XSetClipMask(gGui->display, (XITK_WIDGET_LIST_GC(skdloader.widget_list)), None);
308 XSync(gGui->display, False);
309 gGui->x_unlock_display (gGui->display);
310 }
311
download_update_preview(void)312 static void download_update_preview(void) {
313
314 download_update_blank_preview();
315
316 if(skdloader.preview_image && skdloader.preview_image->image && skdloader.preview_image->image->pixmap)
317 redraw_preview();
318 }
319
download_skin_preview(xitk_widget_t * w,void * data,int selected)320 static void download_skin_preview(xitk_widget_t *w, void *data, int selected) {
321 download_t download;
322
323 if(skdloader.slxs[selected]->skin.preview == NULL)
324 return;
325
326 download.buf = NULL;
327 download.error = NULL;
328 download.size = 0;
329 download.status = 0;
330
331 download_set_cursor_state(WAIT_CURS);
332
333 if((network_download(skdloader.slxs[selected]->skin.preview, &download))) {
334 char *skpname;
335 FILE *fd;
336 char tmpfile[XITK_PATH_MAX + XITK_NAME_MAX + 2];
337
338 skpname = strrchr(skdloader.slxs[selected]->skin.preview, '/');
339
340 if(skpname)
341 skpname++;
342 else
343 skpname = skdloader.slxs[selected]->skin.preview;
344
345 snprintf(tmpfile, sizeof(tmpfile), "%s%u%s", "/tmp/", (unsigned int)time(NULL), skpname);
346
347 if((fd = fopen(tmpfile, "w+b")) != NULL) {
348 ImlibImage *img = NULL;
349
350 fwrite(download.buf, download.size, 1, fd);
351 fflush(fd);
352 fclose(fd);
353
354 gGui->x_lock_display (gGui->display);
355 img = Imlib_load_image(gGui->imlib_data, tmpfile);
356 gGui->x_unlock_display (gGui->display);
357
358 if(img) {
359 xitk_image_t *ximg, *oimg = skdloader.preview_image;
360 int preview_width, preview_height;
361 float ratio;
362
363 preview_width = img->rgb_width;
364 preview_height = img->rgb_height;
365
366 ratio = ((float)preview_width / (float)preview_height);
367
368 if(ratio > PREVIEW_RATIO) {
369 if(preview_width > PREVIEW_WIDTH) {
370 preview_width = PREVIEW_WIDTH;
371 preview_height = (float)preview_width / ratio;
372 }
373 }
374 else {
375 if(preview_height > PREVIEW_HEIGHT) {
376 preview_height = PREVIEW_HEIGHT;
377 preview_width = (float)preview_height * ratio;
378 }
379 }
380
381 /* Rescale preview */
382 gGui->x_lock_display (gGui->display);
383 Imlib_render(gGui->imlib_data, img, preview_width, preview_height);
384 gGui->x_unlock_display (gGui->display);
385
386 ximg = (xitk_image_t *) xitk_xmalloc(sizeof(xitk_image_t));
387 ximg->width = preview_width;
388 ximg->height = preview_height;
389
390 ximg->image = xitk_image_create_xitk_pixmap(gGui->imlib_data, preview_width, preview_height);
391 ximg->mask = xitk_image_create_xitk_mask_pixmap(gGui->imlib_data, preview_width, preview_height);
392
393 gGui->x_lock_display (gGui->display);
394 ximg->image->pixmap = Imlib_copy_image(gGui->imlib_data, img);
395 ximg->mask->pixmap = Imlib_copy_mask(gGui->imlib_data, img);
396 Imlib_destroy_image(gGui->imlib_data, img);
397 gGui->x_unlock_display (gGui->display);
398
399 skdloader.preview_image = ximg;
400
401 if(oimg)
402 xitk_image_free_image(gGui->imlib_data, &oimg);
403
404 download_update_preview();
405 }
406
407 unlink(tmpfile);
408 }
409 }
410 else {
411 xine_error(_("Unable to download '%s': %s"),
412 skdloader.slxs[selected]->skin.preview, download.error);
413 download_update_blank_preview();
414 }
415
416 download_set_cursor_state(NORMAL_CURS);
417
418 free(download.buf);
419 free(download.error);
420 }
421
download_skin_select(xitk_widget_t * w,void * data)422 static void download_skin_select(xitk_widget_t *w, void *data) {
423 int selected = xitk_browser_get_current_selected(skdloader.browser);
424 download_t download;
425
426 if(selected < 0)
427 return;
428
429 download.buf = NULL;
430 download.error = NULL;
431 download.size = 0;
432 download.status = 0;
433
434 download_set_cursor_state(WAIT_CURS);
435
436 if((network_download(skdloader.slxs[selected]->skin.href, &download))) {
437 char *filename;
438
439 filename = strrchr(skdloader.slxs[selected]->skin.href, '/');
440
441 if(filename)
442 filename++;
443 else
444 filename = skdloader.slxs[selected]->skin.href;
445
446 if(filename[0]) {
447 struct stat st;
448 char skindir[XITK_PATH_MAX + 1];
449
450 snprintf(skindir, sizeof(skindir), "%s%s", xine_get_homedir(), "/.xine/skins");
451
452 /*
453 * Make sure to have the directory
454 */
455 if(stat(skindir, &st) < 0)
456 (void) mkdir_safe(skindir);
457
458 if(stat(skindir, &st) < 0) {
459 xine_error(_("Unable to create '%s' directory: %s."), skindir, strerror(errno));
460 }
461 else {
462 char tmpskin[XITK_PATH_MAX + XITK_NAME_MAX + 2];
463 FILE *fd;
464
465 snprintf(tmpskin, sizeof(tmpskin), "%s%u%s", "/tmp/", (unsigned int)time(NULL), filename);
466
467 if((fd = fopen(tmpskin, "w+b")) != NULL) {
468 char buffer[2048];
469 char *cmd;
470 char *fskin_path;
471 int i, skin_found = -1, len;
472
473 fwrite(download.buf, download.size, 1, fd);
474 fflush(fd);
475 fclose(fd);
476
477 cmd = xitk_asprintf("%s %s %s %s %s", "which tar > /dev/null 2>&1 && cd ", skindir, " && gunzip -c ", tmpskin, " | tar xf -");
478 if (cmd)
479 xine_system(0, cmd);
480 free(cmd);
481 unlink(tmpskin);
482
483 len = strlen(filename) - strlen(".tar.gz");
484 if (len > sizeof(buffer) - 1) len = sizeof(buffer) - 1;
485 strncpy(buffer, filename, len);
486 buffer[len] = '\0';
487
488 fskin_path = xitk_asprintf("%s/%s/%s", skindir, buffer, "doinst.sh");
489 if (fskin_path && is_a_file(fskin_path)) {
490 char *doinst;
491
492 doinst = xitk_asprintf("%s %s/%s %s", "cd", skindir, buffer, "&& ./doinst.sh");
493 if (doinst)
494 xine_system(0, doinst);
495 free(doinst);
496 }
497 free(fskin_path);
498
499 for(i = 0; i < skins_avail_num; i++) {
500 if((!strcmp(skins_avail[i]->pathname, skindir))
501 && (!strcmp(skins_avail[i]->skin, buffer))) {
502 skin_found = i;
503 break;
504 }
505 }
506
507 if(skin_found == -1) {
508 skins_avail = (skins_locations_t **) realloc(skins_avail, (skins_avail_num + 2) * sizeof(skins_locations_t*));
509 skin_names = (char **) realloc(skin_names, (skins_avail_num + 2) * sizeof(char *));
510
511 skins_avail[skins_avail_num] = (skins_locations_t *) calloc(1, sizeof(skins_locations_t));
512 skins_avail[skins_avail_num]->pathname = strdup(skindir);
513 skins_avail[skins_avail_num]->skin = strdup(buffer);
514 skins_avail[skins_avail_num]->number = skins_avail_num;
515
516 skin_names[skins_avail_num] = strdup(skins_avail[skins_avail_num]->skin);
517
518 skins_avail_num++;
519
520 skins_avail[skins_avail_num] = NULL;
521 skin_names[skins_avail_num] = NULL;
522
523 /* Re-register skin enum config, a new one has been added */
524 (void) xine_config_register_enum (__xineui_global_xine_instance, "gui.skin",
525 (get_skin_offset(DEFAULT_SKIN)),
526 skin_names,
527 _("gui skin theme"),
528 CONFIG_NO_HELP,
529 CONFIG_LEVEL_EXP,
530 skin_change_cb,
531 CONFIG_NO_DATA);
532 }
533 else
534 xine_info(_("Skin %s correctly installed"), buffer);
535
536 /* Okay, load this skin */
537 select_new_skin((skin_found >= 0) ? skin_found : skins_avail_num - 1);
538 }
539 else
540 xine_error(_("Unable to create '%s'."), tmpskin);
541
542 }
543 }
544 }
545 else
546 xine_error(_("Unable to download '%s': %s"),
547 skdloader.slxs[selected]->skin.href, download.error);
548
549 download_set_cursor_state(NORMAL_CURS);
550
551 free(download.buf);
552 free(download.error);
553
554 download_skin_exit(w, NULL);
555 }
556
download_skin_handle_event(XEvent * event,void * data)557 static void download_skin_handle_event(XEvent *event, void *data) {
558
559 switch(event->type) {
560
561 case Expose:
562 if(event->xexpose.count == 0)
563 download_update_preview();
564 break;
565
566 case KeyPress:
567 if(xitk_get_key_pressed(event) == XK_Escape)
568 download_skin_exit(NULL, NULL);
569 else
570 gui_handle_event (event, gGui);
571 break;
572
573 }
574 }
575
download_skin_end(void)576 void download_skin_end(void) {
577 download_skin_exit(NULL, NULL);
578 }
579
download_skin(char * url)580 void download_skin(char *url) {
581 slx_entry_t **slxs;
582 xitk_window_t *xwin;
583 xitk_pixmap_t *bg;
584 int w, width, height;
585 xitk_widget_t *widget;
586
587 if(skdloader.running)
588 {
589 gGui->x_lock_display (gGui->display);
590 XRaiseWindow(gGui->display, xitk_window_get_window(skdloader.xwin));
591 XSetInputFocus(gGui->display, xitk_window_get_window(skdloader.xwin), RevertToParent, CurrentTime);
592 gGui->x_unlock_display (gGui->display);
593 return;
594 }
595
596 w = 300;
597 gGui->x_lock_display (gGui->display);
598 gGui->x_unlock_display (gGui->display);
599
600 xwin = xitk_window_dialog_button_free_with_width(gGui->imlib_data, _("Be patient..."),
601 w, ALIGN_CENTER,
602 _("Retrieving skin list from %s"), url);
603
604 while(!xitk_is_window_visible(gGui->display, xitk_window_get_window(xwin)))
605 xine_usec_sleep(5000);
606
607 if(!gGui->use_root_window && gGui->video_display == gGui->display) {
608 gGui->x_lock_display (gGui->display);
609 XSetTransientForHint (gGui->display,
610 xitk_window_get_window(xwin), gGui->video_window);
611 gGui->x_unlock_display (gGui->display);
612 }
613 layer_above_video(xitk_window_get_window(xwin));
614
615 if((slxs = skins_get_slx_entries(url)) != NULL) {
616 int i;
617 xitk_browser_widget_t br;
618 xitk_labelbutton_widget_t lb;
619 GC gc;
620 int x, y;
621
622 xitk_window_dialog_destroy(xwin);
623
624 XITK_WIDGET_INIT(&br, gGui->imlib_data);
625 XITK_WIDGET_INIT(&lb, gGui->imlib_data);
626
627 #if 0
628 for(i = 0; slxs[i]; i++) {
629 printf("download skins: Skin number %d:\n", i);
630 printf(" Name: %s\n", slxs[i]->name);
631 printf(" Author Name: %s\n", slxs[i]->author.name);
632 printf(" Author email: %s\n", slxs[i]->author.email);
633 printf(" Href: %s\n", slxs[i]->skin.href);
634 printf(" Version: %d\n", slxs[i]->skin.version);
635 printf(" Maintained: %d\n", slxs[i]->skin.maintained);
636 printf("--\n");
637 }
638 #endif
639
640 skdloader.running = 1;
641
642 gGui->x_lock_display (gGui->display);
643 x = ((DisplayWidth(gGui->display, gGui->screen)) >> 1) - (WINDOW_WIDTH >> 1);
644 y = ((DisplayHeight(gGui->display, gGui->screen)) >> 1) - (WINDOW_HEIGHT >> 1);
645 gGui->x_unlock_display (gGui->display);
646
647 skdloader.xwin = xitk_window_create_dialog_window(gGui->imlib_data,
648 _("Choose a skin to download..."),
649 x, y, WINDOW_WIDTH, WINDOW_HEIGHT);
650
651 set_window_states_start((xitk_window_get_window(skdloader.xwin)));
652
653 gGui->x_lock_display (gGui->display);
654 gc = XCreateGC(gGui->display,
655 (xitk_window_get_window(skdloader.xwin)), None, None);
656 gGui->x_unlock_display (gGui->display);
657
658 xitk_window_get_window_size(skdloader.xwin, &width, &height);
659 bg = xitk_image_create_xitk_pixmap(gGui->imlib_data, width, height);
660 gGui->x_lock_display (gGui->display);
661 XCopyArea(gGui->display, (xitk_window_get_background(skdloader.xwin)), bg->pixmap,
662 bg->gc, 0, 0, width, height, 0, 0);
663 gGui->x_unlock_display (gGui->display);
664
665 skdloader.widget_list = xitk_widget_list_new();
666 xitk_widget_list_set(skdloader.widget_list,
667 WIDGET_LIST_WINDOW, (void *) (xitk_window_get_window(skdloader.xwin)));
668 xitk_widget_list_set(skdloader.widget_list, WIDGET_LIST_GC, gc);
669
670 skdloader.slxs = slxs;
671
672 i = 0;
673 while(slxs[i]) {
674
675 skdloader.entries = (char **) realloc(skdloader.entries, sizeof(char *) * (i + 2));
676
677 skdloader.entries[i] = strdup(slxs[i]->name);
678 i++;
679 }
680 skdloader.entries[i] = NULL;
681
682 skdloader.num = i;
683
684 skdloader.preview_image = NULL;
685
686 x = 15;
687 y = 34 + PREVIEW_HEIGHT + 14;
688
689 br.arrow_up.skin_element_name = NULL;
690 br.slider.skin_element_name = NULL;
691 br.arrow_dn.skin_element_name = NULL;
692 br.browser.skin_element_name = NULL;
693 br.browser.max_displayed_entries = MAX_DISP_ENTRIES;
694 br.browser.num_entries = skdloader.num;
695 br.browser.entries = (const char *const *)skdloader.entries;
696 br.callback = download_skin_preview;
697 br.dbl_click_callback = NULL;
698 br.parent_wlist = skdloader.widget_list;
699 br.userdata = NULL;
700 skdloader.browser = xitk_noskin_browser_create (skdloader.widget_list, &br,
701 (XITK_WIDGET_LIST_GC(skdloader.widget_list)), x + 5, y + 5, WINDOW_WIDTH - (30 + 10 + 16), 20, 16, br_fontname);
702 xitk_add_widget (skdloader.widget_list, skdloader.browser);
703
704 xitk_browser_update_list(skdloader.browser,
705 (const char *const *)skdloader.entries, NULL, skdloader.num, 0);
706
707 xitk_enable_and_show_widget(skdloader.browser);
708
709 draw_rectangular_inner_box(gGui->imlib_data, bg, x, y,
710 (WINDOW_WIDTH - 30 - 1), (MAX_DISP_ENTRIES * 20 + 16 + 10 - 1));
711
712 xitk_window_change_background(gGui->imlib_data, skdloader.xwin, bg->pixmap, width, height);
713 xitk_image_destroy_xitk_pixmap(bg);
714
715 y = WINDOW_HEIGHT - (23 + 15);
716 x = 15;
717
718 lb.button_type = CLICK_BUTTON;
719 lb.label = _("Load");
720 lb.align = ALIGN_CENTER;
721 lb.callback = download_skin_select;
722 lb.state_callback = NULL;
723 lb.userdata = NULL;
724 lb.skin_element_name = NULL;
725 widget = xitk_noskin_labelbutton_create (skdloader.widget_list,
726 &lb, x, y, 100, 23, "Black", "Black", "White", btnfontname);
727 xitk_add_widget (skdloader.widget_list, widget);
728 xitk_enable_and_show_widget(widget);
729
730 x = WINDOW_WIDTH - (100 + 15);
731
732 lb.button_type = CLICK_BUTTON;
733 lb.label = _("Cancel");
734 lb.align = ALIGN_CENTER;
735 lb.callback = download_skin_exit;
736 lb.state_callback = NULL;
737 lb.userdata = NULL;
738 lb.skin_element_name = NULL;
739 widget = xitk_noskin_labelbutton_create (skdloader.widget_list,
740 &lb, x, y, 100, 23, "Black", "Black", "White", btnfontname);
741 xitk_add_widget (skdloader.widget_list, widget);
742 xitk_enable_and_show_widget(widget);
743
744 skdloader.widget_key = xitk_register_event_handler("skdloader",
745 (xitk_window_get_window(skdloader.xwin)),
746 download_skin_handle_event,
747 NULL,
748 NULL,
749 skdloader.widget_list,
750 NULL);
751
752 gGui->x_lock_display (gGui->display);
753 XRaiseWindow(gGui->display, xitk_window_get_window(skdloader.xwin));
754 XMapWindow(gGui->display, xitk_window_get_window(skdloader.xwin));
755 if(!gGui->use_root_window && gGui->video_display == gGui->display)
756 XSetTransientForHint (gGui->display,
757 xitk_window_get_window(skdloader.xwin), gGui->video_window);
758 gGui->x_unlock_display (gGui->display);
759 layer_above_video(xitk_window_get_window(skdloader.xwin));
760
761 try_to_set_input_focus(xitk_window_get_window(skdloader.xwin));
762 download_update_blank_preview();
763 }
764 else
765 xitk_window_dialog_destroy(xwin);
766 }
767