Change to the linux kernel coding style
[wmaker-crm.git] / src / dialog.c
1 /* dialog.c - dialog windows for internal use
2  *
3  *  Window Maker window manager
4  *
5  *  Copyright (c) 1997-2003 Alfredo K. Kojima
6  *  Copyright (c) 1998-2003 Dan Pascu
7  *
8  *  This program is free software; you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License as published by
10  *  the Free Software Foundation; either version 2 of the License, or
11  *  (at your option) any later version.
12  *
13  *  This program is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *  GNU General Public License for more details.
17  *
18  *  You should have received a copy of the GNU General Public License
19  *  along with this program; if not, write to the Free Software
20  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
21  *  USA.
22  */
23
24 #include "wconfig.h"
25
26 #include <X11/Xlib.h>
27 #include <X11/Xutil.h>
28 #include <X11/keysym.h>
29
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
39 #ifdef HAVE_MALLOC_H
40 #include <malloc.h>
41 #endif
42
43 #include <signal.h>
44 #ifdef __FreeBSD__
45 #include <sys/signal.h>
46 #endif
47
48 #ifndef PATH_MAX
49 #define PATH_MAX DEFAULT_PATH_MAX
50 #endif
51
52 #include "WindowMaker.h"
53 #include "GNUstep.h"
54 #include "screen.h"
55 #include "dialog.h"
56 #include "funcs.h"
57 #include "stacking.h"
58 #include "framewin.h"
59 #include "window.h"
60 #include "actions.h"
61 #include "defaults.h"
62 #include "xinerama.h"
63
64 extern WPreferences wPreferences;
65
66 static WMPoint getCenter(WScreen * scr, int width, int height)
67 {
68         return wGetPointToCenterRectInHead(scr, wGetHeadForPointerLocation(scr), width, height);
69 }
70
71 int wMessageDialog(WScreen * scr, char *title, char *message, char *defBtn, char *altBtn, char *othBtn)
72 {
73         WMAlertPanel *panel;
74         Window parent;
75         WWindow *wwin;
76         int result;
77         WMPoint center;
78
79         panel = WMCreateAlertPanel(scr->wmscreen, NULL, title, message, defBtn, altBtn, othBtn);
80
81         parent = XCreateSimpleWindow(dpy, scr->root_win, 0, 0, 400, 180, 0, 0, 0);
82
83         XReparentWindow(dpy, WMWidgetXID(panel->win), parent, 0, 0);
84
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);
88
89         WMMapWidget(panel->win);
90
91         wWindowMap(wwin);
92
93         WMRunModalLoop(WMWidgetScreen(panel->win), WMWidgetView(panel->win));
94
95         result = panel->result;
96
97         WMUnmapWidget(panel->win);
98
99         wUnmanageWindow(wwin, False, False);
100
101         WMDestroyAlertPanel(panel);
102
103         XDestroyWindow(dpy, parent);
104
105         return result;
106 }
107
108 void toggleSaveSession(WMWidget * w, void *data)
109 {
110         wPreferences.save_session_on_exit = WMGetButtonSelected((WMButton *) w);
111 }
112
113 int wExitDialog(WScreen * scr, char *title, char *message, char *defBtn, char *altBtn, char *othBtn)
114 {
115         WMAlertPanel *panel;
116         WMButton *saveSessionBtn;
117         Window parent;
118         WWindow *wwin;
119         WMPoint center;
120         int result;
121
122         panel = WMCreateAlertPanel(scr->wmscreen, NULL, title, message, defBtn, altBtn, othBtn);
123
124         /* add save session button */
125         saveSessionBtn = WMCreateSwitchButton(panel->hbox);
126         WMSetButtonAction(saveSessionBtn, toggleSaveSession, NULL);
127         WMAddBoxSubview(panel->hbox, WMWidgetView(saveSessionBtn), False, True, 200, 0, 0);
128         WMSetButtonText(saveSessionBtn, _("Save workspace state"));
129         WMSetButtonSelected(saveSessionBtn, wPreferences.save_session_on_exit);
130         WMRealizeWidget(saveSessionBtn);
131         WMMapWidget(saveSessionBtn);
132
133         parent = XCreateSimpleWindow(dpy, scr->root_win, 0, 0, 400, 180, 0, 0, 0);
134
135         XReparentWindow(dpy, WMWidgetXID(panel->win), parent, 0, 0);
136
137         center = getCenter(scr, 400, 180);
138         wwin = wManageInternalWindow(scr, parent, None, NULL, center.x, center.y, 400, 180);
139
140         wwin->client_leader = WMWidgetXID(panel->win);
141
142         WMMapWidget(panel->win);
143
144         wWindowMap(wwin);
145
146         WMRunModalLoop(WMWidgetScreen(panel->win), WMWidgetView(panel->win));
147
148         result = panel->result;
149
150         WMUnmapWidget(panel->win);
151
152         wUnmanageWindow(wwin, False, False);
153
154         WMDestroyAlertPanel(panel);
155
156         XDestroyWindow(dpy, parent);
157
158         return result;
159 }
160
161 int wInputDialog(WScreen * scr, char *title, char *message, char **text)
162 {
163         WWindow *wwin;
164         Window parent;
165         WMInputPanel *panel;
166         char *result;
167         WMPoint center;
168
169         panel = WMCreateInputPanel(scr->wmscreen, NULL, title, message, *text, _("OK"), _("Cancel"));
170
171         parent = XCreateSimpleWindow(dpy, scr->root_win, 0, 0, 320, 160, 0, 0, 0);
172         XSelectInput(dpy, parent, KeyPressMask | KeyReleaseMask);
173
174         XReparentWindow(dpy, WMWidgetXID(panel->win), parent, 0, 0);
175
176         center = getCenter(scr, 320, 160);
177         wwin = wManageInternalWindow(scr, parent, None, NULL, center.x, center.y, 320, 160);
178
179         wwin->client_leader = WMWidgetXID(panel->win);
180
181         WMMapWidget(panel->win);
182
183         wWindowMap(wwin);
184
185         WMRunModalLoop(WMWidgetScreen(panel->win), WMWidgetView(panel->win));
186
187         if (panel->result == WAPRDefault)
188                 result = WMGetTextFieldText(panel->text);
189         else
190                 result = NULL;
191
192         wUnmanageWindow(wwin, False, False);
193
194         WMDestroyInputPanel(panel);
195
196         XDestroyWindow(dpy, parent);
197
198         if (result == NULL)
199                 return False;
200         else {
201                 if (*text)
202                         wfree(*text);
203                 *text = result;
204
205                 return True;
206         }
207 }
208
209 /*
210  *****************************************************************
211  * Icon Selection Panel
212  *****************************************************************
213  */
214
215 typedef struct IconPanel {
216
217         WScreen *scr;
218
219         WMWindow *win;
220
221         WMLabel *dirLabel;
222         WMLabel *iconLabel;
223
224         WMList *dirList;
225         WMList *iconList;
226         WMFont *normalfont;
227
228         WMButton *previewButton;
229
230         WMLabel *iconView;
231
232         WMLabel *fileLabel;
233         WMTextField *fileField;
234
235         WMButton *okButton;
236         WMButton *cancelButton;
237 #if 0
238         WMButton *chooseButton;
239 #endif
240         short done;
241         short result;
242         short preview;
243 } IconPanel;
244
245 static void listPixmaps(WScreen * scr, WMList * lPtr, char *path)
246 {
247         struct dirent *dentry;
248         DIR *dir;
249         char pbuf[PATH_MAX + 16];
250         char *apath;
251         IconPanel *panel = WMGetHangedData(lPtr);
252
253         panel->preview = False;
254
255         apath = wexpandpath(path);
256         dir = opendir(apath);
257
258         if (!dir) {
259                 char *msg;
260                 char *tmp;
261                 tmp = _("Could not open directory ");
262                 msg = wmalloc(strlen(tmp) + strlen(path) + 6);
263                 strcpy(msg, tmp);
264                 strcat(msg, path);
265
266                 wMessageDialog(scr, _("Error"), msg, _("OK"), NULL, NULL);
267                 wfree(msg);
268                 wfree(apath);
269                 return;
270         }
271
272         /* list contents in the column */
273         while ((dentry = readdir(dir))) {
274                 struct stat statb;
275
276                 if (strcmp(dentry->d_name, ".") == 0 || strcmp(dentry->d_name, "..") == 0)
277                         continue;
278
279                 strcpy(pbuf, apath);
280                 strcat(pbuf, "/");
281                 strcat(pbuf, dentry->d_name);
282
283                 if (stat(pbuf, &statb) < 0)
284                         continue;
285
286                 if (statb.st_mode & (S_IRUSR | S_IRGRP | S_IROTH)
287                     && statb.st_mode & (S_IFREG | S_IFLNK)) {
288                         WMAddListItem(lPtr, dentry->d_name);
289                 }
290         }
291         WMSortListItems(lPtr);
292
293         closedir(dir);
294         wfree(apath);
295         panel->preview = True;
296 }
297
298 static void setViewedImage(IconPanel * panel, char *file)
299 {
300         WMPixmap *pixmap;
301         RColor color;
302
303         color.red = 0xae;
304         color.green = 0xaa;
305         color.blue = 0xae;
306         color.alpha = 0;
307         pixmap = WMCreateBlendedPixmapFromFile(WMWidgetScreen(panel->win), file, &color);
308         if (!pixmap) {
309                 WMSetButtonEnabled(panel->okButton, False);
310
311                 WMSetLabelText(panel->iconView, _("Could not load image file "));
312
313                 WMSetLabelImage(panel->iconView, NULL);
314         } else {
315                 WMSetButtonEnabled(panel->okButton, True);
316
317                 WMSetLabelText(panel->iconView, NULL);
318                 WMSetLabelImage(panel->iconView, pixmap);
319                 WMReleasePixmap(pixmap);
320         }
321 }
322
323 static void listCallback(void *self, void *data)
324 {
325         WMList *lPtr = (WMList *) self;
326         IconPanel *panel = (IconPanel *) data;
327         char *path;
328
329         if (lPtr == panel->dirList) {
330                 WMListItem *item = WMGetListSelectedItem(lPtr);
331
332                 if (item == NULL)
333                         return;
334                 path = item->text;
335
336                 WMSetTextFieldText(panel->fileField, path);
337
338                 WMSetLabelImage(panel->iconView, NULL);
339
340                 WMSetButtonEnabled(panel->okButton, False);
341
342                 WMClearList(panel->iconList);
343                 listPixmaps(panel->scr, panel->iconList, path);
344         } else {
345                 char *tmp, *iconFile;
346                 WMListItem *item = WMGetListSelectedItem(panel->dirList);
347
348                 if (item == NULL)
349                         return;
350                 path = item->text;
351                 tmp = wexpandpath(path);
352
353                 item = WMGetListSelectedItem(panel->iconList);
354                 if (item == NULL)
355                         return;
356                 iconFile = item->text;
357
358                 path = wmalloc(strlen(tmp) + strlen(iconFile) + 4);
359                 strcpy(path, tmp);
360                 strcat(path, "/");
361                 strcat(path, iconFile);
362                 wfree(tmp);
363                 WMSetTextFieldText(panel->fileField, path);
364                 setViewedImage(panel, path);
365                 wfree(path);
366         }
367 }
368
369 static void listIconPaths(WMList * lPtr)
370 {
371         char *paths;
372         char *path;
373
374         paths = wstrdup(wPreferences.icon_path);
375
376         path = strtok(paths, ":");
377
378         do {
379                 char *tmp;
380
381                 tmp = wexpandpath(path);
382                 /* do not sort, because the order implies the order of
383                  * directories searched */
384                 if (access(tmp, X_OK) == 0)
385                         WMAddListItem(lPtr, path);
386                 wfree(tmp);
387         } while ((path = strtok(NULL, ":")) != NULL);
388
389         wfree(paths);
390 }
391
392 static void drawIconProc(WMList * lPtr, int index, Drawable d, char *text, int state, WMRect * rect)
393 {
394         IconPanel *panel = WMGetHangedData(lPtr);
395         WScreen *scr = panel->scr;
396         GC gc = scr->draw_gc;
397         GC copygc = scr->copy_gc;
398         char *file, *dirfile;
399         WMPixmap *pixmap;
400         WMColor *back;
401         WMSize size;
402         WMScreen *wmscr = WMWidgetScreen(panel->win);
403         RColor color;
404         int x, y, width, height, len;
405
406         if (!panel->preview)
407                 return;
408
409         x = rect->pos.x;
410         y = rect->pos.y;
411         width = rect->size.width;
412         height = rect->size.height;
413
414         back = (state & WLDSSelected) ? scr->white : scr->gray;
415
416         dirfile = wexpandpath(WMGetListSelectedItem(panel->dirList)->text);
417         len = strlen(dirfile) + strlen(text) + 4;
418         file = wmalloc(len);
419         snprintf(file, len, "%s/%s", dirfile, text);
420         wfree(dirfile);
421
422         color.red = WMRedComponentOfColor(back) >> 8;
423         color.green = WMGreenComponentOfColor(back) >> 8;
424         color.blue = WMBlueComponentOfColor(back) >> 8;
425         color.alpha = WMGetColorAlpha(back) >> 8;
426
427         pixmap = WMCreateBlendedPixmapFromFile(wmscr, file, &color);
428         wfree(file);
429
430         if (!pixmap) {
431                 /*WMRemoveListItem(lPtr, index); */
432                 return;
433         }
434
435         XFillRectangle(dpy, d, WMColorGC(back), x, y, width, height);
436
437         XSetClipMask(dpy, gc, None);
438         /*XDrawRectangle(dpy, d, WMColorGC(white), x+5, y+5, width-10, 54); */
439         XDrawLine(dpy, d, WMColorGC(scr->white), x, y + height - 1, x + width, y + height - 1);
440
441         size = WMGetPixmapSize(pixmap);
442
443         XSetClipMask(dpy, copygc, WMGetPixmapMaskXID(pixmap));
444         XSetClipOrigin(dpy, copygc, x + (width - size.width) / 2, y + 2);
445         XCopyArea(dpy, WMGetPixmapXID(pixmap), d, copygc, 0, 0,
446                   size.width > 100 ? 100 : size.width, size.height > 64 ? 64 : size.height,
447                   x + (width - size.width) / 2, y + 2);
448
449         {
450                 int i, j;
451                 int fheight = WMFontHeight(panel->normalfont);
452                 int tlen = strlen(text);
453                 int twidth = WMWidthOfString(panel->normalfont, text, tlen);
454                 int ofx, ofy;
455
456                 ofx = x + (width - twidth) / 2;
457                 ofy = y + 64 - fheight;
458
459                 for (i = -1; i < 2; i++)
460                         for (j = -1; j < 2; j++)
461                                 WMDrawString(wmscr, d, scr->white, panel->normalfont,
462                                              ofx + i, ofy + j, text, tlen);
463
464                 WMDrawString(wmscr, d, scr->black, panel->normalfont, ofx, ofy, text, tlen);
465         }
466
467         WMReleasePixmap(pixmap);
468         /* I hope it is better to do not use cache / on my box it is fast nuff */
469         XFlush(dpy);
470 }
471
472 static void buttonCallback(void *self, void *clientData)
473 {
474         WMButton *bPtr = (WMButton *) self;
475         IconPanel *panel = (IconPanel *) clientData;
476
477         if (bPtr == panel->okButton) {
478                 panel->done = True;
479                 panel->result = True;
480         } else if (bPtr == panel->cancelButton) {
481                 panel->done = True;
482                 panel->result = False;
483         } else if (bPtr == panel->previewButton) {
484         /**** Previewer ****/
485                 WMSetButtonEnabled(bPtr, False);
486                 WMSetListUserDrawItemHeight(panel->iconList, 68);
487                 WMSetListUserDrawProc(panel->iconList, drawIconProc);
488                 WMRedisplayWidget(panel->iconList);
489                 /* for draw proc to access screen/gc */
490         /*** end preview ***/
491         }
492 #if 0
493         else if (bPtr == panel->chooseButton) {
494                 WMOpenPanel *op;
495
496                 op = WMCreateOpenPanel(WMWidgetScreen(bPtr));
497
498                 if (WMRunModalFilePanelForDirectory(op, NULL, "/usr/local", NULL, NULL)) {
499                         char *path;
500                         path = WMGetFilePanelFile(op);
501                         WMSetTextFieldText(panel->fileField, path);
502                         setViewedImage(panel, path);
503                         wfree(path);
504                 }
505                 WMDestroyFilePanel(op);
506         }
507 #endif
508 }
509
510 static void keyPressHandler(XEvent * event, void *data)
511 {
512         IconPanel *panel = (IconPanel *) data;
513         char buffer[32];
514         int count;
515         KeySym ksym;
516         int iidx;
517         int didx;
518         int item = 0;
519         WMList *list = NULL;
520
521         if (event->type == KeyRelease)
522                 return;
523
524         buffer[0] = 0;
525         count = XLookupString(&event->xkey, buffer, sizeof(buffer), &ksym, NULL);
526
527         iidx = WMGetListSelectedItemRow(panel->iconList);
528         didx = WMGetListSelectedItemRow(panel->dirList);
529
530         switch (ksym) {
531         case XK_Up:
532                 if (iidx > 0)
533                         item = iidx - 1;
534                 else
535                         item = iidx;
536                 list = panel->iconList;
537                 break;
538         case XK_Down:
539                 if (iidx < WMGetListNumberOfRows(panel->iconList) - 1)
540                         item = iidx + 1;
541                 else
542                         item = iidx;
543                 list = panel->iconList;
544                 break;
545         case XK_Home:
546                 item = 0;
547                 list = panel->iconList;
548                 break;
549         case XK_End:
550                 item = WMGetListNumberOfRows(panel->iconList) - 1;
551                 list = panel->iconList;
552                 break;
553         case XK_Next:
554                 if (didx < WMGetListNumberOfRows(panel->dirList) - 1)
555                         item = didx + 1;
556                 else
557                         item = didx;
558                 list = panel->dirList;
559                 break;
560         case XK_Prior:
561                 if (didx > 0)
562                         item = didx - 1;
563                 else
564                         item = 0;
565                 list = panel->dirList;
566                 break;
567         case XK_Return:
568                 WMPerformButtonClick(panel->okButton);
569                 break;
570         case XK_Escape:
571                 WMPerformButtonClick(panel->cancelButton);
572                 break;
573         }
574
575         if (list) {
576                 WMSelectListItem(list, item);
577                 WMSetListPosition(list, item - 5);
578                 listCallback(list, panel);
579         }
580 }
581
582 Bool wIconChooserDialog(WScreen * scr, char **file, char *instance, char *class)
583 {
584         WWindow *wwin;
585         Window parent;
586         IconPanel *panel;
587         WMColor *color;
588         WMFont *boldFont;
589         Bool result;
590
591         panel = wmalloc(sizeof(IconPanel));
592         memset(panel, 0, sizeof(IconPanel));
593
594         panel->scr = scr;
595
596         panel->win = WMCreateWindow(scr->wmscreen, "iconChooser");
597         WMResizeWidget(panel->win, 450, 280);
598
599         WMCreateEventHandler(WMWidgetView(panel->win), KeyPressMask | KeyReleaseMask, keyPressHandler, panel);
600
601         boldFont = WMBoldSystemFontOfSize(scr->wmscreen, 12);
602         panel->normalfont = WMSystemFontOfSize(WMWidgetScreen(panel->win), 12);
603
604         panel->dirLabel = WMCreateLabel(panel->win);
605         WMResizeWidget(panel->dirLabel, 200, 20);
606         WMMoveWidget(panel->dirLabel, 10, 7);
607         WMSetLabelText(panel->dirLabel, _("Directories"));
608         WMSetLabelFont(panel->dirLabel, boldFont);
609         WMSetLabelTextAlignment(panel->dirLabel, WACenter);
610
611         WMSetLabelRelief(panel->dirLabel, WRSunken);
612
613         panel->iconLabel = WMCreateLabel(panel->win);
614         WMResizeWidget(panel->iconLabel, 140, 20);
615         WMMoveWidget(panel->iconLabel, 215, 7);
616         WMSetLabelText(panel->iconLabel, _("Icons"));
617         WMSetLabelFont(panel->iconLabel, boldFont);
618         WMSetLabelTextAlignment(panel->iconLabel, WACenter);
619
620         WMReleaseFont(boldFont);
621
622         color = WMWhiteColor(scr->wmscreen);
623         WMSetLabelTextColor(panel->dirLabel, color);
624         WMSetLabelTextColor(panel->iconLabel, color);
625         WMReleaseColor(color);
626
627         color = WMDarkGrayColor(scr->wmscreen);
628         WMSetWidgetBackgroundColor(panel->iconLabel, color);
629         WMSetWidgetBackgroundColor(panel->dirLabel, color);
630         WMReleaseColor(color);
631
632         WMSetLabelRelief(panel->iconLabel, WRSunken);
633
634         panel->dirList = WMCreateList(panel->win);
635         WMResizeWidget(panel->dirList, 200, 170);
636         WMMoveWidget(panel->dirList, 10, 30);
637         WMSetListAction(panel->dirList, listCallback, panel);
638
639         panel->iconList = WMCreateList(panel->win);
640         WMResizeWidget(panel->iconList, 140, 170);
641         WMMoveWidget(panel->iconList, 215, 30);
642         WMSetListAction(panel->iconList, listCallback, panel);
643
644         WMHangData(panel->iconList, panel);
645
646         panel->previewButton = WMCreateCommandButton(panel->win);
647         WMResizeWidget(panel->previewButton, 75, 26);
648         WMMoveWidget(panel->previewButton, 365, 130);
649         WMSetButtonText(panel->previewButton, _("Preview"));
650         WMSetButtonAction(panel->previewButton, buttonCallback, panel);
651
652         panel->iconView = WMCreateLabel(panel->win);
653         WMResizeWidget(panel->iconView, 75, 75);
654         WMMoveWidget(panel->iconView, 365, 40);
655         WMSetLabelImagePosition(panel->iconView, WIPOverlaps);
656         WMSetLabelRelief(panel->iconView, WRSunken);
657         WMSetLabelTextAlignment(panel->iconView, WACenter);
658
659         panel->fileLabel = WMCreateLabel(panel->win);
660         WMResizeWidget(panel->fileLabel, 80, 20);
661         WMMoveWidget(panel->fileLabel, 10, 210);
662         WMSetLabelText(panel->fileLabel, _("File Name:"));
663
664         panel->fileField = WMCreateTextField(panel->win);
665         WMSetViewNextResponder(WMWidgetView(panel->fileField), WMWidgetView(panel->win));
666         WMResizeWidget(panel->fileField, 345, 20);
667         WMMoveWidget(panel->fileField, 95, 210);
668         WMSetTextFieldEditable(panel->fileField, False);
669
670         panel->okButton = WMCreateCommandButton(panel->win);
671         WMResizeWidget(panel->okButton, 80, 26);
672         WMMoveWidget(panel->okButton, 360, 240);
673         WMSetButtonText(panel->okButton, _("OK"));
674         WMSetButtonEnabled(panel->okButton, False);
675         WMSetButtonAction(panel->okButton, buttonCallback, panel);
676
677         panel->cancelButton = WMCreateCommandButton(panel->win);
678         WMResizeWidget(panel->cancelButton, 80, 26);
679         WMMoveWidget(panel->cancelButton, 270, 240);
680         WMSetButtonText(panel->cancelButton, _("Cancel"));
681         WMSetButtonAction(panel->cancelButton, buttonCallback, panel);
682 #if 0
683         panel->chooseButton = WMCreateCommandButton(panel->win);
684         WMResizeWidget(panel->chooseButton, 110, 26);
685         WMMoveWidget(panel->chooseButton, 150, 240);
686         WMSetButtonText(panel->chooseButton, _("Choose File"));
687         WMSetButtonAction(panel->chooseButton, buttonCallback, panel);
688 #endif
689         WMRealizeWidget(panel->win);
690         WMMapSubwidgets(panel->win);
691
692         parent = XCreateSimpleWindow(dpy, scr->root_win, 0, 0, 450, 280, 0, 0, 0);
693
694         XReparentWindow(dpy, WMWidgetXID(panel->win), parent, 0, 0);
695
696         {
697                 char *tmp;
698                 int len = (instance ? strlen(instance) : 0)
699                     + (class ? strlen(class) : 0) + 32;
700                 WMPoint center;
701
702                 tmp = wmalloc(len);
703
704                 if (tmp && (instance || class))
705                         snprintf(tmp, len, "%s [%s.%s]", _("Icon Chooser"), instance, class);
706                 else
707                         strcpy(tmp, _("Icon Chooser"));
708
709                 center = getCenter(scr, 450, 280);
710
711                 wwin = wManageInternalWindow(scr, parent, None, tmp, center.x, center.y, 450, 280);
712                 wfree(tmp);
713         }
714
715         /* put icon paths in the list */
716         listIconPaths(panel->dirList);
717
718         WMMapWidget(panel->win);
719
720         wWindowMap(wwin);
721
722         while (!panel->done) {
723                 XEvent event;
724
725                 WMNextEvent(dpy, &event);
726                 WMHandleEvent(&event);
727         }
728
729         if (panel->result) {
730                 char *defaultPath, *wantedPath;
731
732                 /* check if the file the user selected is not the one that
733                  * would be loaded by default with the current search path */
734                 *file = WMGetListSelectedItem(panel->iconList)->text;
735                 if (**file == 0) {
736                         wfree(*file);
737                         *file = NULL;
738                 } else {
739                         defaultPath = FindImage(wPreferences.icon_path, *file);
740                         wantedPath = WMGetTextFieldText(panel->fileField);
741                         /* if the file is not the default, use full path */
742                         if (strcmp(wantedPath, defaultPath) != 0) {
743                                 *file = wantedPath;
744                         } else {
745                                 *file = wstrdup(*file);
746                                 wfree(wantedPath);
747                         }
748                         wfree(defaultPath);
749                 }
750         } else {
751                 *file = NULL;
752         }
753
754         result = panel->result;
755
756         WMReleaseFont(panel->normalfont);
757
758         WMUnmapWidget(panel->win);
759
760         WMDestroyWidget(panel->win);
761
762         wUnmanageWindow(wwin, False, False);
763
764         wfree(panel);
765
766         XDestroyWindow(dpy, parent);
767
768         return result;
769 }
770
771 /*
772  ***********************************************************************
773  * Info Panel
774  ***********************************************************************
775  */
776
777 typedef struct {
778         WScreen *scr;
779
780         WWindow *wwin;
781
782         WMWindow *win;
783
784         WMLabel *logoL;
785         WMLabel *name1L;
786         WMFrame *lineF;
787         WMLabel *name2L;
788
789         WMLabel *versionL;
790
791         WMLabel *infoL;
792
793         WMLabel *copyrL;
794
795 #ifdef SILLYNESS
796         WMHandlerID timer;
797         int cycle;
798         RImage *icon;
799         RImage *pic;
800         WMPixmap *oldPix;
801         WMFont *oldFont;
802         char *str;
803         int x;
804 #endif
805 } InfoPanel;
806
807 #define COPYRIGHT_TEXT  \
808     "Copyright \xc2\xa9 1997-2006 Alfredo K. Kojima\n"\
809     "Copyright \xc2\xa9 1998-2006 Dan Pascu"
810
811 static InfoPanel *thePanel = NULL;
812
813 static void destroyInfoPanel(WCoreWindow * foo, void *data, XEvent * event)
814 {
815 #ifdef SILLYNESS
816         if (thePanel->timer) {
817                 WMDeleteTimerHandler(thePanel->timer);
818         }
819         if (thePanel->oldPix) {
820                 WMReleasePixmap(thePanel->oldPix);
821         }
822         if (thePanel->oldFont) {
823                 WMReleaseFont(thePanel->oldFont);
824         }
825         if (thePanel->icon) {
826                 RReleaseImage(thePanel->icon);
827         }
828         if (thePanel->pic) {
829                 RReleaseImage(thePanel->pic);
830         }
831 #endif                          /* SILLYNESS */
832         WMUnmapWidget(thePanel);
833
834         wUnmanageWindow(thePanel->wwin, False, False);
835
836         WMDestroyWidget(thePanel->win);
837
838         wfree(thePanel);
839
840         thePanel = NULL;
841 }
842
843 #ifdef SILLYNESS
844
845 extern WMPixmap *DoXThing();
846 extern Bool InitXThing();
847
848 static void logoPushCallback(void *data)
849 {
850         InfoPanel *panel = (InfoPanel *) data;
851         char buffer[512];
852         int i;
853         static int oldi = 0;
854         int len;
855         static int jingobeu[] = {
856                 329, 150, -1, 100, 329, 150, -1, 100, 329, 300, -1, 250,
857                 329, 150, -1, 100, 329, 150, -1, 100, 329, 300, -1, 250,
858                 329, 150, 392, 150, 261, 150, 293, 150, 329, 400, -1, 400, 0
859         };
860         static int c = 0;
861
862         if (panel->x) {
863                 XKeyboardControl kc;
864                 XKeyboardState ksave;
865                 unsigned long mask = KBBellPitch | KBBellDuration | KBBellPercent;
866
867                 XGetKeyboardControl(dpy, &ksave);
868
869                 if (panel->x > 0) {
870                         if (jingobeu[panel->x - 1] == 0) {
871                                 panel->x = -1;
872                         } else if (jingobeu[panel->x - 1] < 0) {
873                                 panel->x++;
874                                 c = jingobeu[panel->x - 1] / 50;
875                                 panel->x++;
876                         } else if (c == 0) {
877                                 kc.bell_percent = 50;
878                                 kc.bell_pitch = jingobeu[panel->x - 1];
879                                 panel->x++;
880                                 kc.bell_duration = jingobeu[panel->x - 1];
881                                 c = jingobeu[panel->x - 1] / 50;
882                                 panel->x++;
883                                 XChangeKeyboardControl(dpy, mask, &kc);
884                                 XBell(dpy, 50);
885                                 XFlush(dpy);
886                         } else {
887                                 c--;
888                         }
889                 }
890                 if (!(panel->cycle % 4)) {
891                         WMPixmap *p;
892
893                         p = DoXThing(panel->wwin);
894                         WMSetLabelImage(panel->logoL, p);
895                 }
896                 kc.bell_pitch = ksave.bell_pitch;
897                 kc.bell_percent = ksave.bell_percent;
898                 kc.bell_duration = ksave.bell_duration;
899                 XChangeKeyboardControl(dpy, mask, &kc);
900         } else if (panel->cycle < 30) {
901                 RImage *image;
902                 WMPixmap *pix;
903                 RColor gray;
904
905                 gray.red = 0xae;
906                 gray.green = 0xaa;
907                 gray.blue = 0xae;
908                 gray.alpha = 0;
909
910                 image = RScaleImage(panel->icon, panel->pic->width, panel->pic->height);
911                 RCombineImagesWithOpaqueness(image, panel->pic, panel->cycle * 255 / 30);
912                 pix = WMCreateBlendedPixmapFromRImage(panel->scr->wmscreen, image, &gray);
913                 RReleaseImage(image);
914                 WMSetLabelImage(panel->logoL, pix);
915                 WMReleasePixmap(pix);
916         }
917
918         /* slow down text a little */
919         i = (int)(panel->cycle * 50.0 / 85.0) % 200;
920
921         if (i != oldi) {
922                 len = strlen(panel->str);
923
924                 strncpy(buffer, panel->str, i < len ? i : len);
925                 if (i >= len)
926                         memset(&buffer[len], ' ', i - len);
927
928                 strncpy(buffer, panel->str, i < len ? i : len);
929                 if (i >= len)
930                         memset(&buffer[len], ' ', i - len);
931                 buffer[i] = 0;
932
933                 WMSetLabelText(panel->versionL, buffer);
934
935                 XFlush(WMScreenDisplay(WMWidgetScreen(panel->versionL)));
936
937                 oldi = i;
938         }
939
940         panel->timer = WMAddTimerHandler(50, logoPushCallback, panel);
941         panel->cycle++;
942 }
943
944 static void handleLogoPush(XEvent * event, void *data)
945 {
946         InfoPanel *panel = (InfoPanel *) data;
947         static int broken = 0;
948         static int clicks = 0;
949         static char *pic_data[] = {
950                 "45 45 57 1",
951                 "       c None",
952                 ".      c #000000",
953                 "X      c #383C00",
954                 "o      c #515500",
955                 "O      c #616100",
956                 "+      c #616900",
957                 "@      c #696D00",
958                 "#      c #697100",
959                 "$      c #495100",
960                 "%      c #202800",
961                 "&      c #969600",
962                 "*      c #CFCF00",
963                 "=      c #D7DB00",
964                 "-      c #D7D700",
965                 ";      c #C7CB00",
966                 ":      c #A6AA00",
967                 ">      c #494900",
968                 ",      c #8E8E00",
969                 "<      c #DFE700",
970                 "1      c #F7FF00",
971                 "2      c #FFFF00",
972                 "3      c #E7EB00",
973                 "4      c #B6B600",
974                 "5      c #595900",
975                 "6      c #717500",
976                 "7      c #AEB200",
977                 "8      c #CFD300",
978                 "9      c #E7EF00",
979                 "0      c #EFF300",
980                 "q      c #9EA200",
981                 "w      c #F7FB00",
982                 "e      c #F7F700",
983                 "r      c #BEBE00",
984                 "t      c #8E9200",
985                 "y      c #EFF700",
986                 "u      c #969A00",
987                 "i      c #414500",
988                 "p      c #595D00",
989                 "a      c #E7E700",
990                 "s      c #C7C700",
991                 "d      c #797D00",
992                 "f      c #BEC300",
993                 "g      c #DFE300",
994                 "h      c #868600",
995                 "j      c #EFEF00",
996                 "k      c #9E9E00",
997                 "l      c #616500",
998                 "z      c #DFDF00",
999                 "x      c #868A00",
1000                 "c      c #969200",
1001                 "v      c #B6BA00",
1002                 "b      c #A6A600",
1003                 "n      c #8E8A00",
1004                 "m      c #717100",
1005                 "M      c #AEAE00",
1006                 "N      c #AEAA00",
1007                 "B      c #868200",
1008                 "               ...............               ",
1009                 "             ....XoO+@##+O$%....             ",
1010                 "           ...%X&*========-;;:o...           ",
1011                 "         ...>.>,<122222222222134@...         ",
1012                 "        ..>5678912222222222222220q%..        ",
1013                 "       ..$.&-w2222222222222222222er>..       ",
1014                 "      ..O.t31222222222222222222222y4>..      ",
1015                 "    ...O5u3222222222222222222222222yri...    ",
1016                 "    ..>p&a22222222222222222222222222wso..    ",
1017                 "   ..ids91222222222222222222222222222wfi..   ",
1018                 "  ..X.7w222222wgs-w2222222213=g0222222<hi..  ",
1019                 "  ..Xuj2222222<@X5=222222229k@l:022222y4i..  ",
1020                 "  .Xdz22222222*X%.s22222222axo%$-222222<c>.. ",
1021                 " ..o7y22222222v...r222222223hX.i82222221si.. ",
1022                 "..io*222222222&...u22222222yt..%*22222220:%. ",
1023                 "..>k02222222227...f222222222v..X=222222229t. ",
1024                 "..dz12222222220ui:y2222222223d%qw222222221g. ",
1025                 ".%vw222222222221y2222222222219*y2222222222wd.",
1026                 ".X;2222222222222222222222222222222222222222b.",
1027                 ".i*2222222222222222222222222222222222222222v.",
1028                 ".i*2222222222222222222222222222222222222222;.",
1029                 ".i*22222222222222222222222222222222222222228.",
1030                 ".>*2222222222222222222222222222222222222222=.",
1031                 ".i*22222222222222222222222222222222222222228.",
1032                 ".i*2222222222222222222222222222222222222222;.",
1033                 ".X*222222222222222222222222222222we12222222r.",
1034                 ".Xs12222222w3aw22222222222222222y8s0222222wk.",
1035                 ".Xq02222222a,na22222222222222222zm6zwy2222gi.",
1036                 "..>*22222y<:Xcj22222222222222222-o$k;;02228..",
1037                 "..i7y2220rhX.:y22222222222222222jtiXd,a220,..",
1038                 " .X@z222a,do%kj2222222222222222wMX5q;gw228%..",
1039                 " ..58222wagsh6ry222222222222221;>Of0w222y:...",
1040                 " ...:e2222218mdz22222222222222a&$vw222220@...",
1041                 " ...O-122222y:.u02222222222229q$uj222221r... ",
1042                 "  ..%&a1222223&573w2222222219NOxz122221z>... ",
1043                 "   ...t3222221-l$nr8ay1222yzbo,=12222w-5...  ",
1044                 "    ..X:022222w-k+>o,7s**s7xOn=12221<f5...   ",
1045                 "     ..o:9222221j8:&Bl>>>>ihv<12221=dX...    ",
1046                 "      ..Xb9122222109g-****;<y22221zn%...     ",
1047                 "       ..X&801222222222222222222w-h....      ",
1048                 "        ...o:=022222222222222221=lX...       ",
1049                 "          ..X@:;3w2222222222210fO...         ",
1050                 "           ...XX&v8<30000003-N@...           ",
1051                 "             .....XmnbN:q&Bo....             ",
1052                 "                 ............                "
1053         };
1054         static char *msgs[] = {
1055                 "Have a nice day!",
1056                 "Focus follow mouse users will burn in hell!!!",
1057                 "Mooo Canada!!!!",
1058                 "Hi! My name is bobby...",
1059                 "AHH! The neurotic monkeys are after me!",
1060                 "WE GET SIGNAL",
1061                 "HOW ARE YOU GENTLEMEN?",
1062                 "WHAT YOU SAY??",
1063                 "SOMEBODY SET UP US THE BOMB",
1064                 "ALL YOUR BASE ARE BELONG TO US!",
1065                 "Oh My God!!! Larry is back!",
1066                 "Alex Perez is aliveeeeeeee!!!"
1067         };
1068
1069         clicks++;
1070
1071         if (!panel->timer && !broken && clicks > 0) {
1072                 WMFont *font;
1073
1074                 panel->x = 0;
1075                 clicks = 0;
1076                 if (!panel->icon) {
1077                         panel->icon = WMGetApplicationIconImage(panel->scr->wmscreen);
1078                         if (!panel->icon) {
1079                                 broken = 1;
1080                                 return;
1081                         } else {
1082                                 RColor color;
1083
1084                                 color.red = 0xae;
1085                                 color.green = 0xaa;
1086                                 color.blue = 0xae;
1087                                 color.alpha = 0;
1088
1089                                 panel->icon = RCloneImage(panel->icon);
1090                                 RCombineImageWithColor(panel->icon, &color);
1091                         }
1092                 }
1093                 if (!panel->pic) {
1094                         panel->pic = RGetImageFromXPMData(panel->scr->rcontext, pic_data);
1095                         if (!panel->pic) {
1096                                 broken = 1;
1097                                 RReleaseImage(panel->icon);
1098                                 panel->icon = NULL;
1099                                 return;
1100                         }
1101                 }
1102
1103                 panel->str = msgs[rand() % (sizeof(msgs) / sizeof(char *))];
1104
1105                 panel->timer = WMAddTimerHandler(50, logoPushCallback, panel);
1106                 panel->cycle = 0;
1107                 panel->oldPix = WMRetainPixmap(WMGetLabelImage(panel->logoL));
1108                 /* If we don't use a fixed font, scrolling will be jumpy */
1109                 /* Alternatively we can draw text in a pixmap and scroll it smoothly */
1110                 if ((panel->oldFont = WMGetLabelFont(panel->versionL)) != NULL)
1111                         WMRetainFont(panel->oldFont);
1112                 font = WMCreateFont(WMWidgetScreen(panel->versionL),
1113                                     "Lucida Console,Courier New,monospace:pixelsize=12");
1114                 if (font) {
1115                         WMSetLabelFont(panel->versionL, font);
1116                         WMReleaseFont(font);
1117                 }
1118                 WMSetLabelText(panel->versionL, "");
1119         } else if (panel->timer) {
1120                 char version[20];
1121
1122                 panel->x = 0;
1123                 clicks = 0;
1124                 WMSetLabelImage(panel->logoL, panel->oldPix);
1125                 WMReleasePixmap(panel->oldPix);
1126                 panel->oldPix = NULL;
1127
1128                 WMDeleteTimerHandler(panel->timer);
1129                 panel->timer = NULL;
1130
1131                 WMSetLabelFont(panel->versionL, panel->oldFont);
1132                 if (panel->oldFont) {
1133                         WMReleaseFont(panel->oldFont);
1134                         panel->oldFont = NULL;
1135                 }
1136                 snprintf(version, sizeof(version), _("Version %s"), VERSION);
1137                 WMSetLabelText(panel->versionL, version);
1138                 XFlush(WMScreenDisplay(WMWidgetScreen(panel->versionL)));
1139         }
1140
1141         {
1142                 XEvent ev;
1143                 while (XCheckTypedWindowEvent(dpy, WMWidgetXID(panel->versionL), ButtonPress, &ev)) ;
1144         }
1145 }
1146 #endif                          /* SILLYNESS */
1147
1148 void wShowInfoPanel(WScreen * scr)
1149 {
1150         InfoPanel *panel;
1151         WMPixmap *logo;
1152         WMSize size;
1153         WMFont *font;
1154         char *strbuf = NULL;
1155         char buffer[256];
1156         char *name;
1157         Window parent;
1158         WWindow *wwin;
1159         char **strl;
1160         int i, width = 50, sepHeight;
1161         char *visuals[] = {
1162                 "StaticGray",
1163                 "GrayScale",
1164                 "StaticColor",
1165                 "PseudoColor",
1166                 "TrueColor",
1167                 "DirectColor"
1168         };
1169
1170         if (thePanel) {
1171                 if (thePanel->scr == scr) {
1172                         wRaiseFrame(thePanel->wwin->frame->core);
1173                         wSetFocusTo(scr, thePanel->wwin);
1174                 }
1175                 return;
1176         }
1177
1178         panel = wmalloc(sizeof(InfoPanel));
1179         memset(panel, 0, sizeof(InfoPanel));
1180
1181         panel->scr = scr;
1182
1183         panel->win = WMCreateWindow(scr->wmscreen, "info");
1184         WMResizeWidget(panel->win, 390, 230);
1185
1186         logo = WMCreateApplicationIconBlendedPixmap(scr->wmscreen, (RColor *) NULL);
1187         if (!logo) {
1188                 logo = WMRetainPixmap(WMGetApplicationIconPixmap(scr->wmscreen));
1189         }
1190         if (logo) {
1191                 size = WMGetPixmapSize(logo);
1192                 panel->logoL = WMCreateLabel(panel->win);
1193                 WMResizeWidget(panel->logoL, 64, 64);
1194                 WMMoveWidget(panel->logoL, 30, 20);
1195                 WMSetLabelImagePosition(panel->logoL, WIPImageOnly);
1196                 WMSetLabelImage(panel->logoL, logo);
1197 #ifdef SILLYNESS
1198                 WMCreateEventHandler(WMWidgetView(panel->logoL), ButtonPressMask, handleLogoPush, panel);
1199 #endif
1200                 WMReleasePixmap(logo);
1201         }
1202
1203         sepHeight = 3;
1204         panel->name1L = WMCreateLabel(panel->win);
1205         WMResizeWidget(panel->name1L, 240, 30 + 2);
1206         WMMoveWidget(panel->name1L, 100, 30 - 2 - sepHeight);
1207
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);
1215         }
1216         WMSetLabelTextAlignment(panel->name1L, WACenter);
1217         WMSetLabelText(panel->name1L, strbuf);
1218
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);
1224
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;
1234         }
1235         WMSetLabelTextAlignment(panel->name2L, WACenter);
1236         WMSetLabelText(panel->name2L, _("Window Manager for X"));
1237
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);
1245
1246         panel->copyrL = WMCreateLabel(panel->win);
1247         WMResizeWidget(panel->copyrL, 360, 40);
1248         WMMoveWidget(panel->copyrL, 15, 185);
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;
1256         }
1257
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);
1261
1262         strbuf = wstrappend(strbuf, buffer);
1263
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;
1279         }
1280
1281 #if defined(HAVE_MALLOC_H) && defined(HAVE_MALLINFO)
1282         {
1283                 struct mallinfo ma = mallinfo();
1284                 snprintf(buffer, sizeof(buffer),
1285                          _("Total allocated memory: %i kB. Total memory in use: %i kB.\n"),
1286                          (ma.arena + ma.hblkhd) / 1024, (ma.uordblks + ma.hblkhd) / 1024);
1287
1288                 strbuf = wstrappend(strbuf, buffer);
1289         }
1290 #endif
1291
1292         strbuf = wstrappend(strbuf, _("Supported image formats: "));
1293         strl = RSupportedFileFormats();
1294         for (i = 0; strl[i] != NULL; i++) {
1295                 strbuf = wstrappend(strbuf, strl[i]);
1296                 strbuf = wstrappend(strbuf, " ");
1297         }
1298
1299         strbuf = wstrappend(strbuf, _("\nAdditional support for: "));
1300         {
1301                 char *list[9];
1302                 char buf[80];
1303                 int j = 0;
1304
1305 #ifdef NETWM_HINTS
1306                 list[j++] = "WMSPEC";
1307 #endif
1308 #ifdef MWM_HINTS
1309                 list[j++] = "MWM";
1310 #endif
1311
1312                 buf[0] = 0;
1313                 for (i = 0; i < j; i++) {
1314                         if (i > 0) {
1315                                 if (i == j - 1)
1316                                         strcat(buf, _(" and "));
1317                                 else
1318                                         strcat(buf, ", ");
1319                         }
1320                         strcat(buf, list[i]);
1321                 }
1322                 strbuf = wstrappend(strbuf, buf);
1323         }
1324
1325         if (wPreferences.no_sound) {
1326                 strbuf = wstrappend(strbuf, _("\nSound disabled"));
1327         } else {
1328                 strbuf = wstrappend(strbuf, _("\nSound enabled"));
1329         }
1330
1331 #ifdef VIRTUAL_DESKTOP
1332         if (wPreferences.vdesk_enable)
1333                 strbuf = wstrappend(strbuf, _(", VirtualDesktop enabled"));
1334         else
1335                 strbuf = wstrappend(strbuf, _(", VirtualDesktop disabled"));
1336 #endif
1337
1338 #ifdef XINERAMA
1339         strbuf = wstrappend(strbuf, _("\n"));
1340 #ifdef SOLARIS_XINERAMA
1341         strbuf = wstrappend(strbuf, _("Solaris "));
1342 #endif
1343         strbuf = wstrappend(strbuf, _("Xinerama: "));
1344         {
1345                 char tmp[128];
1346                 snprintf(tmp, sizeof(tmp) - 1, "%d heads found.", scr->xine_info.count);
1347                 strbuf = wstrappend(strbuf, tmp);
1348         }
1349 #endif
1350
1351         panel->infoL = WMCreateLabel(panel->win);
1352         WMResizeWidget(panel->infoL, 350, 75);
1353         WMMoveWidget(panel->infoL, 15, 115);
1354         WMSetLabelText(panel->infoL, strbuf);
1355         font = WMSystemFontOfSize(scr->wmscreen, 11);
1356         if (font) {
1357                 WMSetLabelFont(panel->infoL, font);
1358                 WMReleaseFont(font);
1359                 font = NULL;
1360         }
1361         wfree(strbuf);
1362
1363         WMRealizeWidget(panel->win);
1364         WMMapSubwidgets(panel->win);
1365
1366         parent = XCreateSimpleWindow(dpy, scr->root_win, 0, 0, 382, 230, 0, 0, 0);
1367
1368         XReparentWindow(dpy, WMWidgetXID(panel->win), parent, 0, 0);
1369
1370         WMMapWidget(panel->win);
1371
1372         {
1373                 WMPoint center = getCenter(scr, 382, 230);
1374
1375                 wwin = wManageInternalWindow(scr, parent, None, _("Info"), center.x, center.y, 382, 230);
1376         }
1377
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;
1386
1387         wWindowMap(wwin);
1388
1389         panel->wwin = wwin;
1390
1391         thePanel = panel;
1392 #ifdef SILLYNESS
1393         if (InitXThing(panel->scr)) {
1394                 panel->timer = WMAddTimerHandler(100, logoPushCallback, panel);
1395                 panel->cycle = 0;
1396                 panel->x = 1;
1397                 panel->str = _("Merry Christmas!");
1398                 panel->oldPix = WMRetainPixmap(WMGetLabelImage(panel->logoL));
1399         }
1400 #endif
1401 }
1402
1403 /*
1404  ***********************************************************************
1405  * Legal Panel
1406  ***********************************************************************
1407  */
1408
1409 typedef struct {
1410         WScreen *scr;
1411
1412         WWindow *wwin;
1413
1414         WMWindow *win;
1415
1416         WMLabel *licenseL;
1417 } LegalPanel;
1418
1419 static LegalPanel *legalPanel = NULL;
1420
1421 static void destroyLegalPanel(WCoreWindow * foo, void *data, XEvent * event)
1422 {
1423         WMUnmapWidget(legalPanel->win);
1424
1425         WMDestroyWidget(legalPanel->win);
1426
1427         wUnmanageWindow(legalPanel->wwin, False, False);
1428
1429         wfree(legalPanel);
1430
1431         legalPanel = NULL;
1432 }
1433
1434 void wShowLegalPanel(WScreen * scr)
1435 {
1436         LegalPanel *panel;
1437         Window parent;
1438         WWindow *wwin;
1439
1440         if (legalPanel) {
1441                 if (legalPanel->scr == scr) {
1442                         wRaiseFrame(legalPanel->wwin->frame->core);
1443                         wSetFocusTo(scr, legalPanel->wwin);
1444                 }
1445                 return;
1446         }
1447
1448         panel = wmalloc(sizeof(LegalPanel));
1449
1450         panel->scr = scr;
1451
1452         panel->win = WMCreateWindow(scr->wmscreen, "legal");
1453         WMResizeWidget(panel->win, 420, 250);
1454
1455         panel->licenseL = WMCreateLabel(panel->win);
1456         WMSetLabelWraps(panel->licenseL, True);
1457         WMResizeWidget(panel->licenseL, 400, 230);
1458         WMMoveWidget(panel->licenseL, 10, 10);
1459         WMSetLabelTextAlignment(panel->licenseL, WALeft);
1460         WMSetLabelText(panel->licenseL,
1461                        _("    Window Maker is free software; you can redistribute it and/or\n"
1462                          "modify it under the terms of the GNU General Public License as\n"
1463                          "published by the Free Software Foundation; either version 2 of the\n"
1464                          "License, or (at your option) any later version.\n\n"
1465                          "    Window Maker is distributed in the hope that it will be useful,\n"
1466                          "but WITHOUT ANY WARRANTY; without even the implied warranty\n"
1467                          "of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
1468                          "See the GNU General Public License for more details.\n\n"
1469                          "    You should have received a copy of the GNU General Public\n"
1470                          "License along with this program; if not, write to the Free Software\n"
1471                          "Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA\n" "02111-1307, USA."));
1472         WMSetLabelRelief(panel->licenseL, WRGroove);
1473
1474         WMRealizeWidget(panel->win);
1475         WMMapSubwidgets(panel->win);
1476
1477         parent = XCreateSimpleWindow(dpy, scr->root_win, 0, 0, 420, 250, 0, 0, 0);
1478
1479         XReparentWindow(dpy, WMWidgetXID(panel->win), parent, 0, 0);
1480
1481         {
1482                 WMPoint center = getCenter(scr, 420, 250);
1483
1484                 wwin = wManageInternalWindow(scr, parent, None, _("Legal"), center.x, center.y, 420, 250);
1485         }
1486
1487         WSETUFLAG(wwin, no_closable, 0);
1488         WSETUFLAG(wwin, no_close_button, 0);
1489         wWindowUpdateButtonImages(wwin);
1490         wFrameWindowShowButton(wwin->frame, WFF_RIGHT_BUTTON);
1491 #ifdef XKB_BUTTON_HINT
1492         wFrameWindowHideButton(wwin->frame, WFF_LANGUAGE_BUTTON);
1493 #endif
1494         wwin->frame->on_click_right = destroyLegalPanel;
1495
1496         panel->wwin = wwin;
1497
1498         WMMapWidget(panel->win);
1499
1500         wWindowMap(wwin);
1501
1502         legalPanel = panel;
1503 }
1504
1505 /*
1506  ***********************************************************************
1507  * Crashing Dialog Panel
1508  ***********************************************************************
1509  */
1510
1511 extern WDDomain *WDWindowAttributes;
1512
1513 typedef struct _CrashPanel {
1514         WMWindow *win;          /* main window */
1515
1516         WMLabel *iconL;         /* application icon */
1517         WMLabel *nameL;         /* title of panel */
1518
1519         WMFrame *sepF;          /* separator frame */
1520
1521         WMLabel *noteL;         /* Title of note */
1522         WMLabel *note2L;        /* body of note with what happened */
1523
1524         WMFrame *whatF;         /* "what to do next" frame */
1525         WMPopUpButton *whatP;   /* action selection popup button */
1526
1527         WMButton *okB;          /* ok button */
1528
1529         Bool done;              /* if finished with this dialog */
1530         int action;             /* what to do after */
1531
1532         KeyCode retKey;
1533
1534 } CrashPanel;
1535
1536 static void handleKeyPress(XEvent * event, void *clientData)
1537 {
1538         CrashPanel *panel = (CrashPanel *) clientData;
1539
1540         if (event->xkey.keycode == panel->retKey) {
1541                 WMPerformButtonClick(panel->okB);
1542         }
1543 }
1544
1545 static void okButtonCallback(void *self, void *clientData)
1546 {
1547         CrashPanel *panel = (CrashPanel *) clientData;
1548
1549         panel->done = True;
1550 }
1551
1552 static void setCrashAction(void *self, void *clientData)
1553 {
1554         WMPopUpButton *pop = (WMPopUpButton *) self;
1555         CrashPanel *panel = (CrashPanel *) clientData;
1556
1557         panel->action = WMGetPopUpButtonSelectedItem(pop);
1558 }
1559
1560 /* Make this read the logo from a compiled in pixmap -Dan */
1561 static WMPixmap *getWindowMakerIconImage(WMScreen * scr)
1562 {
1563         WMPropList *dict, *key, *option, *value = NULL;
1564         WMPixmap *pix = NULL;
1565         char *path;
1566
1567         if (!WDWindowAttributes || !WDWindowAttributes->dictionary)
1568                 return NULL;
1569
1570         WMPLSetCaseSensitive(True);
1571
1572         key = WMCreatePLString("Logo.WMPanel");
1573         option = WMCreatePLString("Icon");
1574
1575         dict = WMGetFromPLDictionary(WDWindowAttributes->dictionary, key);
1576
1577         if (dict) {
1578                 value = WMGetFromPLDictionary(dict, option);
1579         }
1580
1581         WMReleasePropList(key);
1582         WMReleasePropList(option);
1583
1584         WMPLSetCaseSensitive(False);
1585
1586         if (value && WMIsPLString(value)) {
1587                 path = FindImage(wPreferences.icon_path, WMGetFromPLString(value));
1588
1589                 if (path) {
1590                         RColor gray;
1591
1592                         gray.red = 0xae;
1593                         gray.green = 0xaa;
1594                         gray.blue = 0xae;
1595                         gray.alpha = 0;
1596
1597                         pix = WMCreateBlendedPixmapFromFile(scr, path, &gray);
1598                         wfree(path);
1599                 }
1600         }
1601
1602         return pix;
1603 }
1604
1605 #define PWIDTH  295
1606 #define PHEIGHT 345
1607
1608 int wShowCrashingDialogPanel(int whatSig)
1609 {
1610         CrashPanel *panel;
1611         WMScreen *scr;
1612         WMFont *font;
1613         WMPixmap *logo;
1614         int screen_no, scr_width, scr_height;
1615         int action;
1616         char buf[256];
1617
1618         panel = wmalloc(sizeof(CrashPanel));
1619         memset(panel, 0, sizeof(CrashPanel));
1620
1621         screen_no = DefaultScreen(dpy);
1622         scr_width = WidthOfScreen(ScreenOfDisplay(dpy, screen_no));
1623         scr_height = HeightOfScreen(ScreenOfDisplay(dpy, screen_no));
1624
1625         scr = WMCreateScreen(dpy, screen_no);
1626         if (!scr) {
1627                 wsyserror(_("cannot open connection for crashing dialog panel. Aborting."));
1628                 return WMAbort;
1629         }
1630
1631         panel->retKey = XKeysymToKeycode(dpy, XK_Return);
1632
1633         panel->win = WMCreateWindow(scr, "crashingDialog");
1634         WMResizeWidget(panel->win, PWIDTH, PHEIGHT);
1635         WMMoveWidget(panel->win, (scr_width - PWIDTH) / 2, (scr_height - PHEIGHT) / 2);
1636
1637         logo = getWindowMakerIconImage(scr);
1638         if (logo) {
1639                 panel->iconL = WMCreateLabel(panel->win);
1640                 WMResizeWidget(panel->iconL, 64, 64);
1641                 WMMoveWidget(panel->iconL, 10, 10);
1642                 WMSetLabelImagePosition(panel->iconL, WIPImageOnly);
1643                 WMSetLabelImage(panel->iconL, logo);
1644         }
1645
1646         panel->nameL = WMCreateLabel(panel->win);
1647         WMResizeWidget(panel->nameL, 200, 30);
1648         WMMoveWidget(panel->nameL, 80, 25);
1649         WMSetLabelTextAlignment(panel->nameL, WALeft);
1650         font = WMBoldSystemFontOfSize(scr, 24);
1651         WMSetLabelFont(panel->nameL, font);
1652         WMReleaseFont(font);
1653         WMSetLabelText(panel->nameL, _("Fatal error"));
1654
1655         panel->sepF = WMCreateFrame(panel->win);
1656         WMResizeWidget(panel->sepF, PWIDTH + 4, 2);
1657         WMMoveWidget(panel->sepF, -2, 80);
1658
1659         panel->noteL = WMCreateLabel(panel->win);
1660         WMResizeWidget(panel->noteL, PWIDTH - 20, 40);
1661         WMMoveWidget(panel->noteL, 10, 90);
1662         WMSetLabelTextAlignment(panel->noteL, WAJustified);
1663 #ifdef SYS_SIGLIST_DECLARED
1664         snprintf(buf, sizeof(buf), _("Window Maker received signal %i\n(%s)."), whatSig, sys_siglist[whatSig]);
1665 #else
1666         snprintf(buf, sizeof(buf), _("Window Maker received signal %i."), whatSig);
1667 #endif
1668         WMSetLabelText(panel->noteL, buf);
1669
1670         panel->note2L = WMCreateLabel(panel->win);
1671         WMResizeWidget(panel->note2L, PWIDTH - 20, 100);
1672         WMMoveWidget(panel->note2L, 10, 130);
1673         WMSetLabelTextAlignment(panel->note2L, WALeft);
1674         WMSetLabelText(panel->note2L,
1675                        _(" This fatal error occured probably due to a bug."
1676                          " Please fill the included BUGFORM and " "report it to bugs@windowmaker.info."));
1677         WMSetLabelWraps(panel->note2L, True);
1678
1679         panel->whatF = WMCreateFrame(panel->win);
1680         WMResizeWidget(panel->whatF, PWIDTH - 20, 50);
1681         WMMoveWidget(panel->whatF, 10, 240);
1682         WMSetFrameTitle(panel->whatF, _("What do you want to do now?"));
1683
1684         panel->whatP = WMCreatePopUpButton(panel->whatF);
1685         WMResizeWidget(panel->whatP, PWIDTH - 20 - 70, 20);
1686         WMMoveWidget(panel->whatP, 35, 20);
1687         WMSetPopUpButtonPullsDown(panel->whatP, False);
1688         WMSetPopUpButtonText(panel->whatP, _("Select action"));
1689         WMAddPopUpButtonItem(panel->whatP, _("Abort and leave a core file"));
1690         WMAddPopUpButtonItem(panel->whatP, _("Restart Window Maker"));
1691         WMAddPopUpButtonItem(panel->whatP, _("Start alternate window manager"));
1692         WMSetPopUpButtonAction(panel->whatP, setCrashAction, panel);
1693         WMSetPopUpButtonSelectedItem(panel->whatP, WMRestart);
1694         panel->action = WMRestart;
1695
1696         WMMapSubwidgets(panel->whatF);
1697
1698         panel->okB = WMCreateCommandButton(panel->win);
1699         WMResizeWidget(panel->okB, 80, 26);
1700         WMMoveWidget(panel->okB, 205, 309);
1701         WMSetButtonText(panel->okB, _("OK"));
1702         WMSetButtonImage(panel->okB, WMGetSystemPixmap(scr, WSIReturnArrow));
1703         WMSetButtonAltImage(panel->okB, WMGetSystemPixmap(scr, WSIHighlightedReturnArrow));
1704         WMSetButtonImagePosition(panel->okB, WIPRight);
1705         WMSetButtonAction(panel->okB, okButtonCallback, panel);
1706
1707         panel->done = 0;
1708
1709         WMCreateEventHandler(WMWidgetView(panel->win), KeyPressMask, handleKeyPress, panel);
1710
1711         WMRealizeWidget(panel->win);
1712         WMMapSubwidgets(panel->win);
1713
1714         WMMapWidget(panel->win);
1715
1716         XSetInputFocus(dpy, WMWidgetXID(panel->win), RevertToParent, CurrentTime);
1717
1718         while (!panel->done) {
1719                 XEvent event;
1720
1721                 WMNextEvent(dpy, &event);
1722                 WMHandleEvent(&event);
1723         }
1724
1725         action = panel->action;
1726
1727         WMUnmapWidget(panel->win);
1728         WMDestroyWidget(panel->win);
1729         wfree(panel);
1730
1731         return action;
1732 }
1733
1734 /*****************************************************************************
1735  *                      About GNUstep Panel
1736  *****************************************************************************/
1737
1738 static void
1739 drawGNUstepLogo(Display * dpy, Drawable d, int width, int height,
1740                 unsigned long blackPixel, unsigned long whitePixel)
1741 {
1742         GC gc;
1743         XGCValues gcv;
1744         XRectangle rects[3];
1745
1746         gcv.foreground = blackPixel;
1747         gc = XCreateGC(dpy, d, GCForeground, &gcv);
1748
1749         XFillArc(dpy, d, gc, width / 45, height / 45,
1750                  width - 2 * width / 45, height - 2 * height / 45, 0, 360 * 64);
1751
1752         rects[0].x = 0;
1753         rects[0].y = 37 * height / 45;
1754         rects[0].width = width / 3;
1755         rects[0].height = height - rects[0].y;
1756
1757         rects[1].x = rects[0].width;
1758         rects[1].y = height / 2;
1759         rects[1].width = width - 2 * width / 3;
1760         rects[1].height = height - rects[1].y;
1761
1762         rects[2].x = 2 * width / 3;
1763         rects[2].y = height - 37 * height / 45;
1764         rects[2].width = width / 3;
1765         rects[2].height = height - rects[2].y;
1766
1767         XSetClipRectangles(dpy, gc, 0, 0, rects, 3, Unsorted);
1768         XFillRectangle(dpy, d, gc, 0, 0, width, height);
1769
1770         XSetForeground(dpy, gc, whitePixel);
1771         XFillArc(dpy, d, gc, width / 45, height / 45,
1772                  width - 2 * width / 45, height - 2 * height / 45, 0, 360 * 64);
1773
1774         XFreeGC(dpy, gc);
1775 }
1776
1777 typedef struct {
1778         WScreen *scr;
1779
1780         WWindow *wwin;
1781
1782         WMWindow *win;
1783
1784         WMLabel *gstepL;
1785         WMLabel *textL;
1786 } GNUstepPanel;
1787
1788 static GNUstepPanel *gnustepPanel = NULL;
1789
1790 static void destroyGNUstepPanel(WCoreWindow * foo, void *data, XEvent * event)
1791 {
1792         WMUnmapWidget(gnustepPanel->win);
1793
1794         WMDestroyWidget(gnustepPanel->win);
1795
1796         wUnmanageWindow(gnustepPanel->wwin, False, False);
1797
1798         wfree(gnustepPanel);
1799
1800         gnustepPanel = NULL;
1801 }
1802
1803 void wShowGNUstepPanel(WScreen * scr)
1804 {
1805         GNUstepPanel *panel;
1806         Window parent;
1807         WWindow *wwin;
1808         WMPixmap *pixmap;
1809         WMColor *color;
1810
1811         if (gnustepPanel) {
1812                 if (gnustepPanel->scr == scr) {
1813                         wRaiseFrame(gnustepPanel->wwin->frame->core);
1814                         wSetFocusTo(scr, gnustepPanel->wwin);
1815                 }
1816                 return;
1817         }
1818
1819         panel = wmalloc(sizeof(GNUstepPanel));
1820
1821         panel->scr = scr;
1822
1823         panel->win = WMCreateWindow(scr->wmscreen, "About GNUstep");
1824         WMResizeWidget(panel->win, 325, 205);
1825
1826         pixmap = WMCreatePixmap(scr->wmscreen, 130, 130, WMScreenDepth(scr->wmscreen), True);
1827
1828         color = WMCreateNamedColor(scr->wmscreen, "gray50", True);
1829
1830         drawGNUstepLogo(dpy, WMGetPixmapXID(pixmap), 130, 130, WMColorPixel(color), scr->white_pixel);
1831
1832         WMReleaseColor(color);
1833
1834         XSetForeground(dpy, scr->mono_gc, 0);
1835         XFillRectangle(dpy, WMGetPixmapMaskXID(pixmap), scr->mono_gc, 0, 0, 130, 130);
1836         drawGNUstepLogo(dpy, WMGetPixmapMaskXID(pixmap), 130, 130, 1, 1);
1837
1838         panel->gstepL = WMCreateLabel(panel->win);
1839         WMResizeWidget(panel->gstepL, 285, 64);
1840         WMMoveWidget(panel->gstepL, 20, 0);
1841         WMSetLabelTextAlignment(panel->gstepL, WARight);
1842         WMSetLabelText(panel->gstepL, "GNUstep");
1843         {
1844                 WMFont *font = WMBoldSystemFontOfSize(scr->wmscreen, 24);
1845
1846                 WMSetLabelFont(panel->gstepL, font);
1847                 WMReleaseFont(font);
1848         }
1849
1850         panel->textL = WMCreateLabel(panel->win);
1851         WMResizeWidget(panel->textL, 305, 140);
1852         WMMoveWidget(panel->textL, 10, 50);
1853         WMSetLabelTextAlignment(panel->textL, WARight);
1854         WMSetLabelImagePosition(panel->textL, WIPOverlaps);
1855         WMSetLabelText(panel->textL,
1856                        _("Window Maker is part of the GNUstep project.\n"
1857                          "The GNUstep project aims to create a free\n"
1858                          "implementation of the OpenStep(tm) specification\n"
1859                          "which is a object-oriented framework for\n"
1860                          "creating advanced graphical, multi-platform\n"
1861                          "applications. Additionally, a development and\n"
1862                          "user desktop enviroment will be created on top\n"
1863                          "of the framework. For more information about\n"
1864                          "GNUstep, please visit: www.gnustep.org"));
1865         WMSetLabelImage(panel->textL, pixmap);
1866
1867         WMReleasePixmap(pixmap);
1868
1869         WMRealizeWidget(panel->win);
1870         WMMapSubwidgets(panel->win);
1871
1872         parent = XCreateSimpleWindow(dpy, scr->root_win, 0, 0, 325, 200, 0, 0, 0);
1873
1874         XReparentWindow(dpy, WMWidgetXID(panel->win), parent, 0, 0);
1875
1876         {
1877                 WMPoint center = getCenter(scr, 325, 200);
1878
1879                 wwin = wManageInternalWindow(scr, parent, None, _("About GNUstep"), center.x, center.y, 325, 200);
1880         }
1881
1882         WSETUFLAG(wwin, no_closable, 0);
1883         WSETUFLAG(wwin, no_close_button, 0);
1884         wWindowUpdateButtonImages(wwin);
1885         wFrameWindowShowButton(wwin->frame, WFF_RIGHT_BUTTON);
1886 #ifdef XKB_BUTTON_HINT
1887         wFrameWindowHideButton(wwin->frame, WFF_LANGUAGE_BUTTON);
1888 #endif
1889         wwin->frame->on_click_right = destroyGNUstepPanel;
1890
1891         panel->wwin = wwin;
1892
1893         WMMapWidget(panel->win);
1894
1895         wWindowMap(wwin);
1896
1897         gnustepPanel = panel;
1898 }