wmaker: fix possible buffer overrun with filename for Icon Chooser (Coverity #50218)
[wmaker-crm.git] / src / dialog.c
blobd14d336e07ba83c763540cc24992ff8a037bcfce
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
7 * Copyright (c) 2014 Window Maker Team
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24 #include "wconfig.h"
26 #include <X11/Xlib.h>
27 #include <X11/Xutil.h>
28 #include <X11/keysym.h>
30 #include <stdlib.h>
31 #include <stdio.h>
32 #include <unistd.h>
33 #include <string.h>
34 #include <sys/types.h>
35 #include <sys/stat.h>
36 #include <dirent.h>
37 #include <limits.h>
39 #ifdef HAVE_MALLOC_H
40 #include <malloc.h>
41 #endif
43 #include <signal.h>
44 #ifdef __FreeBSD__
45 #include <sys/signal.h>
46 #endif
48 #ifndef PATH_MAX
49 #define PATH_MAX DEFAULT_PATH_MAX
50 #endif
52 #include "WindowMaker.h"
53 #include "GNUstep.h"
54 #include "screen.h"
55 #include "window.h"
56 #include "dialog.h"
57 #include "misc.h"
58 #include "stacking.h"
59 #include "framewin.h"
60 #include "window.h"
61 #include "actions.h"
62 #include "xinerama.h"
65 static WMPoint getCenter(WScreen * scr, int width, int height)
67 return wGetPointToCenterRectInHead(scr, wGetHeadForPointerLocation(scr), width, height);
70 int wMessageDialog(WScreen *scr, const char *title, const char *message, const char *defBtn, const char *altBtn, const char *othBtn)
72 WMAlertPanel *panel;
73 Window parent;
74 WWindow *wwin;
75 int result;
76 WMPoint center;
78 panel = WMCreateAlertPanel(scr->wmscreen, NULL, title, message, defBtn, altBtn, othBtn);
80 parent = XCreateSimpleWindow(dpy, scr->root_win, 0, 0, 400, 180, 0, 0, 0);
82 XReparentWindow(dpy, WMWidgetXID(panel->win), parent, 0, 0);
84 center = getCenter(scr, 400, 180);
85 wwin = wManageInternalWindow(scr, parent, None, NULL, center.x, center.y, 400, 180);
86 wwin->client_leader = WMWidgetXID(panel->win);
88 WMMapWidget(panel->win);
90 wWindowMap(wwin);
92 WMRunModalLoop(WMWidgetScreen(panel->win), WMWidgetView(panel->win));
94 result = panel->result;
96 WMUnmapWidget(panel->win);
98 wUnmanageWindow(wwin, False, False);
100 WMDestroyAlertPanel(panel);
102 XDestroyWindow(dpy, parent);
104 return result;
107 static void toggleSaveSession(WMWidget *w, void *data)
109 /* Parameter not used, but tell the compiler that it is ok */
110 (void) data;
112 wPreferences.save_session_on_exit = WMGetButtonSelected((WMButton *) w);
115 int wExitDialog(WScreen *scr, const char *title, const char *message, const char *defBtn, const char *altBtn, const char *othBtn)
117 WMAlertPanel *panel;
118 WMButton *saveSessionBtn;
119 Window parent;
120 WWindow *wwin;
121 WMPoint center;
122 int result;
124 panel = WMCreateAlertPanel(scr->wmscreen, NULL, title, message, defBtn, altBtn, othBtn);
126 /* add save session button */
127 saveSessionBtn = WMCreateSwitchButton(panel->hbox);
128 WMSetButtonAction(saveSessionBtn, toggleSaveSession, NULL);
129 WMAddBoxSubview(panel->hbox, WMWidgetView(saveSessionBtn), False, True, 200, 0, 0);
130 WMSetButtonText(saveSessionBtn, _("Save workspace state"));
131 WMSetButtonSelected(saveSessionBtn, wPreferences.save_session_on_exit);
132 WMRealizeWidget(saveSessionBtn);
133 WMMapWidget(saveSessionBtn);
135 parent = XCreateSimpleWindow(dpy, scr->root_win, 0, 0, 400, 180, 0, 0, 0);
137 XReparentWindow(dpy, WMWidgetXID(panel->win), parent, 0, 0);
139 center = getCenter(scr, 400, 180);
140 wwin = wManageInternalWindow(scr, parent, None, NULL, center.x, center.y, 400, 180);
142 wwin->client_leader = WMWidgetXID(panel->win);
144 WMMapWidget(panel->win);
146 wWindowMap(wwin);
148 WMRunModalLoop(WMWidgetScreen(panel->win), WMWidgetView(panel->win));
150 result = panel->result;
152 WMUnmapWidget(panel->win);
154 wUnmanageWindow(wwin, False, False);
156 WMDestroyAlertPanel(panel);
158 XDestroyWindow(dpy, parent);
160 return result;
163 typedef struct _WMInputPanelWithHistory {
164 WMInputPanel *panel;
165 WMArray *history;
166 int histpos;
167 char *prefix;
168 char *suffix;
169 char *rest;
170 WMArray *variants;
171 int varpos;
172 } WMInputPanelWithHistory;
174 static char *HistoryFileName(const char *name)
176 char *filename = NULL;
178 filename = wstrdup(wusergnusteppath());
179 filename = wstrappend(filename, "/.AppInfo/WindowMaker/History");
180 if (name && strlen(name)) {
181 filename = wstrappend(filename, ".");
182 filename = wstrappend(filename, name);
184 return filename;
187 static int strmatch(const void *str1, const void *str2)
189 return !strcmp((const char *)str1, (const char *)str2);
192 static WMArray *LoadHistory(const char *filename, int max)
194 WMPropList *plhistory;
195 WMPropList *plitem;
196 WMArray *history;
197 int i, num;
198 char *str;
200 history = WMCreateArrayWithDestructor(1, wfree);
201 WMAddToArray(history, wstrdup(""));
203 plhistory = WMReadPropListFromFile(filename);
205 if (plhistory) {
206 if (WMIsPLArray(plhistory)) {
207 num = WMGetPropListItemCount(plhistory);
209 for (i = 0; i < num; ++i) {
210 plitem = WMGetFromPLArray(plhistory, i);
211 if (WMIsPLString(plitem)) {
212 str = WMGetFromPLString(plitem);
213 if (WMFindInArray(history, strmatch, str) == WANotFound) {
215 * The string here is duplicated because it will be freed
216 * automatically when the array is deleted. This is not really
217 * great because it is already an allocated string,
218 * unfortunately we cannot re-use it because it will be freed
219 * when we discard the PL (and we don't want to waste the PL's
220 * memory either)
222 WMAddToArray(history, wstrdup(str));
223 if (--max <= 0)
224 break;
229 WMReleasePropList(plhistory);
232 return history;
235 static void SaveHistory(WMArray * history, const char *filename)
237 int i;
238 WMPropList *plhistory;
240 plhistory = WMCreatePLArray(NULL);
242 for (i = 0; i < WMGetArrayItemCount(history); ++i)
243 WMAddToPLArray(plhistory, WMCreatePLString(WMGetFromArray(history, i)));
245 WMWritePropListToFile(plhistory, filename);
246 WMReleasePropList(plhistory);
249 static int pstrcmp(const char **str1, const char **str2)
251 return strcmp(*str1, *str2);
254 static void
255 ScanFiles(const char *dir, const char *prefix, unsigned acceptmask, unsigned declinemask, WMArray * result)
257 int prefixlen;
258 DIR *d;
259 struct dirent *de;
260 struct stat sb;
261 char *fullfilename, *suffix;
263 prefixlen = strlen(prefix);
264 if ((d = opendir(dir)) != NULL) {
265 while ((de = readdir(d)) != NULL) {
266 if (strlen(de->d_name) > prefixlen &&
267 !strncmp(prefix, de->d_name, prefixlen) &&
268 strcmp(de->d_name, ".") != 0 && strcmp(de->d_name, "..")) {
269 fullfilename = wstrconcat((char *)dir, "/");
270 fullfilename = wstrappend(fullfilename, de->d_name);
272 if (stat(fullfilename, &sb) == 0 &&
273 (sb.st_mode & acceptmask) &&
274 !(sb.st_mode & declinemask) &&
275 WMFindInArray(result, (WMMatchDataProc *) strmatch,
276 de->d_name + prefixlen) == WANotFound) {
277 suffix = wstrdup(de->d_name + prefixlen);
278 if (sb.st_mode & S_IFDIR)
279 suffix = wstrappend(suffix, "/");
280 WMAddToArray(result, suffix);
282 wfree(fullfilename);
285 closedir(d);
289 static WMArray *GenerateVariants(const char *complete)
291 Bool firstWord = True;
292 WMArray *variants = NULL;
293 char *pos = NULL, *path = NULL, *tmp = NULL, *dir = NULL, *prefix = NULL;
295 variants = WMCreateArrayWithDestructor(0, wfree);
297 while (*complete == ' ')
298 ++complete;
300 if ((pos = strrchr(complete, ' ')) != NULL) {
301 complete = pos + 1;
302 firstWord = False;
305 if ((pos = strrchr(complete, '/')) != NULL) {
306 tmp = wstrndup((char *)complete, pos - complete + 1);
307 if (*tmp == '~' && *(tmp + 1) == '/' && getenv("HOME")) {
308 dir = wstrdup(getenv("HOME"));
309 dir = wstrappend(dir, tmp + 1);
310 wfree(tmp);
311 } else {
312 dir = tmp;
314 prefix = wstrdup(pos + 1);
315 ScanFiles(dir, prefix, (unsigned)-1, 0, variants);
316 wfree(dir);
317 wfree(prefix);
318 } else if (*complete == '~') {
319 WMAddToArray(variants, wstrdup("/"));
320 } else if (firstWord) {
321 path = getenv("PATH");
322 while (path) {
323 pos = strchr(path, ':');
324 if (pos) {
325 tmp = wstrndup(path, pos - path);
326 path = pos + 1;
327 } else if (*path != '\0') {
328 tmp = wstrdup(path);
329 path = NULL;
330 } else
331 break;
332 ScanFiles(tmp, complete, S_IXOTH | S_IXGRP | S_IXUSR, S_IFDIR, variants);
333 wfree(tmp);
337 WMSortArray(variants, (WMCompareDataProc *) pstrcmp);
338 return variants;
341 static void handleHistoryKeyPress(XEvent * event, void *clientData)
343 char *text;
344 unsigned pos;
345 WMInputPanelWithHistory *p = (WMInputPanelWithHistory *) clientData;
346 KeySym ksym;
348 ksym = XLookupKeysym(&event->xkey, 0);
350 switch (ksym) {
351 case XK_Up:
352 if (p->histpos < WMGetArrayItemCount(p->history) - 1) {
353 if (p->histpos == 0)
354 wfree(WMReplaceInArray(p->history, 0, WMGetTextFieldText(p->panel->text)));
355 p->histpos++;
356 WMSetTextFieldText(p->panel->text, WMGetFromArray(p->history, p->histpos));
358 break;
359 case XK_Down:
360 if (p->histpos > 0) {
361 p->histpos--;
362 WMSetTextFieldText(p->panel->text, WMGetFromArray(p->history, p->histpos));
364 break;
365 case XK_Tab:
366 if (!p->variants) {
367 text = WMGetTextFieldText(p->panel->text);
368 pos = WMGetTextFieldCursorPosition(p->panel->text);
369 p->prefix = wstrndup(text, pos);
370 p->suffix = wstrdup(text + pos);
371 wfree(text);
372 p->variants = GenerateVariants(p->prefix);
373 p->varpos = 0;
374 if (!p->variants) {
375 wfree(p->prefix);
376 wfree(p->suffix);
377 p->prefix = NULL;
378 p->suffix = NULL;
381 if (p->variants && p->prefix && p->suffix) {
382 p->varpos++;
383 if (p->varpos > WMGetArrayItemCount(p->variants))
384 p->varpos = 0;
385 if (p->varpos > 0)
386 text = wstrconcat(p->prefix, WMGetFromArray(p->variants, p->varpos - 1));
387 else
388 text = wstrdup(p->prefix);
389 pos = strlen(text);
390 text = wstrappend(text, p->suffix);
391 WMSetTextFieldText(p->panel->text, text);
392 WMSetTextFieldCursorPosition(p->panel->text, pos);
393 wfree(text);
395 break;
397 if (ksym != XK_Tab) {
398 if (p->prefix) {
399 wfree(p->prefix);
400 p->prefix = NULL;
402 if (p->suffix) {
403 wfree(p->suffix);
404 p->suffix = NULL;
406 if (p->variants) {
407 WMFreeArray(p->variants);
408 p->variants = NULL;
413 int wAdvancedInputDialog(WScreen *scr, const char *title, const char *message, const char *name, char **text)
415 WWindow *wwin;
416 Window parent;
417 char *result;
418 WMPoint center;
419 WMInputPanelWithHistory *p;
420 char *filename;
422 filename = HistoryFileName(name);
423 p = wmalloc(sizeof(WMInputPanelWithHistory));
424 p->panel = WMCreateInputPanel(scr->wmscreen, NULL, title, message, *text, _("OK"), _("Cancel"));
425 p->history = LoadHistory(filename, wPreferences.history_lines);
426 p->histpos = 0;
427 p->prefix = NULL;
428 p->suffix = NULL;
429 p->rest = NULL;
430 p->variants = NULL;
431 p->varpos = 0;
432 WMCreateEventHandler(WMWidgetView(p->panel->text), KeyPressMask, handleHistoryKeyPress, p);
434 parent = XCreateSimpleWindow(dpy, scr->root_win, 0, 0, 320, 160, 0, 0, 0);
435 XSelectInput(dpy, parent, KeyPressMask | KeyReleaseMask);
437 XReparentWindow(dpy, WMWidgetXID(p->panel->win), parent, 0, 0);
439 center = getCenter(scr, 320, 160);
440 wwin = wManageInternalWindow(scr, parent, None, NULL, center.x, center.y, 320, 160);
442 wwin->client_leader = WMWidgetXID(p->panel->win);
444 WMMapWidget(p->panel->win);
446 wWindowMap(wwin);
448 WMRunModalLoop(WMWidgetScreen(p->panel->win), WMWidgetView(p->panel->win));
450 if (p->panel->result == WAPRDefault) {
451 result = WMGetTextFieldText(p->panel->text);
452 wfree(WMReplaceInArray(p->history, 0, wstrdup(result)));
453 SaveHistory(p->history, filename);
454 } else
455 result = NULL;
457 wUnmanageWindow(wwin, False, False);
459 WMDestroyInputPanel(p->panel);
460 WMFreeArray(p->history);
461 wfree(p);
462 wfree(filename);
464 XDestroyWindow(dpy, parent);
466 if (result == NULL)
467 return False;
468 else {
469 if (*text)
470 wfree(*text);
471 *text = result;
473 return True;
477 int wInputDialog(WScreen *scr, const char *title, const char *message, char **text)
479 WWindow *wwin;
480 Window parent;
481 WMInputPanel *panel;
482 char *result;
483 WMPoint center;
485 panel = WMCreateInputPanel(scr->wmscreen, NULL, title, message, *text, _("OK"), _("Cancel"));
487 parent = XCreateSimpleWindow(dpy, scr->root_win, 0, 0, 320, 160, 0, 0, 0);
488 XSelectInput(dpy, parent, KeyPressMask | KeyReleaseMask);
490 XReparentWindow(dpy, WMWidgetXID(panel->win), parent, 0, 0);
492 center = getCenter(scr, 320, 160);
493 wwin = wManageInternalWindow(scr, parent, None, NULL, center.x, center.y, 320, 160);
495 wwin->client_leader = WMWidgetXID(panel->win);
497 WMMapWidget(panel->win);
499 wWindowMap(wwin);
501 WMRunModalLoop(WMWidgetScreen(panel->win), WMWidgetView(panel->win));
503 if (panel->result == WAPRDefault)
504 result = WMGetTextFieldText(panel->text);
505 else
506 result = NULL;
508 wUnmanageWindow(wwin, False, False);
510 WMDestroyInputPanel(panel);
512 XDestroyWindow(dpy, parent);
514 if (result == NULL)
515 return False;
516 else {
517 if (*text)
518 wfree(*text);
519 *text = result;
521 return True;
526 *****************************************************************
527 * Icon Selection Panel
528 *****************************************************************
531 typedef struct IconPanel {
533 WScreen *scr;
535 WMWindow *win;
537 WMLabel *dirLabel;
538 WMLabel *iconLabel;
540 WMList *dirList;
541 WMList *iconList;
542 WMFont *normalfont;
544 WMButton *previewButton;
546 WMLabel *iconView;
548 WMLabel *fileLabel;
549 WMTextField *fileField;
551 WMButton *okButton;
552 WMButton *cancelButton;
553 #if 0
554 WMButton *chooseButton;
555 #endif
556 short done;
557 short result;
558 short preview;
559 } IconPanel;
561 static void listPixmaps(WScreen *scr, WMList *lPtr, const char *path)
563 struct dirent *dentry;
564 DIR *dir;
565 char pbuf[PATH_MAX + 16];
566 char *apath;
567 IconPanel *panel = WMGetHangedData(lPtr);
569 panel->preview = False;
571 apath = wexpandpath(path);
572 dir = opendir(apath);
574 if (!dir) {
575 char *msg;
576 char *tmp;
577 tmp = _("Could not open directory ");
578 msg = wmalloc(strlen(tmp) + strlen(path) + 6);
579 strcpy(msg, tmp);
580 strcat(msg, path);
582 wMessageDialog(scr, _("Error"), msg, _("OK"), NULL, NULL);
583 wfree(msg);
584 wfree(apath);
585 return;
588 /* list contents in the column */
589 while ((dentry = readdir(dir))) {
590 struct stat statb;
592 if (strcmp(dentry->d_name, ".") == 0 || strcmp(dentry->d_name, "..") == 0)
593 continue;
595 if (wstrlcpy(pbuf, apath, sizeof(pbuf)) >= sizeof(pbuf) ||
596 wstrlcat(pbuf, "/", sizeof(pbuf)) >= sizeof(pbuf) ||
597 wstrlcat(pbuf, dentry->d_name, sizeof(pbuf)) >= sizeof(pbuf)) {
598 wwarning(_("full path for file \"%s\" in \"%s\" is longer than %ld bytes, skipped"),
599 dentry->d_name, path, sizeof(pbuf) - 1);
600 continue;
603 if (stat(pbuf, &statb) < 0)
604 continue;
606 if (statb.st_mode & (S_IRUSR | S_IRGRP | S_IROTH)
607 && statb.st_mode & (S_IFREG | S_IFLNK)) {
608 WMAddListItem(lPtr, dentry->d_name);
611 WMSortListItems(lPtr);
613 closedir(dir);
614 wfree(apath);
615 panel->preview = True;
618 static void setViewedImage(IconPanel *panel, const char *file)
620 WMPixmap *pixmap;
621 RColor color;
623 color.red = 0xae;
624 color.green = 0xaa;
625 color.blue = 0xae;
626 color.alpha = 0;
627 pixmap = WMCreateScaledBlendedPixmapFromFile(WMWidgetScreen(panel->win), file, &color, 75, 75);
629 if (!pixmap) {
630 WMSetButtonEnabled(panel->okButton, False);
632 WMSetLabelText(panel->iconView, _("Could not load image file "));
634 WMSetLabelImage(panel->iconView, NULL);
635 } else {
636 WMSetButtonEnabled(panel->okButton, True);
638 WMSetLabelText(panel->iconView, NULL);
639 WMSetLabelImage(panel->iconView, pixmap);
640 WMReleasePixmap(pixmap);
644 static void listCallback(void *self, void *data)
646 WMList *lPtr = (WMList *) self;
647 IconPanel *panel = (IconPanel *) data;
648 char *path;
650 if (lPtr == panel->dirList) {
651 WMListItem *item = WMGetListSelectedItem(lPtr);
653 if (item == NULL)
654 return;
655 path = item->text;
657 WMSetTextFieldText(panel->fileField, path);
659 WMSetLabelImage(panel->iconView, NULL);
661 WMSetButtonEnabled(panel->okButton, False);
663 WMClearList(panel->iconList);
664 listPixmaps(panel->scr, panel->iconList, path);
665 } else {
666 char *tmp, *iconFile;
667 WMListItem *item = WMGetListSelectedItem(panel->dirList);
669 if (item == NULL)
670 return;
671 path = item->text;
673 item = WMGetListSelectedItem(panel->iconList);
674 if (item == NULL)
675 return;
676 iconFile = item->text;
678 tmp = wexpandpath(path);
679 path = wmalloc(strlen(tmp) + strlen(iconFile) + 4);
680 strcpy(path, tmp);
681 strcat(path, "/");
682 strcat(path, iconFile);
683 wfree(tmp);
684 WMSetTextFieldText(panel->fileField, path);
685 setViewedImage(panel, path);
686 wfree(path);
690 static void listIconPaths(WMList * lPtr)
692 char *paths;
693 char *path;
695 paths = wstrdup(wPreferences.icon_path);
697 path = strtok(paths, ":");
699 do {
700 char *tmp;
702 tmp = wexpandpath(path);
703 /* do not sort, because the order implies the order of
704 * directories searched */
705 if (access(tmp, X_OK) == 0)
706 WMAddListItem(lPtr, path);
707 wfree(tmp);
708 } while ((path = strtok(NULL, ":")) != NULL);
710 wfree(paths);
713 static void drawIconProc(WMList * lPtr, int index, Drawable d, char *text, int state, WMRect * rect)
715 IconPanel *panel = WMGetHangedData(lPtr);
716 WScreen *scr = panel->scr;
717 GC gc = scr->draw_gc;
718 GC copygc = scr->copy_gc;
719 char *file, *dirfile;
720 WMPixmap *pixmap;
721 WMColor *back;
722 WMSize size;
723 WMScreen *wmscr = WMWidgetScreen(panel->win);
724 RColor color;
725 int x, y, width, height, len;
727 /* Parameter not used, but tell the compiler that it is ok */
728 (void) index;
730 if (!panel->preview)
731 return;
733 x = rect->pos.x;
734 y = rect->pos.y;
735 width = rect->size.width;
736 height = rect->size.height;
738 back = (state & WLDSSelected) ? scr->white : scr->gray;
740 dirfile = wexpandpath(WMGetListSelectedItem(panel->dirList)->text);
741 len = strlen(dirfile) + strlen(text) + 4;
742 file = wmalloc(len);
743 snprintf(file, len, "%s/%s", dirfile, text);
744 wfree(dirfile);
746 color.red = WMRedComponentOfColor(back) >> 8;
747 color.green = WMGreenComponentOfColor(back) >> 8;
748 color.blue = WMBlueComponentOfColor(back) >> 8;
749 color.alpha = WMGetColorAlpha(back) >> 8;
751 pixmap = WMCreateScaledBlendedPixmapFromFile(wmscr, file, &color, width - 2, height - 2);
752 wfree(file);
754 if (!pixmap) {
755 /*WMRemoveListItem(lPtr, index); */
756 return;
759 XFillRectangle(dpy, d, WMColorGC(back), x, y, width, height);
761 XSetClipMask(dpy, gc, None);
762 /*XDrawRectangle(dpy, d, WMColorGC(white), x+5, y+5, width-10, 54); */
763 XDrawLine(dpy, d, WMColorGC(scr->white), x, y + height - 1, x + width, y + height - 1);
765 size = WMGetPixmapSize(pixmap);
767 XSetClipMask(dpy, copygc, WMGetPixmapMaskXID(pixmap));
768 XSetClipOrigin(dpy, copygc, x + (width - size.width) / 2, y + 2);
769 XCopyArea(dpy, WMGetPixmapXID(pixmap), d, copygc, 0, 0,
770 size.width > 100 ? 100 : size.width, size.height > 64 ? 64 : size.height,
771 x + (width - size.width) / 2, y + 2);
774 int i, j;
775 int fheight = WMFontHeight(panel->normalfont);
776 int tlen = strlen(text);
777 int twidth = WMWidthOfString(panel->normalfont, text, tlen);
778 int ofx, ofy;
780 ofx = x + (width - twidth) / 2;
781 ofy = y + 64 - fheight;
783 for (i = -1; i < 2; i++)
784 for (j = -1; j < 2; j++)
785 WMDrawString(wmscr, d, scr->white, panel->normalfont,
786 ofx + i, ofy + j, text, tlen);
788 WMDrawString(wmscr, d, scr->black, panel->normalfont, ofx, ofy, text, tlen);
791 WMReleasePixmap(pixmap);
792 /* I hope it is better to do not use cache / on my box it is fast nuff */
793 XFlush(dpy);
796 static void buttonCallback(void *self, void *clientData)
798 WMButton *bPtr = (WMButton *) self;
799 IconPanel *panel = (IconPanel *) clientData;
801 if (bPtr == panel->okButton) {
802 panel->done = True;
803 panel->result = True;
804 } else if (bPtr == panel->cancelButton) {
805 panel->done = True;
806 panel->result = False;
807 } else if (bPtr == panel->previewButton) {
808 /**** Previewer ****/
809 WMSetButtonEnabled(bPtr, False);
810 WMSetListUserDrawItemHeight(panel->iconList, 68);
811 WMSetListUserDrawProc(panel->iconList, drawIconProc);
812 WMRedisplayWidget(panel->iconList);
813 /* for draw proc to access screen/gc */
814 /*** end preview ***/
816 #if 0
817 else if (bPtr == panel->chooseButton) {
818 WMOpenPanel *op;
820 op = WMCreateOpenPanel(WMWidgetScreen(bPtr));
822 if (WMRunModalFilePanelForDirectory(op, NULL, "/usr/local", NULL, NULL)) {
823 char *path;
824 path = WMGetFilePanelFile(op);
825 WMSetTextFieldText(panel->fileField, path);
826 setViewedImage(panel, path);
827 wfree(path);
829 WMDestroyFilePanel(op);
831 #endif
834 static void keyPressHandler(XEvent * event, void *data)
836 IconPanel *panel = (IconPanel *) data;
837 char buffer[32];
838 KeySym ksym;
839 int iidx;
840 int didx;
841 int item = 0;
842 WMList *list = NULL;
844 if (event->type == KeyRelease)
845 return;
847 buffer[0] = 0;
848 XLookupString(&event->xkey, buffer, sizeof(buffer), &ksym, NULL);
850 iidx = WMGetListSelectedItemRow(panel->iconList);
851 didx = WMGetListSelectedItemRow(panel->dirList);
853 switch (ksym) {
854 case XK_Up:
855 if (iidx > 0)
856 item = iidx - 1;
857 else
858 item = iidx;
859 list = panel->iconList;
860 break;
861 case XK_Down:
862 if (iidx < WMGetListNumberOfRows(panel->iconList) - 1)
863 item = iidx + 1;
864 else
865 item = iidx;
866 list = panel->iconList;
867 break;
868 case XK_Home:
869 item = 0;
870 list = panel->iconList;
871 break;
872 case XK_End:
873 item = WMGetListNumberOfRows(panel->iconList) - 1;
874 list = panel->iconList;
875 break;
876 case XK_Next:
877 if (didx < WMGetListNumberOfRows(panel->dirList) - 1)
878 item = didx + 1;
879 else
880 item = didx;
881 list = panel->dirList;
882 break;
883 case XK_Prior:
884 if (didx > 0)
885 item = didx - 1;
886 else
887 item = 0;
888 list = panel->dirList;
889 break;
890 case XK_Return:
891 WMPerformButtonClick(panel->okButton);
892 break;
893 case XK_Escape:
894 WMPerformButtonClick(panel->cancelButton);
895 break;
898 if (list) {
899 WMSelectListItem(list, item);
900 WMSetListPosition(list, item - 5);
901 listCallback(list, panel);
905 Bool wIconChooserDialog(WScreen *scr, char **file, const char *instance, const char *class)
907 WWindow *wwin;
908 Window parent;
909 IconPanel *panel;
910 WMColor *color;
911 WMFont *boldFont;
912 Bool result;
914 panel = wmalloc(sizeof(IconPanel));
916 panel->scr = scr;
918 panel->win = WMCreateWindow(scr->wmscreen, "iconChooser");
919 WMResizeWidget(panel->win, 450, 280);
921 WMCreateEventHandler(WMWidgetView(panel->win), KeyPressMask | KeyReleaseMask, keyPressHandler, panel);
923 boldFont = WMBoldSystemFontOfSize(scr->wmscreen, 12);
924 panel->normalfont = WMSystemFontOfSize(WMWidgetScreen(panel->win), 12);
926 panel->dirLabel = WMCreateLabel(panel->win);
927 WMResizeWidget(panel->dirLabel, 200, 20);
928 WMMoveWidget(panel->dirLabel, 10, 7);
929 WMSetLabelText(panel->dirLabel, _("Directories"));
930 WMSetLabelFont(panel->dirLabel, boldFont);
931 WMSetLabelTextAlignment(panel->dirLabel, WACenter);
933 WMSetLabelRelief(panel->dirLabel, WRSunken);
935 panel->iconLabel = WMCreateLabel(panel->win);
936 WMResizeWidget(panel->iconLabel, 140, 20);
937 WMMoveWidget(panel->iconLabel, 215, 7);
938 WMSetLabelText(panel->iconLabel, _("Icons"));
939 WMSetLabelFont(panel->iconLabel, boldFont);
940 WMSetLabelTextAlignment(panel->iconLabel, WACenter);
942 WMReleaseFont(boldFont);
944 color = WMWhiteColor(scr->wmscreen);
945 WMSetLabelTextColor(panel->dirLabel, color);
946 WMSetLabelTextColor(panel->iconLabel, color);
947 WMReleaseColor(color);
949 color = WMDarkGrayColor(scr->wmscreen);
950 WMSetWidgetBackgroundColor(panel->iconLabel, color);
951 WMSetWidgetBackgroundColor(panel->dirLabel, color);
952 WMReleaseColor(color);
954 WMSetLabelRelief(panel->iconLabel, WRSunken);
956 panel->dirList = WMCreateList(panel->win);
957 WMResizeWidget(panel->dirList, 200, 170);
958 WMMoveWidget(panel->dirList, 10, 30);
959 WMSetListAction(panel->dirList, listCallback, panel);
961 panel->iconList = WMCreateList(panel->win);
962 WMResizeWidget(panel->iconList, 140, 170);
963 WMMoveWidget(panel->iconList, 215, 30);
964 WMSetListAction(panel->iconList, listCallback, panel);
966 WMHangData(panel->iconList, panel);
968 panel->previewButton = WMCreateCommandButton(panel->win);
969 WMResizeWidget(panel->previewButton, 75, 26);
970 WMMoveWidget(panel->previewButton, 365, 130);
971 WMSetButtonText(panel->previewButton, _("Preview"));
972 WMSetButtonAction(panel->previewButton, buttonCallback, panel);
974 panel->iconView = WMCreateLabel(panel->win);
975 WMResizeWidget(panel->iconView, 75, 75);
976 WMMoveWidget(panel->iconView, 365, 40);
977 WMSetLabelImagePosition(panel->iconView, WIPOverlaps);
978 WMSetLabelRelief(panel->iconView, WRSunken);
979 WMSetLabelTextAlignment(panel->iconView, WACenter);
981 panel->fileLabel = WMCreateLabel(panel->win);
982 WMResizeWidget(panel->fileLabel, 80, 20);
983 WMMoveWidget(panel->fileLabel, 10, 210);
984 WMSetLabelText(panel->fileLabel, _("File Name:"));
986 panel->fileField = WMCreateTextField(panel->win);
987 WMSetViewNextResponder(WMWidgetView(panel->fileField), WMWidgetView(panel->win));
988 WMResizeWidget(panel->fileField, 345, 20);
989 WMMoveWidget(panel->fileField, 95, 210);
990 WMSetTextFieldEditable(panel->fileField, False);
992 panel->okButton = WMCreateCommandButton(panel->win);
993 WMResizeWidget(panel->okButton, 80, 26);
994 WMMoveWidget(panel->okButton, 360, 240);
995 WMSetButtonText(panel->okButton, _("OK"));
996 WMSetButtonEnabled(panel->okButton, False);
997 WMSetButtonAction(panel->okButton, buttonCallback, panel);
999 panel->cancelButton = WMCreateCommandButton(panel->win);
1000 WMResizeWidget(panel->cancelButton, 80, 26);
1001 WMMoveWidget(panel->cancelButton, 270, 240);
1002 WMSetButtonText(panel->cancelButton, _("Cancel"));
1003 WMSetButtonAction(panel->cancelButton, buttonCallback, panel);
1004 #if 0
1005 panel->chooseButton = WMCreateCommandButton(panel->win);
1006 WMResizeWidget(panel->chooseButton, 110, 26);
1007 WMMoveWidget(panel->chooseButton, 150, 240);
1008 WMSetButtonText(panel->chooseButton, _("Choose File"));
1009 WMSetButtonAction(panel->chooseButton, buttonCallback, panel);
1010 #endif
1011 WMRealizeWidget(panel->win);
1012 WMMapSubwidgets(panel->win);
1014 parent = XCreateSimpleWindow(dpy, scr->root_win, 0, 0, 450, 280, 0, 0, 0);
1016 XReparentWindow(dpy, WMWidgetXID(panel->win), parent, 0, 0);
1019 static const char *prefix = NULL;
1020 char *title;
1021 int len;
1022 WMPoint center;
1024 if (prefix == NULL)
1025 prefix = _("Icon Chooser");
1027 len = strlen(prefix)
1028 + 2 // " ["
1029 + (instance ? strlen(instance) : 0)
1030 + 1 // "."
1031 + (class ? strlen(class) : 0)
1032 + 1 // "]"
1033 + 1; // final NUL
1035 title = wmalloc(len);
1036 strcpy(title, prefix);
1038 if (instance || class) {
1039 strcat(title, " [");
1040 if (instance != NULL)
1041 strcat(title, instance);
1042 if (instance && class)
1043 strcat(title, ".");
1044 if (class != NULL)
1045 strcat(title, class);
1046 strcat(title, "]");
1049 center = getCenter(scr, 450, 280);
1051 wwin = wManageInternalWindow(scr, parent, None, title, center.x, center.y, 450, 280);
1052 wfree(title);
1055 /* put icon paths in the list */
1056 listIconPaths(panel->dirList);
1058 WMMapWidget(panel->win);
1060 wWindowMap(wwin);
1062 while (!panel->done) {
1063 XEvent event;
1065 WMNextEvent(dpy, &event);
1066 WMHandleEvent(&event);
1069 if (panel->result) {
1070 char *defaultPath, *wantedPath;
1072 /* check if the file the user selected is not the one that
1073 * would be loaded by default with the current search path */
1074 *file = WMGetListSelectedItem(panel->iconList)->text;
1075 if (**file == 0) {
1076 wfree(*file);
1077 *file = NULL;
1078 } else {
1079 defaultPath = FindImage(wPreferences.icon_path, *file);
1080 wantedPath = WMGetTextFieldText(panel->fileField);
1081 /* if the file is not the default, use full path */
1082 if (strcmp(wantedPath, defaultPath) != 0) {
1083 *file = wantedPath;
1084 } else {
1085 *file = wstrdup(*file);
1086 wfree(wantedPath);
1088 wfree(defaultPath);
1090 } else {
1091 *file = NULL;
1094 result = panel->result;
1096 WMReleaseFont(panel->normalfont);
1098 WMUnmapWidget(panel->win);
1100 WMDestroyWidget(panel->win);
1102 wUnmanageWindow(wwin, False, False);
1104 wfree(panel);
1106 XDestroyWindow(dpy, parent);
1108 return result;
1112 ***********************************************************************
1113 * Info Panel
1114 ***********************************************************************
1117 typedef struct {
1118 WScreen *scr;
1119 WWindow *wwin;
1120 WMWindow *win;
1121 WMLabel *logoL;
1122 WMLabel *name1L;
1123 WMFrame *lineF;
1124 WMLabel *name2L;
1125 WMLabel *versionL;
1126 WMLabel *infoL;
1127 WMLabel *copyrL;
1128 } InfoPanel;
1130 #define COPYRIGHT_TEXT \
1131 "Copyright \xc2\xa9 1997-2006 Alfredo K. Kojima\n"\
1132 "Copyright \xc2\xa9 1998-2006 Dan Pascu\n"\
1133 "Copyright \xc2\xa9 2013-2014 Window Maker Developers Team"
1135 static InfoPanel *infoPanel = NULL;
1137 static void destroyInfoPanel(WCoreWindow *foo, void *data, XEvent *event)
1139 /* Parameter not used, but tell the compiler that it is ok */
1140 (void) foo;
1141 (void) data;
1142 (void) event;
1144 WMUnmapWidget(infoPanel);
1145 wUnmanageWindow(infoPanel->wwin, False, False);
1146 WMDestroyWidget(infoPanel->win);
1147 wfree(infoPanel);
1148 infoPanel = NULL;
1151 void wShowInfoPanel(WScreen *scr)
1153 const int win_width = 382;
1154 const int win_height = 250;
1155 InfoPanel *panel;
1156 WMPixmap *logo;
1157 WMFont *font;
1158 char *name, *strbuf = NULL;
1159 const char *separator;
1160 char buffer[256];
1161 Window parent;
1162 WWindow *wwin;
1163 WMPoint center;
1164 char **strl;
1165 int i, width = 50, sepHeight;
1166 char *visuals[] = {
1167 "StaticGray",
1168 "GrayScale",
1169 "StaticColor",
1170 "PseudoColor",
1171 "TrueColor",
1172 "DirectColor"
1175 if (infoPanel) {
1176 if (infoPanel->scr == scr) {
1177 wRaiseFrame(infoPanel->wwin->frame->core);
1178 wSetFocusTo(scr, infoPanel->wwin);
1180 return;
1183 panel = wmalloc(sizeof(InfoPanel));
1185 panel->scr = scr;
1187 panel->win = WMCreateWindow(scr->wmscreen, "info");
1188 WMResizeWidget(panel->win, win_width, win_height);
1190 logo = WMCreateApplicationIconBlendedPixmap(scr->wmscreen, (RColor *) NULL);
1191 if (!logo) {
1192 logo = WMRetainPixmap(WMGetApplicationIconPixmap(scr->wmscreen));
1194 if (logo) {
1195 panel->logoL = WMCreateLabel(panel->win);
1196 WMResizeWidget(panel->logoL, 64, 64);
1197 WMMoveWidget(panel->logoL, 30, 20);
1198 WMSetLabelImagePosition(panel->logoL, WIPImageOnly);
1199 WMSetLabelImage(panel->logoL, logo);
1200 WMReleasePixmap(logo);
1203 sepHeight = 3;
1204 panel->name1L = WMCreateLabel(panel->win);
1205 WMResizeWidget(panel->name1L, 240, 30 + 2);
1206 WMMoveWidget(panel->name1L, 100, 30 - 2 - sepHeight);
1208 name = "Lucida Sans,Comic Sans MS,URW Gothic L,Trebuchet MS" ":italic:pixelsize=28:antialias=true";
1209 font = WMCreateFont(scr->wmscreen, name);
1210 strbuf = "Window Maker";
1211 if (font) {
1212 width = WMWidthOfString(font, strbuf, strlen(strbuf));
1213 WMSetLabelFont(panel->name1L, font);
1214 WMReleaseFont(font);
1216 WMSetLabelTextAlignment(panel->name1L, WACenter);
1217 WMSetLabelText(panel->name1L, strbuf);
1219 panel->lineF = WMCreateFrame(panel->win);
1220 WMResizeWidget(panel->lineF, width, sepHeight);
1221 WMMoveWidget(panel->lineF, 100 + (240 - width) / 2, 60 - sepHeight);
1222 WMSetFrameRelief(panel->lineF, WRSimple);
1223 WMSetWidgetBackgroundColor(panel->lineF, scr->black);
1225 panel->name2L = WMCreateLabel(panel->win);
1226 WMResizeWidget(panel->name2L, 240, 24);
1227 WMMoveWidget(panel->name2L, 100, 60);
1228 name = "URW Gothic L,Nimbus Sans L:pixelsize=16:antialias=true";
1229 font = WMCreateFont(scr->wmscreen, name);
1230 if (font) {
1231 WMSetLabelFont(panel->name2L, font);
1232 WMReleaseFont(font);
1233 font = NULL;
1235 WMSetLabelTextAlignment(panel->name2L, WACenter);
1236 WMSetLabelText(panel->name2L, _("Window Manager for X"));
1238 snprintf(buffer, sizeof(buffer), _("Version %s"), VERSION);
1239 panel->versionL = WMCreateLabel(panel->win);
1240 WMResizeWidget(panel->versionL, 310, 16);
1241 WMMoveWidget(panel->versionL, 30, 95);
1242 WMSetLabelTextAlignment(panel->versionL, WARight);
1243 WMSetLabelText(panel->versionL, buffer);
1244 WMSetLabelWraps(panel->versionL, False);
1246 panel->copyrL = WMCreateLabel(panel->win);
1247 WMResizeWidget(panel->copyrL, 360, 60);
1248 WMMoveWidget(panel->copyrL, 15, 190);
1249 WMSetLabelTextAlignment(panel->copyrL, WALeft);
1250 WMSetLabelText(panel->copyrL, COPYRIGHT_TEXT);
1251 font = WMSystemFontOfSize(scr->wmscreen, 11);
1252 if (font) {
1253 WMSetLabelFont(panel->copyrL, font);
1254 WMReleaseFont(font);
1255 font = NULL;
1258 strbuf = NULL;
1259 snprintf(buffer, sizeof(buffer), _("Using visual 0x%x: %s %ibpp "),
1260 (unsigned)scr->w_visual->visualid, visuals[scr->w_visual->class], scr->w_depth);
1262 strbuf = wstrappend(strbuf, buffer);
1264 switch (scr->w_depth) {
1265 case 15:
1266 strbuf = wstrappend(strbuf, _("(32 thousand colors)\n"));
1267 break;
1268 case 16:
1269 strbuf = wstrappend(strbuf, _("(64 thousand colors)\n"));
1270 break;
1271 case 24:
1272 case 32:
1273 strbuf = wstrappend(strbuf, _("(16 million colors)\n"));
1274 break;
1275 default:
1276 snprintf(buffer, sizeof(buffer), _("(%d colors)\n"), 1 << scr->w_depth);
1277 strbuf = wstrappend(strbuf, buffer);
1278 break;
1281 #if defined(HAVE_MALLOC_H) && defined(HAVE_MALLINFO)
1283 struct mallinfo ma = mallinfo();
1284 snprintf(buffer, sizeof(buffer),
1285 #ifdef DEBUG
1286 _("Total memory allocated: %i kB (in use: %i kB, %d free chunks).\n"),
1287 #else
1288 _("Total memory allocated: %i kB (in use: %i kB).\n"),
1289 #endif
1290 (ma.arena + ma.hblkhd) / 1024,
1291 (ma.uordblks + ma.hblkhd) / 1024
1292 #ifdef DEBUG
1294 * This information is representative of the memory
1295 * fragmentation. In ideal case it should be 1, but
1296 * that is never possible
1298 , ma.ordblks
1299 #endif
1302 strbuf = wstrappend(strbuf, buffer);
1304 #endif
1306 strbuf = wstrappend(strbuf, _("Image formats: "));
1307 strl = RSupportedFileFormats();
1308 separator = NULL;
1309 for (i = 0; strl[i] != NULL; i++) {
1310 if (separator != NULL)
1311 strbuf = wstrappend(strbuf, separator);
1312 strbuf = wstrappend(strbuf, strl[i]);
1313 separator = ", ";
1316 strbuf = wstrappend(strbuf, _("\nAdditional support for: "));
1317 strbuf = wstrappend(strbuf, "WMSPEC");
1319 #ifdef MWM_HINTS
1320 strbuf = wstrappend(strbuf, ", MWM");
1321 #endif
1323 #ifdef XDND
1324 strbuf = wstrappend(strbuf, ", XDnD");
1325 #endif
1327 #ifdef USE_MAGICK
1328 strbuf = wstrappend(strbuf, ", ImageMagick");
1329 #endif
1331 #ifdef USE_XINERAMA
1332 strbuf = wstrappend(strbuf, _("\n"));
1333 #ifdef SOLARIS_XINERAMA
1334 strbuf = wstrappend(strbuf, _("Solaris "));
1335 #endif
1336 strbuf = wstrappend(strbuf, _("Xinerama: "));
1338 char tmp[128];
1339 snprintf(tmp, sizeof(tmp) - 1, _("%d head(s) found."), scr->xine_info.count);
1340 strbuf = wstrappend(strbuf, tmp);
1342 #endif
1344 #ifdef USE_RANDR
1345 strbuf = wstrappend(strbuf, _("\n"));
1346 strbuf = wstrappend(strbuf, "RandR: ");
1347 if (w_global.xext.randr.supported)
1348 strbuf = wstrappend(strbuf, _("supported"));
1349 else
1350 strbuf = wstrappend(strbuf, _("unsupported"));
1351 strbuf = wstrappend(strbuf, ".");
1352 #endif
1354 panel->infoL = WMCreateLabel(panel->win);
1355 WMResizeWidget(panel->infoL, 350, 80);
1356 WMMoveWidget(panel->infoL, 15, 115);
1357 WMSetLabelText(panel->infoL, strbuf);
1358 font = WMSystemFontOfSize(scr->wmscreen, 11);
1359 if (font) {
1360 WMSetLabelFont(panel->infoL, font);
1361 WMReleaseFont(font);
1362 font = NULL;
1364 wfree(strbuf);
1366 WMRealizeWidget(panel->win);
1367 WMMapSubwidgets(panel->win);
1369 parent = XCreateSimpleWindow(dpy, scr->root_win, 0, 0, win_width, win_height, 0, 0, 0);
1371 XReparentWindow(dpy, WMWidgetXID(panel->win), parent, 0, 0);
1373 WMMapWidget(panel->win);
1375 center = getCenter(scr, win_width, win_height);
1376 wwin = wManageInternalWindow(scr, parent, None, _("Info"), center.x, center.y, win_width, win_height);
1378 WSETUFLAG(wwin, no_closable, 0);
1379 WSETUFLAG(wwin, no_close_button, 0);
1380 #ifdef XKB_BUTTON_HINT
1381 wFrameWindowHideButton(wwin->frame, WFF_LANGUAGE_BUTTON);
1382 #endif
1383 wWindowUpdateButtonImages(wwin);
1384 wFrameWindowShowButton(wwin->frame, WFF_RIGHT_BUTTON);
1385 wwin->frame->on_click_right = destroyInfoPanel;
1387 wWindowMap(wwin);
1389 panel->wwin = wwin;
1390 infoPanel = panel;
1394 ***********************************************************************
1395 * Legal Panel
1396 ***********************************************************************
1399 typedef struct {
1400 WScreen *scr;
1401 WWindow *wwin;
1402 WMWindow *win;
1403 WMLabel *licenseL;
1404 } LegalPanel;
1406 static LegalPanel *legalPanel = NULL;
1408 static void destroyLegalPanel(WCoreWindow * foo, void *data, XEvent * event)
1410 /* Parameter not used, but tell the compiler that it is ok */
1411 (void) foo;
1412 (void) data;
1413 (void) event;
1415 WMUnmapWidget(legalPanel->win);
1416 WMDestroyWidget(legalPanel->win);
1417 wUnmanageWindow(legalPanel->wwin, False, False);
1418 wfree(legalPanel);
1419 legalPanel = NULL;
1422 void wShowLegalPanel(WScreen *scr)
1424 const int win_width = 420;
1425 const int win_height = 250;
1426 const int margin = 10;
1427 LegalPanel *panel;
1428 Window parent;
1429 WWindow *wwin;
1430 WMPoint center;
1432 if (legalPanel) {
1433 if (legalPanel->scr == scr) {
1434 wRaiseFrame(legalPanel->wwin->frame->core);
1435 wSetFocusTo(scr, legalPanel->wwin);
1437 return;
1440 panel = wmalloc(sizeof(LegalPanel));
1441 panel->scr = scr;
1442 panel->win = WMCreateWindow(scr->wmscreen, "legal");
1443 WMResizeWidget(panel->win, win_width, win_height);
1445 panel->licenseL = WMCreateLabel(panel->win);
1446 WMSetLabelWraps(panel->licenseL, True);
1447 WMResizeWidget(panel->licenseL, win_width - (2 * margin), win_height - (2 * margin));
1448 WMMoveWidget(panel->licenseL, margin, margin);
1449 WMSetLabelTextAlignment(panel->licenseL, WALeft);
1450 WMSetLabelText(panel->licenseL,
1451 _(" Window Maker is free software; you can redistribute it and/or "
1452 "modify it under the terms of the GNU General Public License as "
1453 "published by the Free Software Foundation; either version 2 of the "
1454 "License, or (at your option) any later version.\n\n"
1455 " Window Maker is distributed in the hope that it will be useful, "
1456 "but WITHOUT ANY WARRANTY; without even the implied warranty "
1457 "of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. "
1458 "See the GNU General Public License for more details.\n\n"
1459 " You should have received a copy of the GNU General Public "
1460 "License along with this program; if not, write to the Free Software "
1461 "Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA"
1462 "02110-1301 USA."));
1463 WMSetLabelRelief(panel->licenseL, WRGroove);
1465 WMRealizeWidget(panel->win);
1466 WMMapSubwidgets(panel->win);
1468 parent = XCreateSimpleWindow(dpy, scr->root_win, 0, 0, win_width, win_height, 0, 0, 0);
1469 XReparentWindow(dpy, WMWidgetXID(panel->win), parent, 0, 0);
1470 center = getCenter(scr, win_width, win_height);
1471 wwin = wManageInternalWindow(scr, parent, None, _("Legal"), center.x, center.y, win_width, win_height);
1473 WSETUFLAG(wwin, no_closable, 0);
1474 WSETUFLAG(wwin, no_close_button, 0);
1475 wWindowUpdateButtonImages(wwin);
1476 wFrameWindowShowButton(wwin->frame, WFF_RIGHT_BUTTON);
1477 #ifdef XKB_BUTTON_HINT
1478 wFrameWindowHideButton(wwin->frame, WFF_LANGUAGE_BUTTON);
1479 #endif
1480 wwin->frame->on_click_right = destroyLegalPanel;
1481 panel->wwin = wwin;
1483 WMMapWidget(panel->win);
1484 wWindowMap(wwin);
1485 legalPanel = panel;
1489 ***********************************************************************
1490 * Crashing Dialog Panel
1491 ***********************************************************************
1494 typedef struct _CrashPanel {
1495 WMWindow *win; /* main window */
1497 WMLabel *iconL; /* application icon */
1498 WMLabel *nameL; /* title of panel */
1500 WMFrame *sepF; /* separator frame */
1502 WMLabel *noteL; /* Title of note */
1503 WMLabel *note2L; /* body of note with what happened */
1505 WMFrame *whatF; /* "what to do next" frame */
1506 WMPopUpButton *whatP; /* action selection popup button */
1508 WMButton *okB; /* ok button */
1510 Bool done; /* if finished with this dialog */
1511 int action; /* what to do after */
1513 KeyCode retKey;
1515 } CrashPanel;
1517 static void handleKeyPress(XEvent * event, void *clientData)
1519 CrashPanel *panel = (CrashPanel *) clientData;
1521 if (event->xkey.keycode == panel->retKey) {
1522 WMPerformButtonClick(panel->okB);
1526 static void okButtonCallback(void *self, void *clientData)
1528 CrashPanel *panel = (CrashPanel *) clientData;
1530 /* Parameter not used, but tell the compiler that it is ok */
1531 (void) self;
1533 panel->done = True;
1536 static void setCrashAction(void *self, void *clientData)
1538 WMPopUpButton *pop = (WMPopUpButton *) self;
1539 CrashPanel *panel = (CrashPanel *) clientData;
1541 panel->action = WMGetPopUpButtonSelectedItem(pop);
1544 /* Make this read the logo from a compiled in pixmap -Dan */
1545 static WMPixmap *getWindowMakerIconImage(WMScreen *scr)
1547 WMPixmap *pix = NULL;
1548 char *path = NULL;
1550 /* Get the Logo icon, without the default icon */
1551 path = get_icon_filename("Logo", "WMPanel", NULL, False);
1553 if (path) {
1554 RColor gray;
1556 gray.red = 0xae;
1557 gray.green = 0xaa;
1558 gray.blue = 0xae;
1559 gray.alpha = 0;
1561 pix = WMCreateBlendedPixmapFromFile(scr, path, &gray);
1562 wfree(path);
1565 return pix;
1568 #define PWIDTH 295
1569 #define PHEIGHT 345
1571 int wShowCrashingDialogPanel(int whatSig)
1573 CrashPanel *panel;
1574 WMScreen *scr;
1575 WMFont *font;
1576 WMPixmap *logo;
1577 int screen_no, scr_width, scr_height;
1578 int action;
1579 char buf[256];
1581 screen_no = DefaultScreen(dpy);
1582 scr_width = WidthOfScreen(ScreenOfDisplay(dpy, screen_no));
1583 scr_height = HeightOfScreen(ScreenOfDisplay(dpy, screen_no));
1585 scr = WMCreateScreen(dpy, screen_no);
1586 if (!scr) {
1587 werror(_("cannot open connection for crashing dialog panel. Aborting."));
1588 return WMAbort;
1591 panel = wmalloc(sizeof(CrashPanel));
1593 panel->retKey = XKeysymToKeycode(dpy, XK_Return);
1595 panel->win = WMCreateWindow(scr, "crashingDialog");
1596 WMResizeWidget(panel->win, PWIDTH, PHEIGHT);
1597 WMMoveWidget(panel->win, (scr_width - PWIDTH) / 2, (scr_height - PHEIGHT) / 2);
1599 logo = getWindowMakerIconImage(scr);
1600 if (logo) {
1601 panel->iconL = WMCreateLabel(panel->win);
1602 WMResizeWidget(panel->iconL, 64, 64);
1603 WMMoveWidget(panel->iconL, 10, 10);
1604 WMSetLabelImagePosition(panel->iconL, WIPImageOnly);
1605 WMSetLabelImage(panel->iconL, logo);
1608 panel->nameL = WMCreateLabel(panel->win);
1609 WMResizeWidget(panel->nameL, 200, 30);
1610 WMMoveWidget(panel->nameL, 80, 25);
1611 WMSetLabelTextAlignment(panel->nameL, WALeft);
1612 font = WMBoldSystemFontOfSize(scr, 24);
1613 WMSetLabelFont(panel->nameL, font);
1614 WMReleaseFont(font);
1615 WMSetLabelText(panel->nameL, _("Fatal error"));
1617 panel->sepF = WMCreateFrame(panel->win);
1618 WMResizeWidget(panel->sepF, PWIDTH + 4, 2);
1619 WMMoveWidget(panel->sepF, -2, 80);
1621 panel->noteL = WMCreateLabel(panel->win);
1622 WMResizeWidget(panel->noteL, PWIDTH - 20, 40);
1623 WMMoveWidget(panel->noteL, 10, 90);
1624 WMSetLabelTextAlignment(panel->noteL, WAJustified);
1625 snprintf(buf, sizeof(buf), _("Window Maker received signal %i."), whatSig);
1626 WMSetLabelText(panel->noteL, buf);
1628 panel->note2L = WMCreateLabel(panel->win);
1629 WMResizeWidget(panel->note2L, PWIDTH - 20, 100);
1630 WMMoveWidget(panel->note2L, 10, 130);
1631 WMSetLabelTextAlignment(panel->note2L, WALeft);
1632 WMSetLabelText(panel->note2L,
1633 _(" This fatal error occured probably due to a bug."
1634 " Please fill the included BUGFORM and " "report it to bugs@windowmaker.info."));
1635 WMSetLabelWraps(panel->note2L, True);
1637 panel->whatF = WMCreateFrame(panel->win);
1638 WMResizeWidget(panel->whatF, PWIDTH - 20, 50);
1639 WMMoveWidget(panel->whatF, 10, 240);
1640 WMSetFrameTitle(panel->whatF, _("What do you want to do now?"));
1642 panel->whatP = WMCreatePopUpButton(panel->whatF);
1643 WMResizeWidget(panel->whatP, PWIDTH - 20 - 70, 20);
1644 WMMoveWidget(panel->whatP, 35, 20);
1645 WMSetPopUpButtonPullsDown(panel->whatP, False);
1646 WMSetPopUpButtonText(panel->whatP, _("Select action"));
1647 WMAddPopUpButtonItem(panel->whatP, _("Abort and leave a core file"));
1648 WMAddPopUpButtonItem(panel->whatP, _("Restart Window Maker"));
1649 WMAddPopUpButtonItem(panel->whatP, _("Start alternate window manager"));
1650 WMSetPopUpButtonAction(panel->whatP, setCrashAction, panel);
1651 WMSetPopUpButtonSelectedItem(panel->whatP, WMRestart);
1652 panel->action = WMRestart;
1654 WMMapSubwidgets(panel->whatF);
1656 panel->okB = WMCreateCommandButton(panel->win);
1657 WMResizeWidget(panel->okB, 80, 26);
1658 WMMoveWidget(panel->okB, 205, 309);
1659 WMSetButtonText(panel->okB, _("OK"));
1660 WMSetButtonImage(panel->okB, WMGetSystemPixmap(scr, WSIReturnArrow));
1661 WMSetButtonAltImage(panel->okB, WMGetSystemPixmap(scr, WSIHighlightedReturnArrow));
1662 WMSetButtonImagePosition(panel->okB, WIPRight);
1663 WMSetButtonAction(panel->okB, okButtonCallback, panel);
1665 panel->done = 0;
1667 WMCreateEventHandler(WMWidgetView(panel->win), KeyPressMask, handleKeyPress, panel);
1669 WMRealizeWidget(panel->win);
1670 WMMapSubwidgets(panel->win);
1672 WMMapWidget(panel->win);
1674 XSetInputFocus(dpy, WMWidgetXID(panel->win), RevertToParent, CurrentTime);
1676 while (!panel->done) {
1677 XEvent event;
1679 WMNextEvent(dpy, &event);
1680 WMHandleEvent(&event);
1683 action = panel->action;
1685 WMUnmapWidget(panel->win);
1686 WMDestroyWidget(panel->win);
1687 wfree(panel);
1689 return action;