configure: rewrote 2 ARG_WITH for paths to provide better feedback
[wmaker-crm.git] / src / dialog.c
blob6bb342467766b7596c1d9097e49da43516d45415
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>
38 #include <errno.h>
40 #ifdef HAVE_MALLOC_H
41 #include <malloc.h>
42 #endif
44 #include <signal.h>
45 #ifdef __FreeBSD__
46 #include <sys/signal.h>
47 #endif
49 #ifndef PATH_MAX
50 #define PATH_MAX DEFAULT_PATH_MAX
51 #endif
53 #include "WindowMaker.h"
54 #include "GNUstep.h"
55 #include "screen.h"
56 #include "window.h"
57 #include "dialog.h"
58 #include "misc.h"
59 #include "stacking.h"
60 #include "framewin.h"
61 #include "window.h"
62 #include "actions.h"
63 #include "xinerama.h"
66 static WMPoint getCenter(WScreen * scr, int width, int height)
68 return wGetPointToCenterRectInHead(scr, wGetHeadForPointerLocation(scr), width, height);
71 int wMessageDialog(WScreen *scr, const char *title, const char *message, const char *defBtn, const char *altBtn, const char *othBtn)
73 WMAlertPanel *panel;
74 Window parent;
75 WWindow *wwin;
76 int result;
77 WMPoint center;
79 panel = WMCreateAlertPanel(scr->wmscreen, NULL, title, message, defBtn, altBtn, othBtn);
81 parent = XCreateSimpleWindow(dpy, scr->root_win, 0, 0, 400, 180, 0, 0, 0);
83 XReparentWindow(dpy, WMWidgetXID(panel->win), parent, 0, 0);
85 center = getCenter(scr, 400, 180);
86 wwin = wManageInternalWindow(scr, parent, None, NULL, center.x, center.y, 400, 180);
87 wwin->client_leader = WMWidgetXID(panel->win);
89 WMMapWidget(panel->win);
91 wWindowMap(wwin);
93 WMRunModalLoop(WMWidgetScreen(panel->win), WMWidgetView(panel->win));
95 result = panel->result;
97 WMUnmapWidget(panel->win);
99 wUnmanageWindow(wwin, False, False);
101 WMDestroyAlertPanel(panel);
103 XDestroyWindow(dpy, parent);
105 return result;
108 static void toggleSaveSession(WMWidget *w, void *data)
110 /* Parameter not used, but tell the compiler that it is ok */
111 (void) data;
113 wPreferences.save_session_on_exit = WMGetButtonSelected((WMButton *) w);
116 int wExitDialog(WScreen *scr, const char *title, const char *message, const char *defBtn, const char *altBtn, const char *othBtn)
118 WMAlertPanel *panel;
119 WMButton *saveSessionBtn;
120 Window parent;
121 WWindow *wwin;
122 WMPoint center;
123 int result;
125 panel = WMCreateAlertPanel(scr->wmscreen, NULL, title, message, defBtn, altBtn, othBtn);
127 /* add save session button */
128 saveSessionBtn = WMCreateSwitchButton(panel->hbox);
129 WMSetButtonAction(saveSessionBtn, toggleSaveSession, NULL);
130 WMAddBoxSubview(panel->hbox, WMWidgetView(saveSessionBtn), False, True, 200, 0, 0);
131 WMSetButtonText(saveSessionBtn, _("Save workspace state"));
132 WMSetButtonSelected(saveSessionBtn, wPreferences.save_session_on_exit);
133 WMRealizeWidget(saveSessionBtn);
134 WMMapWidget(saveSessionBtn);
136 parent = XCreateSimpleWindow(dpy, scr->root_win, 0, 0, 400, 180, 0, 0, 0);
138 XReparentWindow(dpy, WMWidgetXID(panel->win), parent, 0, 0);
140 center = getCenter(scr, 400, 180);
141 wwin = wManageInternalWindow(scr, parent, None, NULL, center.x, center.y, 400, 180);
143 wwin->client_leader = WMWidgetXID(panel->win);
145 WMMapWidget(panel->win);
147 wWindowMap(wwin);
149 WMRunModalLoop(WMWidgetScreen(panel->win), WMWidgetView(panel->win));
151 result = panel->result;
153 WMUnmapWidget(panel->win);
155 wUnmanageWindow(wwin, False, False);
157 WMDestroyAlertPanel(panel);
159 XDestroyWindow(dpy, parent);
161 return result;
164 typedef struct _WMInputPanelWithHistory {
165 WMInputPanel *panel;
166 WMArray *history;
167 int histpos;
168 char *prefix;
169 char *suffix;
170 char *rest;
171 WMArray *variants;
172 int varpos;
173 } WMInputPanelWithHistory;
175 static char *HistoryFileName(const char *name)
177 char *filename = NULL;
179 filename = wstrdup(wusergnusteppath());
180 filename = wstrappend(filename, "/.AppInfo/WindowMaker/History");
181 if (name && strlen(name)) {
182 filename = wstrappend(filename, ".");
183 filename = wstrappend(filename, name);
185 return filename;
188 static int strmatch(const void *str1, const void *str2)
190 return !strcmp((const char *)str1, (const char *)str2);
193 static WMArray *LoadHistory(const char *filename, int max)
195 WMPropList *plhistory;
196 WMPropList *plitem;
197 WMArray *history;
198 int i, num;
199 char *str;
201 history = WMCreateArrayWithDestructor(1, wfree);
202 WMAddToArray(history, wstrdup(""));
204 plhistory = WMReadPropListFromFile(filename);
206 if (plhistory) {
207 if (WMIsPLArray(plhistory)) {
208 num = WMGetPropListItemCount(plhistory);
210 for (i = 0; i < num; ++i) {
211 plitem = WMGetFromPLArray(plhistory, i);
212 if (WMIsPLString(plitem)) {
213 str = WMGetFromPLString(plitem);
214 if (WMFindInArray(history, strmatch, str) == WANotFound) {
216 * The string here is duplicated because it will be freed
217 * automatically when the array is deleted. This is not really
218 * great because it is already an allocated string,
219 * unfortunately we cannot re-use it because it will be freed
220 * when we discard the PL (and we don't want to waste the PL's
221 * memory either)
223 WMAddToArray(history, wstrdup(str));
224 if (--max <= 0)
225 break;
230 WMReleasePropList(plhistory);
233 return history;
236 static void SaveHistory(WMArray * history, const char *filename)
238 int i;
239 WMPropList *plhistory;
241 plhistory = WMCreatePLArray(NULL);
243 for (i = 0; i < WMGetArrayItemCount(history); ++i)
244 WMAddToPLArray(plhistory, WMCreatePLString(WMGetFromArray(history, i)));
246 WMWritePropListToFile(plhistory, filename);
247 WMReleasePropList(plhistory);
250 static int pstrcmp(const char **str1, const char **str2)
252 return strcmp(*str1, *str2);
255 static void
256 ScanFiles(const char *dir, const char *prefix, unsigned acceptmask, unsigned declinemask, WMArray * result)
258 int prefixlen;
259 DIR *d;
260 struct dirent *de;
261 struct stat sb;
262 char *fullfilename, *suffix;
264 prefixlen = strlen(prefix);
265 if ((d = opendir(dir)) != NULL) {
266 while ((de = readdir(d)) != NULL) {
267 if (strlen(de->d_name) > prefixlen &&
268 !strncmp(prefix, de->d_name, prefixlen) &&
269 strcmp(de->d_name, ".") != 0 && strcmp(de->d_name, "..")) {
270 fullfilename = wstrconcat((char *)dir, "/");
271 fullfilename = wstrappend(fullfilename, de->d_name);
273 if (stat(fullfilename, &sb) == 0 &&
274 (sb.st_mode & acceptmask) &&
275 !(sb.st_mode & declinemask) &&
276 WMFindInArray(result, (WMMatchDataProc *) strmatch,
277 de->d_name + prefixlen) == WANotFound) {
278 suffix = wstrdup(de->d_name + prefixlen);
279 if (sb.st_mode & S_IFDIR)
280 suffix = wstrappend(suffix, "/");
281 WMAddToArray(result, suffix);
283 wfree(fullfilename);
286 closedir(d);
290 static WMArray *GenerateVariants(const char *complete)
292 Bool firstWord = True;
293 WMArray *variants = NULL;
294 char *pos = NULL, *path = NULL, *tmp = NULL, *dir = NULL, *prefix = NULL;
296 variants = WMCreateArrayWithDestructor(0, wfree);
298 while (*complete == ' ')
299 ++complete;
301 if ((pos = strrchr(complete, ' ')) != NULL) {
302 complete = pos + 1;
303 firstWord = False;
306 if ((pos = strrchr(complete, '/')) != NULL) {
307 tmp = wstrndup((char *)complete, pos - complete + 1);
308 if (*tmp == '~' && *(tmp + 1) == '/' && getenv("HOME")) {
309 dir = wstrdup(getenv("HOME"));
310 dir = wstrappend(dir, tmp + 1);
311 wfree(tmp);
312 } else {
313 dir = tmp;
315 prefix = wstrdup(pos + 1);
316 ScanFiles(dir, prefix, (unsigned)-1, 0, variants);
317 wfree(dir);
318 wfree(prefix);
319 } else if (*complete == '~') {
320 WMAddToArray(variants, wstrdup("/"));
321 } else if (firstWord) {
322 path = getenv("PATH");
323 while (path) {
324 pos = strchr(path, ':');
325 if (pos) {
326 tmp = wstrndup(path, pos - path);
327 path = pos + 1;
328 } else if (*path != '\0') {
329 tmp = wstrdup(path);
330 path = NULL;
331 } else
332 break;
333 ScanFiles(tmp, complete, S_IXOTH | S_IXGRP | S_IXUSR, S_IFDIR, variants);
334 wfree(tmp);
338 WMSortArray(variants, (WMCompareDataProc *) pstrcmp);
339 return variants;
342 static void handleHistoryKeyPress(XEvent * event, void *clientData)
344 char *text;
345 unsigned pos;
346 WMInputPanelWithHistory *p = (WMInputPanelWithHistory *) clientData;
347 KeySym ksym;
349 ksym = XLookupKeysym(&event->xkey, 0);
351 switch (ksym) {
352 case XK_Up:
353 if (p->histpos < WMGetArrayItemCount(p->history) - 1) {
354 if (p->histpos == 0)
355 wfree(WMReplaceInArray(p->history, 0, WMGetTextFieldText(p->panel->text)));
356 p->histpos++;
357 WMSetTextFieldText(p->panel->text, WMGetFromArray(p->history, p->histpos));
359 break;
360 case XK_Down:
361 if (p->histpos > 0) {
362 p->histpos--;
363 WMSetTextFieldText(p->panel->text, WMGetFromArray(p->history, p->histpos));
365 break;
366 case XK_Tab:
367 if (!p->variants) {
368 text = WMGetTextFieldText(p->panel->text);
369 pos = WMGetTextFieldCursorPosition(p->panel->text);
370 p->prefix = wstrndup(text, pos);
371 p->suffix = wstrdup(text + pos);
372 wfree(text);
373 p->variants = GenerateVariants(p->prefix);
374 p->varpos = 0;
375 if (!p->variants) {
376 wfree(p->prefix);
377 wfree(p->suffix);
378 p->prefix = NULL;
379 p->suffix = NULL;
382 if (p->variants && p->prefix && p->suffix) {
383 p->varpos++;
384 if (p->varpos > WMGetArrayItemCount(p->variants))
385 p->varpos = 0;
386 if (p->varpos > 0)
387 text = wstrconcat(p->prefix, WMGetFromArray(p->variants, p->varpos - 1));
388 else
389 text = wstrdup(p->prefix);
390 pos = strlen(text);
391 text = wstrappend(text, p->suffix);
392 WMSetTextFieldText(p->panel->text, text);
393 WMSetTextFieldCursorPosition(p->panel->text, pos);
394 wfree(text);
396 break;
398 if (ksym != XK_Tab) {
399 if (p->prefix) {
400 wfree(p->prefix);
401 p->prefix = NULL;
403 if (p->suffix) {
404 wfree(p->suffix);
405 p->suffix = NULL;
407 if (p->variants) {
408 WMFreeArray(p->variants);
409 p->variants = NULL;
414 int wAdvancedInputDialog(WScreen *scr, const char *title, const char *message, const char *name, char **text)
416 WWindow *wwin;
417 Window parent;
418 char *result;
419 WMPoint center;
420 WMInputPanelWithHistory *p;
421 char *filename;
423 filename = HistoryFileName(name);
424 p = wmalloc(sizeof(WMInputPanelWithHistory));
425 p->panel = WMCreateInputPanel(scr->wmscreen, NULL, title, message, *text, _("OK"), _("Cancel"));
426 p->history = LoadHistory(filename, wPreferences.history_lines);
427 p->histpos = 0;
428 p->prefix = NULL;
429 p->suffix = NULL;
430 p->rest = NULL;
431 p->variants = NULL;
432 p->varpos = 0;
433 WMCreateEventHandler(WMWidgetView(p->panel->text), KeyPressMask, handleHistoryKeyPress, p);
435 parent = XCreateSimpleWindow(dpy, scr->root_win, 0, 0, 320, 160, 0, 0, 0);
436 XSelectInput(dpy, parent, KeyPressMask | KeyReleaseMask);
438 XReparentWindow(dpy, WMWidgetXID(p->panel->win), parent, 0, 0);
440 center = getCenter(scr, 320, 160);
441 wwin = wManageInternalWindow(scr, parent, None, NULL, center.x, center.y, 320, 160);
443 wwin->client_leader = WMWidgetXID(p->panel->win);
445 WMMapWidget(p->panel->win);
447 wWindowMap(wwin);
449 WMRunModalLoop(WMWidgetScreen(p->panel->win), WMWidgetView(p->panel->win));
451 if (p->panel->result == WAPRDefault) {
452 result = WMGetTextFieldText(p->panel->text);
453 wfree(WMReplaceInArray(p->history, 0, wstrdup(result)));
454 SaveHistory(p->history, filename);
455 } else
456 result = NULL;
458 wUnmanageWindow(wwin, False, False);
460 WMDestroyInputPanel(p->panel);
461 WMFreeArray(p->history);
462 wfree(p);
463 wfree(filename);
465 XDestroyWindow(dpy, parent);
467 if (result == NULL)
468 return False;
469 else {
470 if (*text)
471 wfree(*text);
472 *text = result;
474 return True;
478 int wInputDialog(WScreen *scr, const char *title, const char *message, char **text)
480 WWindow *wwin;
481 Window parent;
482 WMInputPanel *panel;
483 char *result;
484 WMPoint center;
486 panel = WMCreateInputPanel(scr->wmscreen, NULL, title, message, *text, _("OK"), _("Cancel"));
488 parent = XCreateSimpleWindow(dpy, scr->root_win, 0, 0, 320, 160, 0, 0, 0);
489 XSelectInput(dpy, parent, KeyPressMask | KeyReleaseMask);
491 XReparentWindow(dpy, WMWidgetXID(panel->win), parent, 0, 0);
493 center = getCenter(scr, 320, 160);
494 wwin = wManageInternalWindow(scr, parent, None, NULL, center.x, center.y, 320, 160);
496 wwin->client_leader = WMWidgetXID(panel->win);
498 WMMapWidget(panel->win);
500 wWindowMap(wwin);
502 WMRunModalLoop(WMWidgetScreen(panel->win), WMWidgetView(panel->win));
504 if (panel->result == WAPRDefault)
505 result = WMGetTextFieldText(panel->text);
506 else
507 result = NULL;
509 wUnmanageWindow(wwin, False, False);
511 WMDestroyInputPanel(panel);
513 XDestroyWindow(dpy, parent);
515 if (result == NULL)
516 return False;
517 else {
518 if (*text)
519 wfree(*text);
520 *text = result;
522 return True;
527 *****************************************************************
528 * Icon Selection Panel
529 *****************************************************************
532 typedef struct IconPanel {
534 WScreen *scr;
536 WMWindow *win;
538 WMLabel *dirLabel;
539 WMLabel *iconLabel;
541 WMList *dirList;
542 WMList *iconList;
543 WMFont *normalfont;
545 WMButton *previewButton;
547 WMLabel *iconView;
549 WMLabel *fileLabel;
550 WMTextField *fileField;
552 WMButton *okButton;
553 WMButton *cancelButton;
554 #if 0
555 WMButton *chooseButton;
556 #endif
557 short done;
558 short result;
559 short preview;
560 } IconPanel;
562 static void listPixmaps(WScreen *scr, WMList *lPtr, const char *path)
564 struct dirent *dentry;
565 DIR *dir;
566 char pbuf[PATH_MAX + 16];
567 char *apath;
568 IconPanel *panel = WMGetHangedData(lPtr);
570 panel->preview = False;
572 apath = wexpandpath(path);
573 dir = opendir(apath);
575 if (!dir) {
576 wfree(apath);
577 snprintf(pbuf, sizeof(pbuf),
578 _("Could not open directory \"%s\":\n%s"),
579 path, strerror(errno));
580 wMessageDialog(scr, _("Error"), pbuf, _("OK"), NULL, NULL);
581 return;
584 /* list contents in the column */
585 while ((dentry = readdir(dir))) {
586 struct stat statb;
588 if (strcmp(dentry->d_name, ".") == 0 || strcmp(dentry->d_name, "..") == 0)
589 continue;
591 if (wstrlcpy(pbuf, apath, sizeof(pbuf)) >= sizeof(pbuf) ||
592 wstrlcat(pbuf, "/", sizeof(pbuf)) >= sizeof(pbuf) ||
593 wstrlcat(pbuf, dentry->d_name, sizeof(pbuf)) >= sizeof(pbuf)) {
594 wwarning(_("full path for file \"%s\" in \"%s\" is longer than %ld bytes, skipped"),
595 dentry->d_name, path, sizeof(pbuf) - 1);
596 continue;
599 if (stat(pbuf, &statb) < 0)
600 continue;
602 if (statb.st_mode & (S_IRUSR | S_IRGRP | S_IROTH)
603 && statb.st_mode & (S_IFREG | S_IFLNK)) {
604 WMAddListItem(lPtr, dentry->d_name);
607 WMSortListItems(lPtr);
609 closedir(dir);
610 wfree(apath);
611 panel->preview = True;
614 static void setViewedImage(IconPanel *panel, const char *file)
616 WMPixmap *pixmap;
617 RColor color;
619 color.red = 0xae;
620 color.green = 0xaa;
621 color.blue = 0xae;
622 color.alpha = 0;
623 pixmap = WMCreateScaledBlendedPixmapFromFile(WMWidgetScreen(panel->win), file, &color, 75, 75);
625 if (!pixmap) {
626 WMSetButtonEnabled(panel->okButton, False);
628 WMSetLabelText(panel->iconView, _("Could not load image file "));
630 WMSetLabelImage(panel->iconView, NULL);
631 } else {
632 WMSetButtonEnabled(panel->okButton, True);
634 WMSetLabelText(panel->iconView, NULL);
635 WMSetLabelImage(panel->iconView, pixmap);
636 WMReleasePixmap(pixmap);
640 static void listCallback(void *self, void *data)
642 WMList *lPtr = (WMList *) self;
643 IconPanel *panel = (IconPanel *) data;
644 char *path;
646 if (lPtr == panel->dirList) {
647 WMListItem *item = WMGetListSelectedItem(lPtr);
649 if (item == NULL)
650 return;
651 path = item->text;
653 WMSetTextFieldText(panel->fileField, path);
655 WMSetLabelImage(panel->iconView, NULL);
657 WMSetButtonEnabled(panel->okButton, False);
659 WMClearList(panel->iconList);
660 listPixmaps(panel->scr, panel->iconList, path);
661 } else {
662 char *tmp, *iconFile;
663 WMListItem *item = WMGetListSelectedItem(panel->dirList);
665 if (item == NULL)
666 return;
667 path = item->text;
669 item = WMGetListSelectedItem(panel->iconList);
670 if (item == NULL)
671 return;
672 iconFile = item->text;
674 tmp = wexpandpath(path);
675 path = wmalloc(strlen(tmp) + strlen(iconFile) + 4);
676 strcpy(path, tmp);
677 strcat(path, "/");
678 strcat(path, iconFile);
679 wfree(tmp);
680 WMSetTextFieldText(panel->fileField, path);
681 setViewedImage(panel, path);
682 wfree(path);
686 static void listIconPaths(WMList * lPtr)
688 char *paths;
689 char *path;
691 paths = wstrdup(wPreferences.icon_path);
693 path = strtok(paths, ":");
695 do {
696 char *tmp;
698 tmp = wexpandpath(path);
699 /* do not sort, because the order implies the order of
700 * directories searched */
701 if (access(tmp, X_OK) == 0)
702 WMAddListItem(lPtr, path);
703 wfree(tmp);
704 } while ((path = strtok(NULL, ":")) != NULL);
706 wfree(paths);
709 static void drawIconProc(WMList * lPtr, int index, Drawable d, char *text, int state, WMRect * rect)
711 IconPanel *panel = WMGetHangedData(lPtr);
712 WScreen *scr = panel->scr;
713 GC gc = scr->draw_gc;
714 GC copygc = scr->copy_gc;
715 char *file, *dirfile;
716 WMPixmap *pixmap;
717 WMColor *back;
718 WMSize size;
719 WMScreen *wmscr = WMWidgetScreen(panel->win);
720 RColor color;
721 int x, y, width, height, len;
723 /* Parameter not used, but tell the compiler that it is ok */
724 (void) index;
726 if (!panel->preview)
727 return;
729 x = rect->pos.x;
730 y = rect->pos.y;
731 width = rect->size.width;
732 height = rect->size.height;
734 back = (state & WLDSSelected) ? scr->white : scr->gray;
736 dirfile = wexpandpath(WMGetListSelectedItem(panel->dirList)->text);
737 len = strlen(dirfile) + strlen(text) + 4;
738 file = wmalloc(len);
739 snprintf(file, len, "%s/%s", dirfile, text);
740 wfree(dirfile);
742 color.red = WMRedComponentOfColor(back) >> 8;
743 color.green = WMGreenComponentOfColor(back) >> 8;
744 color.blue = WMBlueComponentOfColor(back) >> 8;
745 color.alpha = WMGetColorAlpha(back) >> 8;
747 pixmap = WMCreateScaledBlendedPixmapFromFile(wmscr, file, &color, width - 2, height - 2);
748 wfree(file);
750 if (!pixmap) {
751 /*WMRemoveListItem(lPtr, index); */
752 return;
755 XFillRectangle(dpy, d, WMColorGC(back), x, y, width, height);
757 XSetClipMask(dpy, gc, None);
758 /*XDrawRectangle(dpy, d, WMColorGC(white), x+5, y+5, width-10, 54); */
759 XDrawLine(dpy, d, WMColorGC(scr->white), x, y + height - 1, x + width, y + height - 1);
761 size = WMGetPixmapSize(pixmap);
763 XSetClipMask(dpy, copygc, WMGetPixmapMaskXID(pixmap));
764 XSetClipOrigin(dpy, copygc, x + (width - size.width) / 2, y + 2);
765 XCopyArea(dpy, WMGetPixmapXID(pixmap), d, copygc, 0, 0,
766 size.width > 100 ? 100 : size.width, size.height > 64 ? 64 : size.height,
767 x + (width - size.width) / 2, y + 2);
770 int i, j;
771 int fheight = WMFontHeight(panel->normalfont);
772 int tlen = strlen(text);
773 int twidth = WMWidthOfString(panel->normalfont, text, tlen);
774 int ofx, ofy;
776 ofx = x + (width - twidth) / 2;
777 ofy = y + 64 - fheight;
779 for (i = -1; i < 2; i++)
780 for (j = -1; j < 2; j++)
781 WMDrawString(wmscr, d, scr->white, panel->normalfont,
782 ofx + i, ofy + j, text, tlen);
784 WMDrawString(wmscr, d, scr->black, panel->normalfont, ofx, ofy, text, tlen);
787 WMReleasePixmap(pixmap);
788 /* I hope it is better to do not use cache / on my box it is fast nuff */
789 XFlush(dpy);
792 static void buttonCallback(void *self, void *clientData)
794 WMButton *bPtr = (WMButton *) self;
795 IconPanel *panel = (IconPanel *) clientData;
797 if (bPtr == panel->okButton) {
798 panel->done = True;
799 panel->result = True;
800 } else if (bPtr == panel->cancelButton) {
801 panel->done = True;
802 panel->result = False;
803 } else if (bPtr == panel->previewButton) {
804 /**** Previewer ****/
805 WMSetButtonEnabled(bPtr, False);
806 WMSetListUserDrawItemHeight(panel->iconList, 68);
807 WMSetListUserDrawProc(panel->iconList, drawIconProc);
808 WMRedisplayWidget(panel->iconList);
809 /* for draw proc to access screen/gc */
810 /*** end preview ***/
812 #if 0
813 else if (bPtr == panel->chooseButton) {
814 WMOpenPanel *op;
816 op = WMCreateOpenPanel(WMWidgetScreen(bPtr));
818 if (WMRunModalFilePanelForDirectory(op, NULL, "/usr/local", NULL, NULL)) {
819 char *path;
820 path = WMGetFilePanelFile(op);
821 WMSetTextFieldText(panel->fileField, path);
822 setViewedImage(panel, path);
823 wfree(path);
825 WMDestroyFilePanel(op);
827 #endif
830 static void keyPressHandler(XEvent * event, void *data)
832 IconPanel *panel = (IconPanel *) data;
833 char buffer[32];
834 KeySym ksym;
835 int iidx;
836 int didx;
837 int item = 0;
838 WMList *list = NULL;
840 if (event->type == KeyRelease)
841 return;
843 buffer[0] = 0;
844 XLookupString(&event->xkey, buffer, sizeof(buffer), &ksym, NULL);
846 iidx = WMGetListSelectedItemRow(panel->iconList);
847 didx = WMGetListSelectedItemRow(panel->dirList);
849 switch (ksym) {
850 case XK_Up:
851 if (iidx > 0)
852 item = iidx - 1;
853 else
854 item = iidx;
855 list = panel->iconList;
856 break;
857 case XK_Down:
858 if (iidx < WMGetListNumberOfRows(panel->iconList) - 1)
859 item = iidx + 1;
860 else
861 item = iidx;
862 list = panel->iconList;
863 break;
864 case XK_Home:
865 item = 0;
866 list = panel->iconList;
867 break;
868 case XK_End:
869 item = WMGetListNumberOfRows(panel->iconList) - 1;
870 list = panel->iconList;
871 break;
872 case XK_Next:
873 if (didx < WMGetListNumberOfRows(panel->dirList) - 1)
874 item = didx + 1;
875 else
876 item = didx;
877 list = panel->dirList;
878 break;
879 case XK_Prior:
880 if (didx > 0)
881 item = didx - 1;
882 else
883 item = 0;
884 list = panel->dirList;
885 break;
886 case XK_Return:
887 WMPerformButtonClick(panel->okButton);
888 break;
889 case XK_Escape:
890 WMPerformButtonClick(panel->cancelButton);
891 break;
894 if (list) {
895 WMSelectListItem(list, item);
896 WMSetListPosition(list, item - 5);
897 listCallback(list, panel);
901 Bool wIconChooserDialog(WScreen *scr, char **file, const char *instance, const char *class)
903 WWindow *wwin;
904 Window parent;
905 IconPanel *panel;
906 WMColor *color;
907 WMFont *boldFont;
908 Bool result;
910 panel = wmalloc(sizeof(IconPanel));
912 panel->scr = scr;
914 panel->win = WMCreateWindow(scr->wmscreen, "iconChooser");
915 WMResizeWidget(panel->win, 450, 280);
917 WMCreateEventHandler(WMWidgetView(panel->win), KeyPressMask | KeyReleaseMask, keyPressHandler, panel);
919 boldFont = WMBoldSystemFontOfSize(scr->wmscreen, 12);
920 panel->normalfont = WMSystemFontOfSize(WMWidgetScreen(panel->win), 12);
922 panel->dirLabel = WMCreateLabel(panel->win);
923 WMResizeWidget(panel->dirLabel, 200, 20);
924 WMMoveWidget(panel->dirLabel, 10, 7);
925 WMSetLabelText(panel->dirLabel, _("Directories"));
926 WMSetLabelFont(panel->dirLabel, boldFont);
927 WMSetLabelTextAlignment(panel->dirLabel, WACenter);
929 WMSetLabelRelief(panel->dirLabel, WRSunken);
931 panel->iconLabel = WMCreateLabel(panel->win);
932 WMResizeWidget(panel->iconLabel, 140, 20);
933 WMMoveWidget(panel->iconLabel, 215, 7);
934 WMSetLabelText(panel->iconLabel, _("Icons"));
935 WMSetLabelFont(panel->iconLabel, boldFont);
936 WMSetLabelTextAlignment(panel->iconLabel, WACenter);
938 WMReleaseFont(boldFont);
940 color = WMWhiteColor(scr->wmscreen);
941 WMSetLabelTextColor(panel->dirLabel, color);
942 WMSetLabelTextColor(panel->iconLabel, color);
943 WMReleaseColor(color);
945 color = WMDarkGrayColor(scr->wmscreen);
946 WMSetWidgetBackgroundColor(panel->iconLabel, color);
947 WMSetWidgetBackgroundColor(panel->dirLabel, color);
948 WMReleaseColor(color);
950 WMSetLabelRelief(panel->iconLabel, WRSunken);
952 panel->dirList = WMCreateList(panel->win);
953 WMResizeWidget(panel->dirList, 200, 170);
954 WMMoveWidget(panel->dirList, 10, 30);
955 WMSetListAction(panel->dirList, listCallback, panel);
957 panel->iconList = WMCreateList(panel->win);
958 WMResizeWidget(panel->iconList, 140, 170);
959 WMMoveWidget(panel->iconList, 215, 30);
960 WMSetListAction(panel->iconList, listCallback, panel);
962 WMHangData(panel->iconList, panel);
964 panel->previewButton = WMCreateCommandButton(panel->win);
965 WMResizeWidget(panel->previewButton, 75, 26);
966 WMMoveWidget(panel->previewButton, 365, 130);
967 WMSetButtonText(panel->previewButton, _("Preview"));
968 WMSetButtonAction(panel->previewButton, buttonCallback, panel);
970 panel->iconView = WMCreateLabel(panel->win);
971 WMResizeWidget(panel->iconView, 75, 75);
972 WMMoveWidget(panel->iconView, 365, 40);
973 WMSetLabelImagePosition(panel->iconView, WIPOverlaps);
974 WMSetLabelRelief(panel->iconView, WRSunken);
975 WMSetLabelTextAlignment(panel->iconView, WACenter);
977 panel->fileLabel = WMCreateLabel(panel->win);
978 WMResizeWidget(panel->fileLabel, 80, 20);
979 WMMoveWidget(panel->fileLabel, 10, 210);
980 WMSetLabelText(panel->fileLabel, _("File Name:"));
982 panel->fileField = WMCreateTextField(panel->win);
983 WMSetViewNextResponder(WMWidgetView(panel->fileField), WMWidgetView(panel->win));
984 WMResizeWidget(panel->fileField, 345, 20);
985 WMMoveWidget(panel->fileField, 95, 210);
986 WMSetTextFieldEditable(panel->fileField, False);
988 panel->okButton = WMCreateCommandButton(panel->win);
989 WMResizeWidget(panel->okButton, 80, 26);
990 WMMoveWidget(panel->okButton, 360, 240);
991 WMSetButtonText(panel->okButton, _("OK"));
992 WMSetButtonEnabled(panel->okButton, False);
993 WMSetButtonAction(panel->okButton, buttonCallback, panel);
995 panel->cancelButton = WMCreateCommandButton(panel->win);
996 WMResizeWidget(panel->cancelButton, 80, 26);
997 WMMoveWidget(panel->cancelButton, 270, 240);
998 WMSetButtonText(panel->cancelButton, _("Cancel"));
999 WMSetButtonAction(panel->cancelButton, buttonCallback, panel);
1000 #if 0
1001 panel->chooseButton = WMCreateCommandButton(panel->win);
1002 WMResizeWidget(panel->chooseButton, 110, 26);
1003 WMMoveWidget(panel->chooseButton, 150, 240);
1004 WMSetButtonText(panel->chooseButton, _("Choose File"));
1005 WMSetButtonAction(panel->chooseButton, buttonCallback, panel);
1006 #endif
1007 WMRealizeWidget(panel->win);
1008 WMMapSubwidgets(panel->win);
1010 parent = XCreateSimpleWindow(dpy, scr->root_win, 0, 0, 450, 280, 0, 0, 0);
1012 XReparentWindow(dpy, WMWidgetXID(panel->win), parent, 0, 0);
1015 static const char *prefix = NULL;
1016 char *title;
1017 int len;
1018 WMPoint center;
1020 if (prefix == NULL)
1021 prefix = _("Icon Chooser");
1023 len = strlen(prefix)
1024 + 2 // " ["
1025 + (instance ? strlen(instance) : 0)
1026 + 1 // "."
1027 + (class ? strlen(class) : 0)
1028 + 1 // "]"
1029 + 1; // final NUL
1031 title = wmalloc(len);
1032 strcpy(title, prefix);
1034 if (instance || class) {
1035 strcat(title, " [");
1036 if (instance != NULL)
1037 strcat(title, instance);
1038 if (instance && class)
1039 strcat(title, ".");
1040 if (class != NULL)
1041 strcat(title, class);
1042 strcat(title, "]");
1045 center = getCenter(scr, 450, 280);
1047 wwin = wManageInternalWindow(scr, parent, None, title, center.x, center.y, 450, 280);
1048 wfree(title);
1051 /* put icon paths in the list */
1052 listIconPaths(panel->dirList);
1054 WMMapWidget(panel->win);
1056 wWindowMap(wwin);
1058 while (!panel->done) {
1059 XEvent event;
1061 WMNextEvent(dpy, &event);
1062 WMHandleEvent(&event);
1065 if (panel->result) {
1066 char *defaultPath, *wantedPath;
1068 /* check if the file the user selected is not the one that
1069 * would be loaded by default with the current search path */
1070 *file = WMGetListSelectedItem(panel->iconList)->text;
1071 if (**file == 0) {
1072 wfree(*file);
1073 *file = NULL;
1074 } else {
1075 defaultPath = FindImage(wPreferences.icon_path, *file);
1076 wantedPath = WMGetTextFieldText(panel->fileField);
1077 /* if the file is not the default, use full path */
1078 if (strcmp(wantedPath, defaultPath) != 0) {
1079 *file = wantedPath;
1080 } else {
1081 *file = wstrdup(*file);
1082 wfree(wantedPath);
1084 wfree(defaultPath);
1086 } else {
1087 *file = NULL;
1090 result = panel->result;
1092 WMReleaseFont(panel->normalfont);
1094 WMUnmapWidget(panel->win);
1096 WMDestroyWidget(panel->win);
1098 wUnmanageWindow(wwin, False, False);
1100 wfree(panel);
1102 XDestroyWindow(dpy, parent);
1104 return result;
1108 ***********************************************************************
1109 * Info Panel
1110 ***********************************************************************
1113 typedef struct {
1114 WScreen *scr;
1115 WWindow *wwin;
1116 WMWindow *win;
1117 WMLabel *logoL;
1118 WMLabel *name1L;
1119 WMFrame *lineF;
1120 WMLabel *name2L;
1121 WMLabel *versionL;
1122 WMLabel *infoL;
1123 WMLabel *copyrL;
1124 } InfoPanel;
1126 #define COPYRIGHT_TEXT \
1127 "Copyright \xc2\xa9 1997-2006 Alfredo K. Kojima\n"\
1128 "Copyright \xc2\xa9 1998-2006 Dan Pascu\n"\
1129 "Copyright \xc2\xa9 2013-2014 Window Maker Developers Team"
1131 static InfoPanel *infoPanel = NULL;
1133 static void destroyInfoPanel(WCoreWindow *foo, void *data, XEvent *event)
1135 /* Parameter not used, but tell the compiler that it is ok */
1136 (void) foo;
1137 (void) data;
1138 (void) event;
1140 WMUnmapWidget(infoPanel);
1141 wUnmanageWindow(infoPanel->wwin, False, False);
1142 WMDestroyWidget(infoPanel->win);
1143 wfree(infoPanel);
1144 infoPanel = NULL;
1147 void wShowInfoPanel(WScreen *scr)
1149 const int win_width = 382;
1150 const int win_height = 250;
1151 InfoPanel *panel;
1152 WMPixmap *logo;
1153 WMFont *font;
1154 char *name, *strbuf = NULL;
1155 const char *separator;
1156 char buffer[256];
1157 Window parent;
1158 WWindow *wwin;
1159 WMPoint center;
1160 char **strl;
1161 int i, width = 50, sepHeight;
1162 char *visuals[] = {
1163 "StaticGray",
1164 "GrayScale",
1165 "StaticColor",
1166 "PseudoColor",
1167 "TrueColor",
1168 "DirectColor"
1171 if (infoPanel) {
1172 if (infoPanel->scr == scr) {
1173 wRaiseFrame(infoPanel->wwin->frame->core);
1174 wSetFocusTo(scr, infoPanel->wwin);
1176 return;
1179 panel = wmalloc(sizeof(InfoPanel));
1181 panel->scr = scr;
1183 panel->win = WMCreateWindow(scr->wmscreen, "info");
1184 WMResizeWidget(panel->win, win_width, win_height);
1186 logo = WMCreateApplicationIconBlendedPixmap(scr->wmscreen, (RColor *) NULL);
1187 if (!logo) {
1188 logo = WMRetainPixmap(WMGetApplicationIconPixmap(scr->wmscreen));
1190 if (logo) {
1191 panel->logoL = WMCreateLabel(panel->win);
1192 WMResizeWidget(panel->logoL, 64, 64);
1193 WMMoveWidget(panel->logoL, 30, 20);
1194 WMSetLabelImagePosition(panel->logoL, WIPImageOnly);
1195 WMSetLabelImage(panel->logoL, logo);
1196 WMReleasePixmap(logo);
1199 sepHeight = 3;
1200 panel->name1L = WMCreateLabel(panel->win);
1201 WMResizeWidget(panel->name1L, 240, 30 + 2);
1202 WMMoveWidget(panel->name1L, 100, 30 - 2 - sepHeight);
1204 name = "Lucida Sans,Comic Sans MS,URW Gothic L,Trebuchet MS" ":italic:pixelsize=28:antialias=true";
1205 font = WMCreateFont(scr->wmscreen, name);
1206 strbuf = "Window Maker";
1207 if (font) {
1208 width = WMWidthOfString(font, strbuf, strlen(strbuf));
1209 WMSetLabelFont(panel->name1L, font);
1210 WMReleaseFont(font);
1212 WMSetLabelTextAlignment(panel->name1L, WACenter);
1213 WMSetLabelText(panel->name1L, strbuf);
1215 panel->lineF = WMCreateFrame(panel->win);
1216 WMResizeWidget(panel->lineF, width, sepHeight);
1217 WMMoveWidget(panel->lineF, 100 + (240 - width) / 2, 60 - sepHeight);
1218 WMSetFrameRelief(panel->lineF, WRSimple);
1219 WMSetWidgetBackgroundColor(panel->lineF, scr->black);
1221 panel->name2L = WMCreateLabel(panel->win);
1222 WMResizeWidget(panel->name2L, 240, 24);
1223 WMMoveWidget(panel->name2L, 100, 60);
1224 name = "URW Gothic L,Nimbus Sans L:pixelsize=16:antialias=true";
1225 font = WMCreateFont(scr->wmscreen, name);
1226 if (font) {
1227 WMSetLabelFont(panel->name2L, font);
1228 WMReleaseFont(font);
1229 font = NULL;
1231 WMSetLabelTextAlignment(panel->name2L, WACenter);
1232 WMSetLabelText(panel->name2L, _("Window Manager for X"));
1234 snprintf(buffer, sizeof(buffer), _("Version %s"), VERSION);
1235 panel->versionL = WMCreateLabel(panel->win);
1236 WMResizeWidget(panel->versionL, 310, 16);
1237 WMMoveWidget(panel->versionL, 30, 95);
1238 WMSetLabelTextAlignment(panel->versionL, WARight);
1239 WMSetLabelText(panel->versionL, buffer);
1240 WMSetLabelWraps(panel->versionL, False);
1242 panel->copyrL = WMCreateLabel(panel->win);
1243 WMResizeWidget(panel->copyrL, 360, 60);
1244 WMMoveWidget(panel->copyrL, 15, 190);
1245 WMSetLabelTextAlignment(panel->copyrL, WALeft);
1246 WMSetLabelText(panel->copyrL, COPYRIGHT_TEXT);
1247 font = WMSystemFontOfSize(scr->wmscreen, 11);
1248 if (font) {
1249 WMSetLabelFont(panel->copyrL, font);
1250 WMReleaseFont(font);
1251 font = NULL;
1254 strbuf = NULL;
1255 snprintf(buffer, sizeof(buffer), _("Using visual 0x%x: %s %ibpp "),
1256 (unsigned)scr->w_visual->visualid, visuals[scr->w_visual->class], scr->w_depth);
1258 strbuf = wstrappend(strbuf, buffer);
1260 switch (scr->w_depth) {
1261 case 15:
1262 strbuf = wstrappend(strbuf, _("(32 thousand colors)\n"));
1263 break;
1264 case 16:
1265 strbuf = wstrappend(strbuf, _("(64 thousand colors)\n"));
1266 break;
1267 case 24:
1268 case 32:
1269 strbuf = wstrappend(strbuf, _("(16 million colors)\n"));
1270 break;
1271 default:
1272 snprintf(buffer, sizeof(buffer), _("(%d colors)\n"), 1 << scr->w_depth);
1273 strbuf = wstrappend(strbuf, buffer);
1274 break;
1277 #if defined(HAVE_MALLOC_H) && defined(HAVE_MALLINFO)
1279 struct mallinfo ma = mallinfo();
1280 snprintf(buffer, sizeof(buffer),
1281 #ifdef DEBUG
1282 _("Total memory allocated: %i kB (in use: %i kB, %d free chunks).\n"),
1283 #else
1284 _("Total memory allocated: %i kB (in use: %i kB).\n"),
1285 #endif
1286 (ma.arena + ma.hblkhd) / 1024,
1287 (ma.uordblks + ma.hblkhd) / 1024
1288 #ifdef DEBUG
1290 * This information is representative of the memory
1291 * fragmentation. In ideal case it should be 1, but
1292 * that is never possible
1294 , ma.ordblks
1295 #endif
1298 strbuf = wstrappend(strbuf, buffer);
1300 #endif
1302 strbuf = wstrappend(strbuf, _("Image formats: "));
1303 strl = RSupportedFileFormats();
1304 separator = NULL;
1305 for (i = 0; strl[i] != NULL; i++) {
1306 if (separator != NULL)
1307 strbuf = wstrappend(strbuf, separator);
1308 strbuf = wstrappend(strbuf, strl[i]);
1309 separator = ", ";
1312 strbuf = wstrappend(strbuf, _("\nAdditional support for: "));
1313 strbuf = wstrappend(strbuf, "WMSPEC");
1315 #ifdef MWM_HINTS
1316 strbuf = wstrappend(strbuf, ", MWM");
1317 #endif
1319 #ifdef XDND
1320 strbuf = wstrappend(strbuf, ", XDnD");
1321 #endif
1323 #ifdef USE_MAGICK
1324 strbuf = wstrappend(strbuf, ", ImageMagick");
1325 #endif
1327 #ifdef USE_XINERAMA
1328 strbuf = wstrappend(strbuf, _("\n"));
1329 #ifdef SOLARIS_XINERAMA
1330 strbuf = wstrappend(strbuf, _("Solaris "));
1331 #endif
1332 strbuf = wstrappend(strbuf, _("Xinerama: "));
1334 char tmp[128];
1335 snprintf(tmp, sizeof(tmp) - 1, _("%d head(s) found."), scr->xine_info.count);
1336 strbuf = wstrappend(strbuf, tmp);
1338 #endif
1340 #ifdef USE_RANDR
1341 strbuf = wstrappend(strbuf, _("\n"));
1342 strbuf = wstrappend(strbuf, "RandR: ");
1343 if (w_global.xext.randr.supported)
1344 strbuf = wstrappend(strbuf, _("supported"));
1345 else
1346 strbuf = wstrappend(strbuf, _("unsupported"));
1347 strbuf = wstrappend(strbuf, ".");
1348 #endif
1350 panel->infoL = WMCreateLabel(panel->win);
1351 WMResizeWidget(panel->infoL, 350, 80);
1352 WMMoveWidget(panel->infoL, 15, 115);
1353 WMSetLabelText(panel->infoL, strbuf);
1354 font = WMSystemFontOfSize(scr->wmscreen, 11);
1355 if (font) {
1356 WMSetLabelFont(panel->infoL, font);
1357 WMReleaseFont(font);
1358 font = NULL;
1360 wfree(strbuf);
1362 WMRealizeWidget(panel->win);
1363 WMMapSubwidgets(panel->win);
1365 parent = XCreateSimpleWindow(dpy, scr->root_win, 0, 0, win_width, win_height, 0, 0, 0);
1367 XReparentWindow(dpy, WMWidgetXID(panel->win), parent, 0, 0);
1369 WMMapWidget(panel->win);
1371 center = getCenter(scr, win_width, win_height);
1372 wwin = wManageInternalWindow(scr, parent, None, _("Info"), center.x, center.y, win_width, win_height);
1374 WSETUFLAG(wwin, no_closable, 0);
1375 WSETUFLAG(wwin, no_close_button, 0);
1376 #ifdef XKB_BUTTON_HINT
1377 wFrameWindowHideButton(wwin->frame, WFF_LANGUAGE_BUTTON);
1378 #endif
1379 wWindowUpdateButtonImages(wwin);
1380 wFrameWindowShowButton(wwin->frame, WFF_RIGHT_BUTTON);
1381 wwin->frame->on_click_right = destroyInfoPanel;
1383 wWindowMap(wwin);
1385 panel->wwin = wwin;
1386 infoPanel = panel;
1390 ***********************************************************************
1391 * Legal Panel
1392 ***********************************************************************
1395 typedef struct {
1396 WScreen *scr;
1397 WWindow *wwin;
1398 WMWindow *win;
1399 WMLabel *licenseL;
1400 } LegalPanel;
1402 static LegalPanel *legalPanel = NULL;
1404 static void destroyLegalPanel(WCoreWindow * foo, void *data, XEvent * event)
1406 /* Parameter not used, but tell the compiler that it is ok */
1407 (void) foo;
1408 (void) data;
1409 (void) event;
1411 WMUnmapWidget(legalPanel->win);
1412 WMDestroyWidget(legalPanel->win);
1413 wUnmanageWindow(legalPanel->wwin, False, False);
1414 wfree(legalPanel);
1415 legalPanel = NULL;
1418 void wShowLegalPanel(WScreen *scr)
1420 const int win_width = 420;
1421 const int win_height = 250;
1422 const int margin = 10;
1423 LegalPanel *panel;
1424 Window parent;
1425 WWindow *wwin;
1426 WMPoint center;
1428 if (legalPanel) {
1429 if (legalPanel->scr == scr) {
1430 wRaiseFrame(legalPanel->wwin->frame->core);
1431 wSetFocusTo(scr, legalPanel->wwin);
1433 return;
1436 panel = wmalloc(sizeof(LegalPanel));
1437 panel->scr = scr;
1438 panel->win = WMCreateWindow(scr->wmscreen, "legal");
1439 WMResizeWidget(panel->win, win_width, win_height);
1441 panel->licenseL = WMCreateLabel(panel->win);
1442 WMSetLabelWraps(panel->licenseL, True);
1443 WMResizeWidget(panel->licenseL, win_width - (2 * margin), win_height - (2 * margin));
1444 WMMoveWidget(panel->licenseL, margin, margin);
1445 WMSetLabelTextAlignment(panel->licenseL, WALeft);
1446 WMSetLabelText(panel->licenseL,
1447 _(" Window Maker is free software; you can redistribute it and/or "
1448 "modify it under the terms of the GNU General Public License as "
1449 "published by the Free Software Foundation; either version 2 of the "
1450 "License, or (at your option) any later version.\n\n"
1451 " Window Maker is distributed in the hope that it will be useful, "
1452 "but WITHOUT ANY WARRANTY; without even the implied warranty "
1453 "of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. "
1454 "See the GNU General Public License for more details.\n\n"
1455 " You should have received a copy of the GNU General Public "
1456 "License along with this program; if not, write to the Free Software "
1457 "Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA"
1458 "02110-1301 USA."));
1459 WMSetLabelRelief(panel->licenseL, WRGroove);
1461 WMRealizeWidget(panel->win);
1462 WMMapSubwidgets(panel->win);
1464 parent = XCreateSimpleWindow(dpy, scr->root_win, 0, 0, win_width, win_height, 0, 0, 0);
1465 XReparentWindow(dpy, WMWidgetXID(panel->win), parent, 0, 0);
1466 center = getCenter(scr, win_width, win_height);
1467 wwin = wManageInternalWindow(scr, parent, None, _("Legal"), center.x, center.y, win_width, win_height);
1469 WSETUFLAG(wwin, no_closable, 0);
1470 WSETUFLAG(wwin, no_close_button, 0);
1471 wWindowUpdateButtonImages(wwin);
1472 wFrameWindowShowButton(wwin->frame, WFF_RIGHT_BUTTON);
1473 #ifdef XKB_BUTTON_HINT
1474 wFrameWindowHideButton(wwin->frame, WFF_LANGUAGE_BUTTON);
1475 #endif
1476 wwin->frame->on_click_right = destroyLegalPanel;
1477 panel->wwin = wwin;
1479 WMMapWidget(panel->win);
1480 wWindowMap(wwin);
1481 legalPanel = panel;
1485 ***********************************************************************
1486 * Crashing Dialog Panel
1487 ***********************************************************************
1490 typedef struct _CrashPanel {
1491 WMWindow *win; /* main window */
1493 WMLabel *iconL; /* application icon */
1494 WMLabel *nameL; /* title of panel */
1496 WMFrame *sepF; /* separator frame */
1498 WMLabel *noteL; /* Title of note */
1499 WMLabel *note2L; /* body of note with what happened */
1501 WMFrame *whatF; /* "what to do next" frame */
1502 WMPopUpButton *whatP; /* action selection popup button */
1504 WMButton *okB; /* ok button */
1506 Bool done; /* if finished with this dialog */
1507 int action; /* what to do after */
1509 KeyCode retKey;
1511 } CrashPanel;
1513 static void handleKeyPress(XEvent * event, void *clientData)
1515 CrashPanel *panel = (CrashPanel *) clientData;
1517 if (event->xkey.keycode == panel->retKey) {
1518 WMPerformButtonClick(panel->okB);
1522 static void okButtonCallback(void *self, void *clientData)
1524 CrashPanel *panel = (CrashPanel *) clientData;
1526 /* Parameter not used, but tell the compiler that it is ok */
1527 (void) self;
1529 panel->done = True;
1532 static void setCrashAction(void *self, void *clientData)
1534 WMPopUpButton *pop = (WMPopUpButton *) self;
1535 CrashPanel *panel = (CrashPanel *) clientData;
1537 panel->action = WMGetPopUpButtonSelectedItem(pop);
1540 /* Make this read the logo from a compiled in pixmap -Dan */
1541 static WMPixmap *getWindowMakerIconImage(WMScreen *scr)
1543 WMPixmap *pix = NULL;
1544 char *path = NULL;
1546 /* Get the Logo icon, without the default icon */
1547 path = get_icon_filename("Logo", "WMPanel", NULL, False);
1549 if (path) {
1550 RColor gray;
1552 gray.red = 0xae;
1553 gray.green = 0xaa;
1554 gray.blue = 0xae;
1555 gray.alpha = 0;
1557 pix = WMCreateBlendedPixmapFromFile(scr, path, &gray);
1558 wfree(path);
1561 return pix;
1564 #define PWIDTH 295
1565 #define PHEIGHT 345
1567 int wShowCrashingDialogPanel(int whatSig)
1569 CrashPanel *panel;
1570 WMScreen *scr;
1571 WMFont *font;
1572 WMPixmap *logo;
1573 int screen_no, scr_width, scr_height;
1574 int action;
1575 char buf[256];
1577 screen_no = DefaultScreen(dpy);
1578 scr_width = WidthOfScreen(ScreenOfDisplay(dpy, screen_no));
1579 scr_height = HeightOfScreen(ScreenOfDisplay(dpy, screen_no));
1581 scr = WMCreateScreen(dpy, screen_no);
1582 if (!scr) {
1583 werror(_("cannot open connection for crashing dialog panel. Aborting."));
1584 return WMAbort;
1587 panel = wmalloc(sizeof(CrashPanel));
1589 panel->retKey = XKeysymToKeycode(dpy, XK_Return);
1591 panel->win = WMCreateWindow(scr, "crashingDialog");
1592 WMResizeWidget(panel->win, PWIDTH, PHEIGHT);
1593 WMMoveWidget(panel->win, (scr_width - PWIDTH) / 2, (scr_height - PHEIGHT) / 2);
1595 logo = getWindowMakerIconImage(scr);
1596 if (logo) {
1597 panel->iconL = WMCreateLabel(panel->win);
1598 WMResizeWidget(panel->iconL, 64, 64);
1599 WMMoveWidget(panel->iconL, 10, 10);
1600 WMSetLabelImagePosition(panel->iconL, WIPImageOnly);
1601 WMSetLabelImage(panel->iconL, logo);
1604 panel->nameL = WMCreateLabel(panel->win);
1605 WMResizeWidget(panel->nameL, 200, 30);
1606 WMMoveWidget(panel->nameL, 80, 25);
1607 WMSetLabelTextAlignment(panel->nameL, WALeft);
1608 font = WMBoldSystemFontOfSize(scr, 24);
1609 WMSetLabelFont(panel->nameL, font);
1610 WMReleaseFont(font);
1611 WMSetLabelText(panel->nameL, _("Fatal error"));
1613 panel->sepF = WMCreateFrame(panel->win);
1614 WMResizeWidget(panel->sepF, PWIDTH + 4, 2);
1615 WMMoveWidget(panel->sepF, -2, 80);
1617 panel->noteL = WMCreateLabel(panel->win);
1618 WMResizeWidget(panel->noteL, PWIDTH - 20, 40);
1619 WMMoveWidget(panel->noteL, 10, 90);
1620 WMSetLabelTextAlignment(panel->noteL, WAJustified);
1621 snprintf(buf, sizeof(buf), _("Window Maker received signal %i."), whatSig);
1622 WMSetLabelText(panel->noteL, buf);
1624 panel->note2L = WMCreateLabel(panel->win);
1625 WMResizeWidget(panel->note2L, PWIDTH - 20, 100);
1626 WMMoveWidget(panel->note2L, 10, 130);
1627 WMSetLabelTextAlignment(panel->note2L, WALeft);
1628 WMSetLabelText(panel->note2L,
1629 _(" This fatal error occured probably due to a bug."
1630 " Please fill the included BUGFORM and " "report it to bugs@windowmaker.info."));
1631 WMSetLabelWraps(panel->note2L, True);
1633 panel->whatF = WMCreateFrame(panel->win);
1634 WMResizeWidget(panel->whatF, PWIDTH - 20, 50);
1635 WMMoveWidget(panel->whatF, 10, 240);
1636 WMSetFrameTitle(panel->whatF, _("What do you want to do now?"));
1638 panel->whatP = WMCreatePopUpButton(panel->whatF);
1639 WMResizeWidget(panel->whatP, PWIDTH - 20 - 70, 20);
1640 WMMoveWidget(panel->whatP, 35, 20);
1641 WMSetPopUpButtonPullsDown(panel->whatP, False);
1642 WMSetPopUpButtonText(panel->whatP, _("Select action"));
1643 WMAddPopUpButtonItem(panel->whatP, _("Abort and leave a core file"));
1644 WMAddPopUpButtonItem(panel->whatP, _("Restart Window Maker"));
1645 WMAddPopUpButtonItem(panel->whatP, _("Start alternate window manager"));
1646 WMSetPopUpButtonAction(panel->whatP, setCrashAction, panel);
1647 WMSetPopUpButtonSelectedItem(panel->whatP, WMRestart);
1648 panel->action = WMRestart;
1650 WMMapSubwidgets(panel->whatF);
1652 panel->okB = WMCreateCommandButton(panel->win);
1653 WMResizeWidget(panel->okB, 80, 26);
1654 WMMoveWidget(panel->okB, 205, 309);
1655 WMSetButtonText(panel->okB, _("OK"));
1656 WMSetButtonImage(panel->okB, WMGetSystemPixmap(scr, WSIReturnArrow));
1657 WMSetButtonAltImage(panel->okB, WMGetSystemPixmap(scr, WSIHighlightedReturnArrow));
1658 WMSetButtonImagePosition(panel->okB, WIPRight);
1659 WMSetButtonAction(panel->okB, okButtonCallback, panel);
1661 panel->done = 0;
1663 WMCreateEventHandler(WMWidgetView(panel->win), KeyPressMask, handleKeyPress, panel);
1665 WMRealizeWidget(panel->win);
1666 WMMapSubwidgets(panel->win);
1668 WMMapWidget(panel->win);
1670 XSetInputFocus(dpy, WMWidgetXID(panel->win), RevertToParent, CurrentTime);
1672 while (!panel->done) {
1673 XEvent event;
1675 WMNextEvent(dpy, &event);
1676 WMHandleEvent(&event);
1679 action = panel->action;
1681 WMUnmapWidget(panel->win);
1682 WMDestroyWidget(panel->win);
1683 wfree(panel);
1685 return action;