util: fix image leak in wmsebg's parseTexture (Coverity #50166)
[wmaker-crm.git] / src / dialog.c
blob90e7192bf9b0e36986cd21f37516e05ea9588ab1
1 /* dialog.c - dialog windows for internal use
3 * Window Maker window manager
5 * Copyright (c) 1997-2003 Alfredo K. Kojima
6 * Copyright (c) 1998-2003 Dan Pascu
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23 #include "wconfig.h"
25 #include <X11/Xlib.h>
26 #include <X11/Xutil.h>
27 #include <X11/keysym.h>
29 #include <stdlib.h>
30 #include <stdio.h>
31 #include <unistd.h>
32 #include <string.h>
33 #include <sys/types.h>
34 #include <sys/stat.h>
35 #include <dirent.h>
36 #include <limits.h>
38 #ifdef HAVE_MALLOC_H
39 #include <malloc.h>
40 #endif
42 #include <signal.h>
43 #ifdef __FreeBSD__
44 #include <sys/signal.h>
45 #endif
47 #ifndef PATH_MAX
48 #define PATH_MAX DEFAULT_PATH_MAX
49 #endif
51 #include "WindowMaker.h"
52 #include "GNUstep.h"
53 #include "screen.h"
54 #include "window.h"
55 #include "dialog.h"
56 #include "misc.h"
57 #include "stacking.h"
58 #include "framewin.h"
59 #include "window.h"
60 #include "actions.h"
61 #include "xinerama.h"
64 static WMPoint getCenter(WScreen * scr, int width, int height)
66 return wGetPointToCenterRectInHead(scr, wGetHeadForPointerLocation(scr), width, height);
69 int wMessageDialog(WScreen *scr, const char *title, const char *message, const char *defBtn, const char *altBtn, const char *othBtn)
71 WMAlertPanel *panel;
72 Window parent;
73 WWindow *wwin;
74 int result;
75 WMPoint center;
77 panel = WMCreateAlertPanel(scr->wmscreen, NULL, title, message, defBtn, altBtn, othBtn);
79 parent = XCreateSimpleWindow(dpy, scr->root_win, 0, 0, 400, 180, 0, 0, 0);
81 XReparentWindow(dpy, WMWidgetXID(panel->win), parent, 0, 0);
83 center = getCenter(scr, 400, 180);
84 wwin = wManageInternalWindow(scr, parent, None, NULL, center.x, center.y, 400, 180);
85 wwin->client_leader = WMWidgetXID(panel->win);
87 WMMapWidget(panel->win);
89 wWindowMap(wwin);
91 WMRunModalLoop(WMWidgetScreen(panel->win), WMWidgetView(panel->win));
93 result = panel->result;
95 WMUnmapWidget(panel->win);
97 wUnmanageWindow(wwin, False, False);
99 WMDestroyAlertPanel(panel);
101 XDestroyWindow(dpy, parent);
103 return result;
106 static void toggleSaveSession(WMWidget *w, void *data)
108 /* Parameter not used, but tell the compiler that it is ok */
109 (void) data;
111 wPreferences.save_session_on_exit = WMGetButtonSelected((WMButton *) w);
114 int wExitDialog(WScreen *scr, const char *title, const char *message, const char *defBtn, const char *altBtn, const char *othBtn)
116 WMAlertPanel *panel;
117 WMButton *saveSessionBtn;
118 Window parent;
119 WWindow *wwin;
120 WMPoint center;
121 int result;
123 panel = WMCreateAlertPanel(scr->wmscreen, NULL, title, message, defBtn, altBtn, othBtn);
125 /* add save session button */
126 saveSessionBtn = WMCreateSwitchButton(panel->hbox);
127 WMSetButtonAction(saveSessionBtn, toggleSaveSession, NULL);
128 WMAddBoxSubview(panel->hbox, WMWidgetView(saveSessionBtn), False, True, 200, 0, 0);
129 WMSetButtonText(saveSessionBtn, _("Save workspace state"));
130 WMSetButtonSelected(saveSessionBtn, wPreferences.save_session_on_exit);
131 WMRealizeWidget(saveSessionBtn);
132 WMMapWidget(saveSessionBtn);
134 parent = XCreateSimpleWindow(dpy, scr->root_win, 0, 0, 400, 180, 0, 0, 0);
136 XReparentWindow(dpy, WMWidgetXID(panel->win), parent, 0, 0);
138 center = getCenter(scr, 400, 180);
139 wwin = wManageInternalWindow(scr, parent, None, NULL, center.x, center.y, 400, 180);
141 wwin->client_leader = WMWidgetXID(panel->win);
143 WMMapWidget(panel->win);
145 wWindowMap(wwin);
147 WMRunModalLoop(WMWidgetScreen(panel->win), WMWidgetView(panel->win));
149 result = panel->result;
151 WMUnmapWidget(panel->win);
153 wUnmanageWindow(wwin, False, False);
155 WMDestroyAlertPanel(panel);
157 XDestroyWindow(dpy, parent);
159 return result;
162 typedef struct _WMInputPanelWithHistory {
163 WMInputPanel *panel;
164 WMArray *history;
165 int histpos;
166 char *prefix;
167 char *suffix;
168 char *rest;
169 WMArray *variants;
170 int varpos;
171 } WMInputPanelWithHistory;
173 static char *HistoryFileName(const char *name)
175 char *filename = NULL;
177 filename = wstrdup(wusergnusteppath());
178 filename = wstrappend(filename, "/.AppInfo/WindowMaker/History");
179 if (name && strlen(name)) {
180 filename = wstrappend(filename, ".");
181 filename = wstrappend(filename, name);
183 return filename;
186 static int strmatch(const void *str1, const void *str2)
188 return !strcmp((const char *)str1, (const char *)str2);
191 static WMArray *LoadHistory(const char *filename, int max)
193 WMPropList *plhistory;
194 WMPropList *plitem;
195 WMArray *history;
196 int i, num;
197 char *str;
199 history = WMCreateArrayWithDestructor(1, wfree);
200 WMAddToArray(history, wstrdup(""));
202 plhistory = WMReadPropListFromFile(filename);
204 if (plhistory) {
205 if (WMIsPLArray(plhistory)) {
206 num = WMGetPropListItemCount(plhistory);
208 for (i = 0; i < num; ++i) {
209 plitem = WMGetFromPLArray(plhistory, i);
210 if (WMIsPLString(plitem)) {
211 str = WMGetFromPLString(plitem);
212 if (WMFindInArray(history, strmatch, str) == WANotFound) {
214 * The string here is duplicated because it will be freed
215 * automatically when the array is deleted. This is not really
216 * great because it is already an allocated string,
217 * unfortunately we cannot re-use it because it will be freed
218 * when we discard the PL (and we don't want to waste the PL's
219 * memory either)
221 WMAddToArray(history, wstrdup(str));
222 if (--max <= 0)
223 break;
228 WMReleasePropList(plhistory);
231 return history;
234 static void SaveHistory(WMArray * history, const char *filename)
236 int i;
237 WMPropList *plhistory;
239 plhistory = WMCreatePLArray(NULL);
241 for (i = 0; i < WMGetArrayItemCount(history); ++i)
242 WMAddToPLArray(plhistory, WMCreatePLString(WMGetFromArray(history, i)));
244 WMWritePropListToFile(plhistory, filename);
245 WMReleasePropList(plhistory);
248 static int pstrcmp(const char **str1, const char **str2)
250 return strcmp(*str1, *str2);
253 static void
254 ScanFiles(const char *dir, const char *prefix, unsigned acceptmask, unsigned declinemask, WMArray * result)
256 int prefixlen;
257 DIR *d;
258 struct dirent *de;
259 struct stat sb;
260 char *fullfilename, *suffix;
262 prefixlen = strlen(prefix);
263 if ((d = opendir(dir)) != NULL) {
264 while ((de = readdir(d)) != NULL) {
265 if (strlen(de->d_name) > prefixlen &&
266 !strncmp(prefix, de->d_name, prefixlen) &&
267 strcmp(de->d_name, ".") != 0 && strcmp(de->d_name, "..")) {
268 fullfilename = wstrconcat((char *)dir, "/");
269 fullfilename = wstrappend(fullfilename, de->d_name);
271 if (stat(fullfilename, &sb) == 0 &&
272 (sb.st_mode & acceptmask) &&
273 !(sb.st_mode & declinemask) &&
274 WMFindInArray(result, (WMMatchDataProc *) strmatch,
275 de->d_name + prefixlen) == WANotFound) {
276 suffix = wstrdup(de->d_name + prefixlen);
277 if (sb.st_mode & S_IFDIR)
278 suffix = wstrappend(suffix, "/");
279 WMAddToArray(result, suffix);
281 wfree(fullfilename);
284 closedir(d);
288 static WMArray *GenerateVariants(const char *complete)
290 Bool firstWord = True;
291 WMArray *variants = NULL;
292 char *pos = NULL, *path = NULL, *tmp = NULL, *dir = NULL, *prefix = NULL;
294 variants = WMCreateArrayWithDestructor(0, wfree);
296 while (*complete == ' ')
297 ++complete;
299 if ((pos = strrchr(complete, ' ')) != NULL) {
300 complete = pos + 1;
301 firstWord = False;
304 if ((pos = strrchr(complete, '/')) != NULL) {
305 tmp = wstrndup((char *)complete, pos - complete + 1);
306 if (*tmp == '~' && *(tmp + 1) == '/' && getenv("HOME")) {
307 dir = wstrdup(getenv("HOME"));
308 dir = wstrappend(dir, tmp + 1);
309 wfree(tmp);
310 } else {
311 dir = tmp;
313 prefix = wstrdup(pos + 1);
314 ScanFiles(dir, prefix, (unsigned)-1, 0, variants);
315 wfree(dir);
316 wfree(prefix);
317 } else if (*complete == '~') {
318 WMAddToArray(variants, wstrdup("/"));
319 } else if (firstWord) {
320 path = getenv("PATH");
321 while (path) {
322 pos = strchr(path, ':');
323 if (pos) {
324 tmp = wstrndup(path, pos - path);
325 path = pos + 1;
326 } else if (*path != '\0') {
327 tmp = wstrdup(path);
328 path = NULL;
329 } else
330 break;
331 ScanFiles(tmp, complete, S_IXOTH | S_IXGRP | S_IXUSR, S_IFDIR, variants);
332 wfree(tmp);
336 WMSortArray(variants, (WMCompareDataProc *) pstrcmp);
337 return variants;
340 static void handleHistoryKeyPress(XEvent * event, void *clientData)
342 char *text;
343 unsigned pos;
344 WMInputPanelWithHistory *p = (WMInputPanelWithHistory *) clientData;
345 KeySym ksym;
347 ksym = XLookupKeysym(&event->xkey, 0);
349 switch (ksym) {
350 case XK_Up:
351 if (p->histpos < WMGetArrayItemCount(p->history) - 1) {
352 if (p->histpos == 0)
353 wfree(WMReplaceInArray(p->history, 0, WMGetTextFieldText(p->panel->text)));
354 p->histpos++;
355 WMSetTextFieldText(p->panel->text, WMGetFromArray(p->history, p->histpos));
357 break;
358 case XK_Down:
359 if (p->histpos > 0) {
360 p->histpos--;
361 WMSetTextFieldText(p->panel->text, WMGetFromArray(p->history, p->histpos));
363 break;
364 case XK_Tab:
365 if (!p->variants) {
366 text = WMGetTextFieldText(p->panel->text);
367 pos = WMGetTextFieldCursorPosition(p->panel->text);
368 p->prefix = wstrndup(text, pos);
369 p->suffix = wstrdup(text + pos);
370 wfree(text);
371 p->variants = GenerateVariants(p->prefix);
372 p->varpos = 0;
373 if (!p->variants) {
374 wfree(p->prefix);
375 wfree(p->suffix);
376 p->prefix = NULL;
377 p->suffix = NULL;
380 if (p->variants && p->prefix && p->suffix) {
381 p->varpos++;
382 if (p->varpos > WMGetArrayItemCount(p->variants))
383 p->varpos = 0;
384 if (p->varpos > 0)
385 text = wstrconcat(p->prefix, WMGetFromArray(p->variants, p->varpos - 1));
386 else
387 text = wstrdup(p->prefix);
388 pos = strlen(text);
389 text = wstrappend(text, p->suffix);
390 WMSetTextFieldText(p->panel->text, text);
391 WMSetTextFieldCursorPosition(p->panel->text, pos);
392 wfree(text);
394 break;
396 if (ksym != XK_Tab) {
397 if (p->prefix) {
398 wfree(p->prefix);
399 p->prefix = NULL;
401 if (p->suffix) {
402 wfree(p->suffix);
403 p->suffix = NULL;
405 if (p->variants) {
406 WMFreeArray(p->variants);
407 p->variants = NULL;
412 int wAdvancedInputDialog(WScreen *scr, const char *title, const char *message, const char *name, char **text)
414 WWindow *wwin;
415 Window parent;
416 char *result;
417 WMPoint center;
418 WMInputPanelWithHistory *p;
419 char *filename;
421 filename = HistoryFileName(name);
422 p = wmalloc(sizeof(WMInputPanelWithHistory));
423 p->panel = WMCreateInputPanel(scr->wmscreen, NULL, title, message, *text, _("OK"), _("Cancel"));
424 p->history = LoadHistory(filename, wPreferences.history_lines);
425 p->histpos = 0;
426 p->prefix = NULL;
427 p->suffix = NULL;
428 p->rest = NULL;
429 p->variants = NULL;
430 p->varpos = 0;
431 WMCreateEventHandler(WMWidgetView(p->panel->text), KeyPressMask, handleHistoryKeyPress, p);
433 parent = XCreateSimpleWindow(dpy, scr->root_win, 0, 0, 320, 160, 0, 0, 0);
434 XSelectInput(dpy, parent, KeyPressMask | KeyReleaseMask);
436 XReparentWindow(dpy, WMWidgetXID(p->panel->win), parent, 0, 0);
438 center = getCenter(scr, 320, 160);
439 wwin = wManageInternalWindow(scr, parent, None, NULL, center.x, center.y, 320, 160);
441 wwin->client_leader = WMWidgetXID(p->panel->win);
443 WMMapWidget(p->panel->win);
445 wWindowMap(wwin);
447 WMRunModalLoop(WMWidgetScreen(p->panel->win), WMWidgetView(p->panel->win));
449 if (p->panel->result == WAPRDefault) {
450 result = WMGetTextFieldText(p->panel->text);
451 wfree(WMReplaceInArray(p->history, 0, wstrdup(result)));
452 SaveHistory(p->history, filename);
453 } else
454 result = NULL;
456 wUnmanageWindow(wwin, False, False);
458 WMDestroyInputPanel(p->panel);
459 WMFreeArray(p->history);
460 wfree(p);
461 wfree(filename);
463 XDestroyWindow(dpy, parent);
465 if (result == NULL)
466 return False;
467 else {
468 if (*text)
469 wfree(*text);
470 *text = result;
472 return True;
476 int wInputDialog(WScreen *scr, const char *title, const char *message, char **text)
478 WWindow *wwin;
479 Window parent;
480 WMInputPanel *panel;
481 char *result;
482 WMPoint center;
484 panel = WMCreateInputPanel(scr->wmscreen, NULL, title, message, *text, _("OK"), _("Cancel"));
486 parent = XCreateSimpleWindow(dpy, scr->root_win, 0, 0, 320, 160, 0, 0, 0);
487 XSelectInput(dpy, parent, KeyPressMask | KeyReleaseMask);
489 XReparentWindow(dpy, WMWidgetXID(panel->win), parent, 0, 0);
491 center = getCenter(scr, 320, 160);
492 wwin = wManageInternalWindow(scr, parent, None, NULL, center.x, center.y, 320, 160);
494 wwin->client_leader = WMWidgetXID(panel->win);
496 WMMapWidget(panel->win);
498 wWindowMap(wwin);
500 WMRunModalLoop(WMWidgetScreen(panel->win), WMWidgetView(panel->win));
502 if (panel->result == WAPRDefault)
503 result = WMGetTextFieldText(panel->text);
504 else
505 result = NULL;
507 wUnmanageWindow(wwin, False, False);
509 WMDestroyInputPanel(panel);
511 XDestroyWindow(dpy, parent);
513 if (result == NULL)
514 return False;
515 else {
516 if (*text)
517 wfree(*text);
518 *text = result;
520 return True;
525 *****************************************************************
526 * Icon Selection Panel
527 *****************************************************************
530 typedef struct IconPanel {
532 WScreen *scr;
534 WMWindow *win;
536 WMLabel *dirLabel;
537 WMLabel *iconLabel;
539 WMList *dirList;
540 WMList *iconList;
541 WMFont *normalfont;
543 WMButton *previewButton;
545 WMLabel *iconView;
547 WMLabel *fileLabel;
548 WMTextField *fileField;
550 WMButton *okButton;
551 WMButton *cancelButton;
552 #if 0
553 WMButton *chooseButton;
554 #endif
555 short done;
556 short result;
557 short preview;
558 } IconPanel;
560 static void listPixmaps(WScreen *scr, WMList *lPtr, const char *path)
562 struct dirent *dentry;
563 DIR *dir;
564 char pbuf[PATH_MAX + 16];
565 char *apath;
566 IconPanel *panel = WMGetHangedData(lPtr);
568 panel->preview = False;
570 apath = wexpandpath(path);
571 dir = opendir(apath);
573 if (!dir) {
574 char *msg;
575 char *tmp;
576 tmp = _("Could not open directory ");
577 msg = wmalloc(strlen(tmp) + strlen(path) + 6);
578 strcpy(msg, tmp);
579 strcat(msg, path);
581 wMessageDialog(scr, _("Error"), msg, _("OK"), NULL, NULL);
582 wfree(msg);
583 wfree(apath);
584 return;
587 /* list contents in the column */
588 while ((dentry = readdir(dir))) {
589 struct stat statb;
591 if (strcmp(dentry->d_name, ".") == 0 || strcmp(dentry->d_name, "..") == 0)
592 continue;
594 strcpy(pbuf, apath);
595 strcat(pbuf, "/");
596 strcat(pbuf, dentry->d_name);
598 if (stat(pbuf, &statb) < 0)
599 continue;
601 if (statb.st_mode & (S_IRUSR | S_IRGRP | S_IROTH)
602 && statb.st_mode & (S_IFREG | S_IFLNK)) {
603 WMAddListItem(lPtr, dentry->d_name);
606 WMSortListItems(lPtr);
608 closedir(dir);
609 wfree(apath);
610 panel->preview = True;
613 static void setViewedImage(IconPanel *panel, const char *file)
615 WMPixmap *pixmap;
616 RColor color;
618 color.red = 0xae;
619 color.green = 0xaa;
620 color.blue = 0xae;
621 color.alpha = 0;
622 pixmap = WMCreateScaledBlendedPixmapFromFile(WMWidgetScreen(panel->win), file, &color, 75, 75);
624 if (!pixmap) {
625 WMSetButtonEnabled(panel->okButton, False);
627 WMSetLabelText(panel->iconView, _("Could not load image file "));
629 WMSetLabelImage(panel->iconView, NULL);
630 } else {
631 WMSetButtonEnabled(panel->okButton, True);
633 WMSetLabelText(panel->iconView, NULL);
634 WMSetLabelImage(panel->iconView, pixmap);
635 WMReleasePixmap(pixmap);
639 static void listCallback(void *self, void *data)
641 WMList *lPtr = (WMList *) self;
642 IconPanel *panel = (IconPanel *) data;
643 char *path;
645 if (lPtr == panel->dirList) {
646 WMListItem *item = WMGetListSelectedItem(lPtr);
648 if (item == NULL)
649 return;
650 path = item->text;
652 WMSetTextFieldText(panel->fileField, path);
654 WMSetLabelImage(panel->iconView, NULL);
656 WMSetButtonEnabled(panel->okButton, False);
658 WMClearList(panel->iconList);
659 listPixmaps(panel->scr, panel->iconList, path);
660 } else {
661 char *tmp, *iconFile;
662 WMListItem *item = WMGetListSelectedItem(panel->dirList);
664 if (item == NULL)
665 return;
666 path = item->text;
668 item = WMGetListSelectedItem(panel->iconList);
669 if (item == NULL)
670 return;
671 iconFile = item->text;
673 tmp = wexpandpath(path);
674 path = wmalloc(strlen(tmp) + strlen(iconFile) + 4);
675 strcpy(path, tmp);
676 strcat(path, "/");
677 strcat(path, iconFile);
678 wfree(tmp);
679 WMSetTextFieldText(panel->fileField, path);
680 setViewedImage(panel, path);
681 wfree(path);
685 static void listIconPaths(WMList * lPtr)
687 char *paths;
688 char *path;
690 paths = wstrdup(wPreferences.icon_path);
692 path = strtok(paths, ":");
694 do {
695 char *tmp;
697 tmp = wexpandpath(path);
698 /* do not sort, because the order implies the order of
699 * directories searched */
700 if (access(tmp, X_OK) == 0)
701 WMAddListItem(lPtr, path);
702 wfree(tmp);
703 } while ((path = strtok(NULL, ":")) != NULL);
705 wfree(paths);
708 static void drawIconProc(WMList * lPtr, int index, Drawable d, char *text, int state, WMRect * rect)
710 IconPanel *panel = WMGetHangedData(lPtr);
711 WScreen *scr = panel->scr;
712 GC gc = scr->draw_gc;
713 GC copygc = scr->copy_gc;
714 char *file, *dirfile;
715 WMPixmap *pixmap;
716 WMColor *back;
717 WMSize size;
718 WMScreen *wmscr = WMWidgetScreen(panel->win);
719 RColor color;
720 int x, y, width, height, len;
722 /* Parameter not used, but tell the compiler that it is ok */
723 (void) index;
725 if (!panel->preview)
726 return;
728 x = rect->pos.x;
729 y = rect->pos.y;
730 width = rect->size.width;
731 height = rect->size.height;
733 back = (state & WLDSSelected) ? scr->white : scr->gray;
735 dirfile = wexpandpath(WMGetListSelectedItem(panel->dirList)->text);
736 len = strlen(dirfile) + strlen(text) + 4;
737 file = wmalloc(len);
738 snprintf(file, len, "%s/%s", dirfile, text);
739 wfree(dirfile);
741 color.red = WMRedComponentOfColor(back) >> 8;
742 color.green = WMGreenComponentOfColor(back) >> 8;
743 color.blue = WMBlueComponentOfColor(back) >> 8;
744 color.alpha = WMGetColorAlpha(back) >> 8;
746 pixmap = WMCreateScaledBlendedPixmapFromFile(wmscr, file, &color, width - 2, height - 2);
747 wfree(file);
749 if (!pixmap) {
750 /*WMRemoveListItem(lPtr, index); */
751 return;
754 XFillRectangle(dpy, d, WMColorGC(back), x, y, width, height);
756 XSetClipMask(dpy, gc, None);
757 /*XDrawRectangle(dpy, d, WMColorGC(white), x+5, y+5, width-10, 54); */
758 XDrawLine(dpy, d, WMColorGC(scr->white), x, y + height - 1, x + width, y + height - 1);
760 size = WMGetPixmapSize(pixmap);
762 XSetClipMask(dpy, copygc, WMGetPixmapMaskXID(pixmap));
763 XSetClipOrigin(dpy, copygc, x + (width - size.width) / 2, y + 2);
764 XCopyArea(dpy, WMGetPixmapXID(pixmap), d, copygc, 0, 0,
765 size.width > 100 ? 100 : size.width, size.height > 64 ? 64 : size.height,
766 x + (width - size.width) / 2, y + 2);
769 int i, j;
770 int fheight = WMFontHeight(panel->normalfont);
771 int tlen = strlen(text);
772 int twidth = WMWidthOfString(panel->normalfont, text, tlen);
773 int ofx, ofy;
775 ofx = x + (width - twidth) / 2;
776 ofy = y + 64 - fheight;
778 for (i = -1; i < 2; i++)
779 for (j = -1; j < 2; j++)
780 WMDrawString(wmscr, d, scr->white, panel->normalfont,
781 ofx + i, ofy + j, text, tlen);
783 WMDrawString(wmscr, d, scr->black, panel->normalfont, ofx, ofy, text, tlen);
786 WMReleasePixmap(pixmap);
787 /* I hope it is better to do not use cache / on my box it is fast nuff */
788 XFlush(dpy);
791 static void buttonCallback(void *self, void *clientData)
793 WMButton *bPtr = (WMButton *) self;
794 IconPanel *panel = (IconPanel *) clientData;
796 if (bPtr == panel->okButton) {
797 panel->done = True;
798 panel->result = True;
799 } else if (bPtr == panel->cancelButton) {
800 panel->done = True;
801 panel->result = False;
802 } else if (bPtr == panel->previewButton) {
803 /**** Previewer ****/
804 WMSetButtonEnabled(bPtr, False);
805 WMSetListUserDrawItemHeight(panel->iconList, 68);
806 WMSetListUserDrawProc(panel->iconList, drawIconProc);
807 WMRedisplayWidget(panel->iconList);
808 /* for draw proc to access screen/gc */
809 /*** end preview ***/
811 #if 0
812 else if (bPtr == panel->chooseButton) {
813 WMOpenPanel *op;
815 op = WMCreateOpenPanel(WMWidgetScreen(bPtr));
817 if (WMRunModalFilePanelForDirectory(op, NULL, "/usr/local", NULL, NULL)) {
818 char *path;
819 path = WMGetFilePanelFile(op);
820 WMSetTextFieldText(panel->fileField, path);
821 setViewedImage(panel, path);
822 wfree(path);
824 WMDestroyFilePanel(op);
826 #endif
829 static void keyPressHandler(XEvent * event, void *data)
831 IconPanel *panel = (IconPanel *) data;
832 char buffer[32];
833 KeySym ksym;
834 int iidx;
835 int didx;
836 int item = 0;
837 WMList *list = NULL;
839 if (event->type == KeyRelease)
840 return;
842 buffer[0] = 0;
843 XLookupString(&event->xkey, buffer, sizeof(buffer), &ksym, NULL);
845 iidx = WMGetListSelectedItemRow(panel->iconList);
846 didx = WMGetListSelectedItemRow(panel->dirList);
848 switch (ksym) {
849 case XK_Up:
850 if (iidx > 0)
851 item = iidx - 1;
852 else
853 item = iidx;
854 list = panel->iconList;
855 break;
856 case XK_Down:
857 if (iidx < WMGetListNumberOfRows(panel->iconList) - 1)
858 item = iidx + 1;
859 else
860 item = iidx;
861 list = panel->iconList;
862 break;
863 case XK_Home:
864 item = 0;
865 list = panel->iconList;
866 break;
867 case XK_End:
868 item = WMGetListNumberOfRows(panel->iconList) - 1;
869 list = panel->iconList;
870 break;
871 case XK_Next:
872 if (didx < WMGetListNumberOfRows(panel->dirList) - 1)
873 item = didx + 1;
874 else
875 item = didx;
876 list = panel->dirList;
877 break;
878 case XK_Prior:
879 if (didx > 0)
880 item = didx - 1;
881 else
882 item = 0;
883 list = panel->dirList;
884 break;
885 case XK_Return:
886 WMPerformButtonClick(panel->okButton);
887 break;
888 case XK_Escape:
889 WMPerformButtonClick(panel->cancelButton);
890 break;
893 if (list) {
894 WMSelectListItem(list, item);
895 WMSetListPosition(list, item - 5);
896 listCallback(list, panel);
900 Bool wIconChooserDialog(WScreen *scr, char **file, const char *instance, const char *class)
902 WWindow *wwin;
903 Window parent;
904 IconPanel *panel;
905 WMColor *color;
906 WMFont *boldFont;
907 Bool result;
909 panel = wmalloc(sizeof(IconPanel));
911 panel->scr = scr;
913 panel->win = WMCreateWindow(scr->wmscreen, "iconChooser");
914 WMResizeWidget(panel->win, 450, 280);
916 WMCreateEventHandler(WMWidgetView(panel->win), KeyPressMask | KeyReleaseMask, keyPressHandler, panel);
918 boldFont = WMBoldSystemFontOfSize(scr->wmscreen, 12);
919 panel->normalfont = WMSystemFontOfSize(WMWidgetScreen(panel->win), 12);
921 panel->dirLabel = WMCreateLabel(panel->win);
922 WMResizeWidget(panel->dirLabel, 200, 20);
923 WMMoveWidget(panel->dirLabel, 10, 7);
924 WMSetLabelText(panel->dirLabel, _("Directories"));
925 WMSetLabelFont(panel->dirLabel, boldFont);
926 WMSetLabelTextAlignment(panel->dirLabel, WACenter);
928 WMSetLabelRelief(panel->dirLabel, WRSunken);
930 panel->iconLabel = WMCreateLabel(panel->win);
931 WMResizeWidget(panel->iconLabel, 140, 20);
932 WMMoveWidget(panel->iconLabel, 215, 7);
933 WMSetLabelText(panel->iconLabel, _("Icons"));
934 WMSetLabelFont(panel->iconLabel, boldFont);
935 WMSetLabelTextAlignment(panel->iconLabel, WACenter);
937 WMReleaseFont(boldFont);
939 color = WMWhiteColor(scr->wmscreen);
940 WMSetLabelTextColor(panel->dirLabel, color);
941 WMSetLabelTextColor(panel->iconLabel, color);
942 WMReleaseColor(color);
944 color = WMDarkGrayColor(scr->wmscreen);
945 WMSetWidgetBackgroundColor(panel->iconLabel, color);
946 WMSetWidgetBackgroundColor(panel->dirLabel, color);
947 WMReleaseColor(color);
949 WMSetLabelRelief(panel->iconLabel, WRSunken);
951 panel->dirList = WMCreateList(panel->win);
952 WMResizeWidget(panel->dirList, 200, 170);
953 WMMoveWidget(panel->dirList, 10, 30);
954 WMSetListAction(panel->dirList, listCallback, panel);
956 panel->iconList = WMCreateList(panel->win);
957 WMResizeWidget(panel->iconList, 140, 170);
958 WMMoveWidget(panel->iconList, 215, 30);
959 WMSetListAction(panel->iconList, listCallback, panel);
961 WMHangData(panel->iconList, panel);
963 panel->previewButton = WMCreateCommandButton(panel->win);
964 WMResizeWidget(panel->previewButton, 75, 26);
965 WMMoveWidget(panel->previewButton, 365, 130);
966 WMSetButtonText(panel->previewButton, _("Preview"));
967 WMSetButtonAction(panel->previewButton, buttonCallback, panel);
969 panel->iconView = WMCreateLabel(panel->win);
970 WMResizeWidget(panel->iconView, 75, 75);
971 WMMoveWidget(panel->iconView, 365, 40);
972 WMSetLabelImagePosition(panel->iconView, WIPOverlaps);
973 WMSetLabelRelief(panel->iconView, WRSunken);
974 WMSetLabelTextAlignment(panel->iconView, WACenter);
976 panel->fileLabel = WMCreateLabel(panel->win);
977 WMResizeWidget(panel->fileLabel, 80, 20);
978 WMMoveWidget(panel->fileLabel, 10, 210);
979 WMSetLabelText(panel->fileLabel, _("File Name:"));
981 panel->fileField = WMCreateTextField(panel->win);
982 WMSetViewNextResponder(WMWidgetView(panel->fileField), WMWidgetView(panel->win));
983 WMResizeWidget(panel->fileField, 345, 20);
984 WMMoveWidget(panel->fileField, 95, 210);
985 WMSetTextFieldEditable(panel->fileField, False);
987 panel->okButton = WMCreateCommandButton(panel->win);
988 WMResizeWidget(panel->okButton, 80, 26);
989 WMMoveWidget(panel->okButton, 360, 240);
990 WMSetButtonText(panel->okButton, _("OK"));
991 WMSetButtonEnabled(panel->okButton, False);
992 WMSetButtonAction(panel->okButton, buttonCallback, panel);
994 panel->cancelButton = WMCreateCommandButton(panel->win);
995 WMResizeWidget(panel->cancelButton, 80, 26);
996 WMMoveWidget(panel->cancelButton, 270, 240);
997 WMSetButtonText(panel->cancelButton, _("Cancel"));
998 WMSetButtonAction(panel->cancelButton, buttonCallback, panel);
999 #if 0
1000 panel->chooseButton = WMCreateCommandButton(panel->win);
1001 WMResizeWidget(panel->chooseButton, 110, 26);
1002 WMMoveWidget(panel->chooseButton, 150, 240);
1003 WMSetButtonText(panel->chooseButton, _("Choose File"));
1004 WMSetButtonAction(panel->chooseButton, buttonCallback, panel);
1005 #endif
1006 WMRealizeWidget(panel->win);
1007 WMMapSubwidgets(panel->win);
1009 parent = XCreateSimpleWindow(dpy, scr->root_win, 0, 0, 450, 280, 0, 0, 0);
1011 XReparentWindow(dpy, WMWidgetXID(panel->win), parent, 0, 0);
1014 static const char *prefix = NULL;
1015 char *title;
1016 int len;
1017 WMPoint center;
1019 if (prefix == NULL)
1020 prefix = _("Icon Chooser");
1022 len = strlen(prefix)
1023 + 2 // " ["
1024 + (instance ? strlen(instance) : 0)
1025 + 1 // "."
1026 + (class ? strlen(class) : 0)
1027 + 1 // "]"
1028 + 1; // final NUL
1030 title = wmalloc(len);
1031 strcpy(title, prefix);
1033 if (instance || class) {
1034 strcat(title, " [");
1035 if (instance != NULL)
1036 strcat(title, instance);
1037 if (instance && class)
1038 strcat(title, ".");
1039 if (class != NULL)
1040 strcat(title, class);
1041 strcat(title, "]");
1044 center = getCenter(scr, 450, 280);
1046 wwin = wManageInternalWindow(scr, parent, None, title, center.x, center.y, 450, 280);
1047 wfree(title);
1050 /* put icon paths in the list */
1051 listIconPaths(panel->dirList);
1053 WMMapWidget(panel->win);
1055 wWindowMap(wwin);
1057 while (!panel->done) {
1058 XEvent event;
1060 WMNextEvent(dpy, &event);
1061 WMHandleEvent(&event);
1064 if (panel->result) {
1065 char *defaultPath, *wantedPath;
1067 /* check if the file the user selected is not the one that
1068 * would be loaded by default with the current search path */
1069 *file = WMGetListSelectedItem(panel->iconList)->text;
1070 if (**file == 0) {
1071 wfree(*file);
1072 *file = NULL;
1073 } else {
1074 defaultPath = FindImage(wPreferences.icon_path, *file);
1075 wantedPath = WMGetTextFieldText(panel->fileField);
1076 /* if the file is not the default, use full path */
1077 if (strcmp(wantedPath, defaultPath) != 0) {
1078 *file = wantedPath;
1079 } else {
1080 *file = wstrdup(*file);
1081 wfree(wantedPath);
1083 wfree(defaultPath);
1085 } else {
1086 *file = NULL;
1089 result = panel->result;
1091 WMReleaseFont(panel->normalfont);
1093 WMUnmapWidget(panel->win);
1095 WMDestroyWidget(panel->win);
1097 wUnmanageWindow(wwin, False, False);
1099 wfree(panel);
1101 XDestroyWindow(dpy, parent);
1103 return result;
1107 ***********************************************************************
1108 * Info Panel
1109 ***********************************************************************
1112 typedef struct {
1113 WScreen *scr;
1114 WWindow *wwin;
1115 WMWindow *win;
1116 WMLabel *logoL;
1117 WMLabel *name1L;
1118 WMFrame *lineF;
1119 WMLabel *name2L;
1120 WMLabel *versionL;
1121 WMLabel *infoL;
1122 WMLabel *copyrL;
1123 } InfoPanel;
1125 #define COPYRIGHT_TEXT \
1126 "Copyright \xc2\xa9 1997-2006 Alfredo K. Kojima\n"\
1127 "Copyright \xc2\xa9 1998-2006 Dan Pascu\n"\
1128 "Copyright \xc2\xa9 2013-2014 Window Maker Developers Team"
1130 static InfoPanel *thePanel = NULL;
1132 static void destroyInfoPanel(WCoreWindow *foo, void *data, XEvent *event)
1134 /* Parameter not used, but tell the compiler that it is ok */
1135 (void) foo;
1136 (void) data;
1137 (void) event;
1139 WMUnmapWidget(thePanel);
1140 wUnmanageWindow(thePanel->wwin, False, False);
1141 WMDestroyWidget(thePanel->win);
1142 wfree(thePanel);
1143 thePanel = NULL;
1146 void wShowInfoPanel(WScreen *scr)
1148 const int win_width = 382;
1149 const int win_height = 250;
1150 InfoPanel *panel;
1151 WMPixmap *logo;
1152 WMFont *font;
1153 char *name, *strbuf = NULL;
1154 const char *separator;
1155 char buffer[256];
1156 Window parent;
1157 WWindow *wwin;
1158 WMPoint center;
1159 char **strl;
1160 int i, width = 50, sepHeight;
1161 char *visuals[] = {
1162 "StaticGray",
1163 "GrayScale",
1164 "StaticColor",
1165 "PseudoColor",
1166 "TrueColor",
1167 "DirectColor"
1170 if (thePanel) {
1171 if (thePanel->scr == scr) {
1172 wRaiseFrame(thePanel->wwin->frame->core);
1173 wSetFocusTo(scr, thePanel->wwin);
1175 return;
1178 panel = wmalloc(sizeof(InfoPanel));
1180 panel->scr = scr;
1182 panel->win = WMCreateWindow(scr->wmscreen, "info");
1183 WMResizeWidget(panel->win, win_width, win_height);
1185 logo = WMCreateApplicationIconBlendedPixmap(scr->wmscreen, (RColor *) NULL);
1186 if (!logo) {
1187 logo = WMRetainPixmap(WMGetApplicationIconPixmap(scr->wmscreen));
1189 if (logo) {
1190 panel->logoL = WMCreateLabel(panel->win);
1191 WMResizeWidget(panel->logoL, 64, 64);
1192 WMMoveWidget(panel->logoL, 30, 20);
1193 WMSetLabelImagePosition(panel->logoL, WIPImageOnly);
1194 WMSetLabelImage(panel->logoL, logo);
1195 WMReleasePixmap(logo);
1198 sepHeight = 3;
1199 panel->name1L = WMCreateLabel(panel->win);
1200 WMResizeWidget(panel->name1L, 240, 30 + 2);
1201 WMMoveWidget(panel->name1L, 100, 30 - 2 - sepHeight);
1203 name = "Lucida Sans,Comic Sans MS,URW Gothic L,Trebuchet MS" ":italic:pixelsize=28:antialias=true";
1204 font = WMCreateFont(scr->wmscreen, name);
1205 strbuf = "Window Maker";
1206 if (font) {
1207 width = WMWidthOfString(font, strbuf, strlen(strbuf));
1208 WMSetLabelFont(panel->name1L, font);
1209 WMReleaseFont(font);
1211 WMSetLabelTextAlignment(panel->name1L, WACenter);
1212 WMSetLabelText(panel->name1L, strbuf);
1214 panel->lineF = WMCreateFrame(panel->win);
1215 WMResizeWidget(panel->lineF, width, sepHeight);
1216 WMMoveWidget(panel->lineF, 100 + (240 - width) / 2, 60 - sepHeight);
1217 WMSetFrameRelief(panel->lineF, WRSimple);
1218 WMSetWidgetBackgroundColor(panel->lineF, scr->black);
1220 panel->name2L = WMCreateLabel(panel->win);
1221 WMResizeWidget(panel->name2L, 240, 24);
1222 WMMoveWidget(panel->name2L, 100, 60);
1223 name = "URW Gothic L,Nimbus Sans L:pixelsize=16:antialias=true";
1224 font = WMCreateFont(scr->wmscreen, name);
1225 if (font) {
1226 WMSetLabelFont(panel->name2L, font);
1227 WMReleaseFont(font);
1228 font = NULL;
1230 WMSetLabelTextAlignment(panel->name2L, WACenter);
1231 WMSetLabelText(panel->name2L, _("Window Manager for X"));
1233 snprintf(buffer, sizeof(buffer), _("Version %s"), VERSION);
1234 panel->versionL = WMCreateLabel(panel->win);
1235 WMResizeWidget(panel->versionL, 310, 16);
1236 WMMoveWidget(panel->versionL, 30, 95);
1237 WMSetLabelTextAlignment(panel->versionL, WARight);
1238 WMSetLabelText(panel->versionL, buffer);
1239 WMSetLabelWraps(panel->versionL, False);
1241 panel->copyrL = WMCreateLabel(panel->win);
1242 WMResizeWidget(panel->copyrL, 360, 60);
1243 WMMoveWidget(panel->copyrL, 15, 190);
1244 WMSetLabelTextAlignment(panel->copyrL, WALeft);
1245 WMSetLabelText(panel->copyrL, COPYRIGHT_TEXT);
1246 font = WMSystemFontOfSize(scr->wmscreen, 11);
1247 if (font) {
1248 WMSetLabelFont(panel->copyrL, font);
1249 WMReleaseFont(font);
1250 font = NULL;
1253 strbuf = NULL;
1254 snprintf(buffer, sizeof(buffer), _("Using visual 0x%x: %s %ibpp "),
1255 (unsigned)scr->w_visual->visualid, visuals[scr->w_visual->class], scr->w_depth);
1257 strbuf = wstrappend(strbuf, buffer);
1259 switch (scr->w_depth) {
1260 case 15:
1261 strbuf = wstrappend(strbuf, _("(32 thousand colors)\n"));
1262 break;
1263 case 16:
1264 strbuf = wstrappend(strbuf, _("(64 thousand colors)\n"));
1265 break;
1266 case 24:
1267 case 32:
1268 strbuf = wstrappend(strbuf, _("(16 million colors)\n"));
1269 break;
1270 default:
1271 snprintf(buffer, sizeof(buffer), _("(%d colors)\n"), 1 << scr->w_depth);
1272 strbuf = wstrappend(strbuf, buffer);
1273 break;
1276 #if defined(HAVE_MALLOC_H) && defined(HAVE_MALLINFO)
1278 struct mallinfo ma = mallinfo();
1279 snprintf(buffer, sizeof(buffer),
1280 #ifdef DEBUG
1281 _("Total memory allocated: %i kB (in use: %i kB, %d free chunks).\n"),
1282 #else
1283 _("Total memory allocated: %i kB (in use: %i kB).\n"),
1284 #endif
1285 (ma.arena + ma.hblkhd) / 1024,
1286 (ma.uordblks + ma.hblkhd) / 1024
1287 #ifdef DEBUG
1289 * This information is representative of the memory
1290 * fragmentation. In ideal case it should be 1, but
1291 * that is never possible
1293 , ma.ordblks
1294 #endif
1297 strbuf = wstrappend(strbuf, buffer);
1299 #endif
1301 strbuf = wstrappend(strbuf, _("Image formats: "));
1302 strl = RSupportedFileFormats();
1303 separator = NULL;
1304 for (i = 0; strl[i] != NULL; i++) {
1305 if (separator != NULL)
1306 strbuf = wstrappend(strbuf, separator);
1307 strbuf = wstrappend(strbuf, strl[i]);
1308 separator = ", ";
1311 strbuf = wstrappend(strbuf, _("\nAdditional support for: "));
1312 strbuf = wstrappend(strbuf, "WMSPEC");
1314 #ifdef MWM_HINTS
1315 strbuf = wstrappend(strbuf, ", MWM");
1316 #endif
1318 #ifdef USE_MAGICK
1319 strbuf = wstrappend(strbuf, ", ImageMagick");
1320 #endif
1322 #ifdef USE_XINERAMA
1323 strbuf = wstrappend(strbuf, _("\n"));
1324 #ifdef SOLARIS_XINERAMA
1325 strbuf = wstrappend(strbuf, _("Solaris "));
1326 #endif
1327 strbuf = wstrappend(strbuf, _("Xinerama: "));
1329 char tmp[128];
1330 snprintf(tmp, sizeof(tmp) - 1, _("%d head(s) found."), scr->xine_info.count);
1331 strbuf = wstrappend(strbuf, tmp);
1333 #endif
1335 #ifdef USE_RANDR
1336 strbuf = wstrappend(strbuf, _("\n"));
1337 strbuf = wstrappend(strbuf, "RandR: ");
1338 if (w_global.xext.randr.supported)
1339 strbuf = wstrappend(strbuf, _("supported"));
1340 else
1341 strbuf = wstrappend(strbuf, _("unsupported"));
1342 strbuf = wstrappend(strbuf, ".");
1343 #endif
1345 panel->infoL = WMCreateLabel(panel->win);
1346 WMResizeWidget(panel->infoL, 350, 80);
1347 WMMoveWidget(panel->infoL, 15, 115);
1348 WMSetLabelText(panel->infoL, strbuf);
1349 font = WMSystemFontOfSize(scr->wmscreen, 11);
1350 if (font) {
1351 WMSetLabelFont(panel->infoL, font);
1352 WMReleaseFont(font);
1353 font = NULL;
1355 wfree(strbuf);
1357 WMRealizeWidget(panel->win);
1358 WMMapSubwidgets(panel->win);
1360 parent = XCreateSimpleWindow(dpy, scr->root_win, 0, 0, win_width, win_height, 0, 0, 0);
1362 XReparentWindow(dpy, WMWidgetXID(panel->win), parent, 0, 0);
1364 WMMapWidget(panel->win);
1366 center = getCenter(scr, win_width, win_height);
1367 wwin = wManageInternalWindow(scr, parent, None, _("Info"), center.x, center.y, win_width, win_height);
1369 WSETUFLAG(wwin, no_closable, 0);
1370 WSETUFLAG(wwin, no_close_button, 0);
1371 #ifdef XKB_BUTTON_HINT
1372 wFrameWindowHideButton(wwin->frame, WFF_LANGUAGE_BUTTON);
1373 #endif
1374 wWindowUpdateButtonImages(wwin);
1375 wFrameWindowShowButton(wwin->frame, WFF_RIGHT_BUTTON);
1376 wwin->frame->on_click_right = destroyInfoPanel;
1378 wWindowMap(wwin);
1380 panel->wwin = wwin;
1381 thePanel = panel;
1385 ***********************************************************************
1386 * Legal Panel
1387 ***********************************************************************
1390 typedef struct {
1391 WScreen *scr;
1392 WWindow *wwin;
1393 WMWindow *win;
1394 WMLabel *licenseL;
1395 } LegalPanel;
1397 static LegalPanel *legalPanel = NULL;
1399 static void destroyLegalPanel(WCoreWindow * foo, void *data, XEvent * event)
1401 /* Parameter not used, but tell the compiler that it is ok */
1402 (void) foo;
1403 (void) data;
1404 (void) event;
1406 WMUnmapWidget(legalPanel->win);
1407 WMDestroyWidget(legalPanel->win);
1408 wUnmanageWindow(legalPanel->wwin, False, False);
1409 wfree(legalPanel);
1410 legalPanel = NULL;
1413 void wShowLegalPanel(WScreen *scr)
1415 const int win_width = 420;
1416 const int win_height = 250;
1417 const int margin = 10;
1418 LegalPanel *panel;
1419 Window parent;
1420 WWindow *wwin;
1421 WMPoint center;
1423 if (legalPanel) {
1424 if (legalPanel->scr == scr) {
1425 wRaiseFrame(legalPanel->wwin->frame->core);
1426 wSetFocusTo(scr, legalPanel->wwin);
1428 return;
1431 panel = wmalloc(sizeof(LegalPanel));
1432 panel->scr = scr;
1433 panel->win = WMCreateWindow(scr->wmscreen, "legal");
1434 WMResizeWidget(panel->win, win_width, win_height);
1436 panel->licenseL = WMCreateLabel(panel->win);
1437 WMSetLabelWraps(panel->licenseL, True);
1438 WMResizeWidget(panel->licenseL, win_width - (2 * margin), win_height - (2 * margin));
1439 WMMoveWidget(panel->licenseL, margin, margin);
1440 WMSetLabelTextAlignment(panel->licenseL, WALeft);
1441 WMSetLabelText(panel->licenseL,
1442 _(" Window Maker is free software; you can redistribute it and/or "
1443 "modify it under the terms of the GNU General Public License as "
1444 "published by the Free Software Foundation; either version 2 of the "
1445 "License, or (at your option) any later version.\n\n"
1446 " Window Maker is distributed in the hope that it will be useful, "
1447 "but WITHOUT ANY WARRANTY; without even the implied warranty "
1448 "of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. "
1449 "See the GNU General Public License for more details.\n\n"
1450 " You should have received a copy of the GNU General Public "
1451 "License along with this program; if not, write to the Free Software "
1452 "Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA"
1453 "02110-1301 USA."));
1454 WMSetLabelRelief(panel->licenseL, WRGroove);
1456 WMRealizeWidget(panel->win);
1457 WMMapSubwidgets(panel->win);
1459 parent = XCreateSimpleWindow(dpy, scr->root_win, 0, 0, win_width, win_height, 0, 0, 0);
1460 XReparentWindow(dpy, WMWidgetXID(panel->win), parent, 0, 0);
1461 center = getCenter(scr, win_width, win_height);
1462 wwin = wManageInternalWindow(scr, parent, None, _("Legal"), center.x, center.y, win_width, win_height);
1464 WSETUFLAG(wwin, no_closable, 0);
1465 WSETUFLAG(wwin, no_close_button, 0);
1466 wWindowUpdateButtonImages(wwin);
1467 wFrameWindowShowButton(wwin->frame, WFF_RIGHT_BUTTON);
1468 #ifdef XKB_BUTTON_HINT
1469 wFrameWindowHideButton(wwin->frame, WFF_LANGUAGE_BUTTON);
1470 #endif
1471 wwin->frame->on_click_right = destroyLegalPanel;
1472 panel->wwin = wwin;
1474 WMMapWidget(panel->win);
1475 wWindowMap(wwin);
1476 legalPanel = panel;
1480 ***********************************************************************
1481 * Crashing Dialog Panel
1482 ***********************************************************************
1485 typedef struct _CrashPanel {
1486 WMWindow *win; /* main window */
1488 WMLabel *iconL; /* application icon */
1489 WMLabel *nameL; /* title of panel */
1491 WMFrame *sepF; /* separator frame */
1493 WMLabel *noteL; /* Title of note */
1494 WMLabel *note2L; /* body of note with what happened */
1496 WMFrame *whatF; /* "what to do next" frame */
1497 WMPopUpButton *whatP; /* action selection popup button */
1499 WMButton *okB; /* ok button */
1501 Bool done; /* if finished with this dialog */
1502 int action; /* what to do after */
1504 KeyCode retKey;
1506 } CrashPanel;
1508 static void handleKeyPress(XEvent * event, void *clientData)
1510 CrashPanel *panel = (CrashPanel *) clientData;
1512 if (event->xkey.keycode == panel->retKey) {
1513 WMPerformButtonClick(panel->okB);
1517 static void okButtonCallback(void *self, void *clientData)
1519 CrashPanel *panel = (CrashPanel *) clientData;
1521 /* Parameter not used, but tell the compiler that it is ok */
1522 (void) self;
1524 panel->done = True;
1527 static void setCrashAction(void *self, void *clientData)
1529 WMPopUpButton *pop = (WMPopUpButton *) self;
1530 CrashPanel *panel = (CrashPanel *) clientData;
1532 panel->action = WMGetPopUpButtonSelectedItem(pop);
1535 /* Make this read the logo from a compiled in pixmap -Dan */
1536 static WMPixmap *getWindowMakerIconImage(WMScreen *scr)
1538 WMPixmap *pix = NULL;
1539 char *path = NULL;
1541 /* Get the Logo icon, without the default icon */
1542 path = get_icon_filename("Logo", "WMPanel", NULL, False);
1544 if (path) {
1545 RColor gray;
1547 gray.red = 0xae;
1548 gray.green = 0xaa;
1549 gray.blue = 0xae;
1550 gray.alpha = 0;
1552 pix = WMCreateBlendedPixmapFromFile(scr, path, &gray);
1553 wfree(path);
1556 return pix;
1559 #define PWIDTH 295
1560 #define PHEIGHT 345
1562 int wShowCrashingDialogPanel(int whatSig)
1564 CrashPanel *panel;
1565 WMScreen *scr;
1566 WMFont *font;
1567 WMPixmap *logo;
1568 int screen_no, scr_width, scr_height;
1569 int action;
1570 char buf[256];
1572 screen_no = DefaultScreen(dpy);
1573 scr_width = WidthOfScreen(ScreenOfDisplay(dpy, screen_no));
1574 scr_height = HeightOfScreen(ScreenOfDisplay(dpy, screen_no));
1576 scr = WMCreateScreen(dpy, screen_no);
1577 if (!scr) {
1578 werror(_("cannot open connection for crashing dialog panel. Aborting."));
1579 return WMAbort;
1582 panel = wmalloc(sizeof(CrashPanel));
1584 panel->retKey = XKeysymToKeycode(dpy, XK_Return);
1586 panel->win = WMCreateWindow(scr, "crashingDialog");
1587 WMResizeWidget(panel->win, PWIDTH, PHEIGHT);
1588 WMMoveWidget(panel->win, (scr_width - PWIDTH) / 2, (scr_height - PHEIGHT) / 2);
1590 logo = getWindowMakerIconImage(scr);
1591 if (logo) {
1592 panel->iconL = WMCreateLabel(panel->win);
1593 WMResizeWidget(panel->iconL, 64, 64);
1594 WMMoveWidget(panel->iconL, 10, 10);
1595 WMSetLabelImagePosition(panel->iconL, WIPImageOnly);
1596 WMSetLabelImage(panel->iconL, logo);
1599 panel->nameL = WMCreateLabel(panel->win);
1600 WMResizeWidget(panel->nameL, 200, 30);
1601 WMMoveWidget(panel->nameL, 80, 25);
1602 WMSetLabelTextAlignment(panel->nameL, WALeft);
1603 font = WMBoldSystemFontOfSize(scr, 24);
1604 WMSetLabelFont(panel->nameL, font);
1605 WMReleaseFont(font);
1606 WMSetLabelText(panel->nameL, _("Fatal error"));
1608 panel->sepF = WMCreateFrame(panel->win);
1609 WMResizeWidget(panel->sepF, PWIDTH + 4, 2);
1610 WMMoveWidget(panel->sepF, -2, 80);
1612 panel->noteL = WMCreateLabel(panel->win);
1613 WMResizeWidget(panel->noteL, PWIDTH - 20, 40);
1614 WMMoveWidget(panel->noteL, 10, 90);
1615 WMSetLabelTextAlignment(panel->noteL, WAJustified);
1616 snprintf(buf, sizeof(buf), _("Window Maker received signal %i."), whatSig);
1617 WMSetLabelText(panel->noteL, buf);
1619 panel->note2L = WMCreateLabel(panel->win);
1620 WMResizeWidget(panel->note2L, PWIDTH - 20, 100);
1621 WMMoveWidget(panel->note2L, 10, 130);
1622 WMSetLabelTextAlignment(panel->note2L, WALeft);
1623 WMSetLabelText(panel->note2L,
1624 _(" This fatal error occured probably due to a bug."
1625 " Please fill the included BUGFORM and " "report it to bugs@windowmaker.info."));
1626 WMSetLabelWraps(panel->note2L, True);
1628 panel->whatF = WMCreateFrame(panel->win);
1629 WMResizeWidget(panel->whatF, PWIDTH - 20, 50);
1630 WMMoveWidget(panel->whatF, 10, 240);
1631 WMSetFrameTitle(panel->whatF, _("What do you want to do now?"));
1633 panel->whatP = WMCreatePopUpButton(panel->whatF);
1634 WMResizeWidget(panel->whatP, PWIDTH - 20 - 70, 20);
1635 WMMoveWidget(panel->whatP, 35, 20);
1636 WMSetPopUpButtonPullsDown(panel->whatP, False);
1637 WMSetPopUpButtonText(panel->whatP, _("Select action"));
1638 WMAddPopUpButtonItem(panel->whatP, _("Abort and leave a core file"));
1639 WMAddPopUpButtonItem(panel->whatP, _("Restart Window Maker"));
1640 WMAddPopUpButtonItem(panel->whatP, _("Start alternate window manager"));
1641 WMSetPopUpButtonAction(panel->whatP, setCrashAction, panel);
1642 WMSetPopUpButtonSelectedItem(panel->whatP, WMRestart);
1643 panel->action = WMRestart;
1645 WMMapSubwidgets(panel->whatF);
1647 panel->okB = WMCreateCommandButton(panel->win);
1648 WMResizeWidget(panel->okB, 80, 26);
1649 WMMoveWidget(panel->okB, 205, 309);
1650 WMSetButtonText(panel->okB, _("OK"));
1651 WMSetButtonImage(panel->okB, WMGetSystemPixmap(scr, WSIReturnArrow));
1652 WMSetButtonAltImage(panel->okB, WMGetSystemPixmap(scr, WSIHighlightedReturnArrow));
1653 WMSetButtonImagePosition(panel->okB, WIPRight);
1654 WMSetButtonAction(panel->okB, okButtonCallback, panel);
1656 panel->done = 0;
1658 WMCreateEventHandler(WMWidgetView(panel->win), KeyPressMask, handleKeyPress, panel);
1660 WMRealizeWidget(panel->win);
1661 WMMapSubwidgets(panel->win);
1663 WMMapWidget(panel->win);
1665 XSetInputFocus(dpy, WMWidgetXID(panel->win), RevertToParent, CurrentTime);
1667 while (!panel->done) {
1668 XEvent event;
1670 WMNextEvent(dpy, &event);
1671 WMHandleEvent(&event);
1674 action = panel->action;
1676 WMUnmapWidget(panel->win);
1677 WMDestroyWidget(panel->win);
1678 wfree(panel);
1680 return action;