Convert uses of XKeycodeToKeysym (deprecated) to XkbKeycodeToKeysym
[oweals/cde.git] / cde / programs / dtstyle / Backdrop.c
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these libraries and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  */
23 /* $TOG: Backdrop.c /main/7 1998/11/25 14:48:36 samborn $ */
24 /************************************<+>*************************************
25  ****************************************************************************
26  **
27  **   File:        Backdrop.c
28  **
29  **   Project:     DT 3.0 
30  **
31  **   Description: Controls the Dtstyle Backdrop dialog
32  **
33  **
34  **  (c) Copyright Hewlett-Packard Company, 1990, 1993.  
35  **
36  **
37  **
38  ****************************************************************************
39  ************************************<+>*************************************/
40
41 /*+++++++++++++++++++++++++++++++++++++++*/
42 /* include files                         */
43 /*+++++++++++++++++++++++++++++++++++++++*/
44 #include <stdio.h>
45 #include <string.h>
46 #include <stdlib.h>
47 #include <sys/types.h>
48 #include <errno.h>
49
50 #if defined(_AIX)
51 #include <sys/dir.h>
52 #else
53 #include <dirent.h>             /* opendir(), directory(3C) */
54 #endif /* _AIX */
55
56 #include <locale.h>
57 #include <X11/Xlib.h>
58 #include <Xm/MwmUtil.h>
59
60 #include <Xm/Xm.h>
61 #include <Xm/XmP.h>
62 #include <Xm/DrawnB.h>
63 #include <Xm/Form.h>
64 #include <Xm/List.h>
65 #include <Xm/VendorSEP.h>
66 #include <Xm/AtomMgr.h>
67
68 #include <Dt/DialogBox.h>
69
70 #include <Dt/Message.h>
71 #include <Dt/SessionM.h>
72 #include <Dt/HourGlass.h>
73 #include <Dt/Wsm.h>
74 #include <Dt/UserMsg.h>
75
76 #include "Help.h"
77 #include "Main.h"
78 #include "SaveRestore.h"
79
80 /*+++++++++++++++++++++++++++++++++++++++*/
81 /* include extern functions              */
82 /*+++++++++++++++++++++++++++++++++++++++*/
83 #include "Backdrop.h"
84
85
86 /*+++++++++++++++++++++++++++++++++++++++*/
87 /* Local #defines                        */
88 /*+++++++++++++++++++++++++++++++++++++++*/
89 #define MAX_STR_LEN         128
90 #define B_OK_BUTTON           1
91 #define B_APPLY_BUTTON        2
92 #define B_CANCEL_BUTTON       3
93 #define B_HELP_BUTTON         4
94
95 #define ERR2   ((char *)GETMESSAGE(11, 2, "The backdrop portion of the Style Manager\n\
96 will not operate because there are no backdrop\nfiles available. Check $HOME/.dt/errorlog."))
97
98 /*+++++++++++++++++++++++++++++++++++++++*/
99 /* Internal Functions                    */
100 /*+++++++++++++++++++++++++++++++++++++++*/
101
102 static int CreateBackdropDialog( Widget parent) ;
103 static void MoreBitmaps( void ) ;
104 static ReadBitmaps( void ) ;
105 static Boolean CreatePixmaps( void ) ;
106 static ReadBitmapDirectory( char *dir ) ;
107 static void DrawBitmap( 
108                         Widget w,
109                         XtPointer client_data,
110                         XtPointer call_data) ;
111 static void SizeBitmap( 
112                         Widget w,
113                         XtPointer client_data,
114                         XtPointer call_data) ;
115 static XmString * MakeListStrings( void ) ;
116 static void FreeListStrings( XmString *listPtr) ;
117 static void ListCB( 
118                         Widget w,
119                         XtPointer client_data,
120                         XtPointer call_data) ;
121 static void ButtonCB( 
122                         Widget w,
123                         XtPointer client_data,
124                         XtPointer call_data) ;
125 static void GetColors( void ) ;
126 static void FreeAll( void ) ;
127 static void _DtMapCB( 
128                         Widget w,
129                         XtPointer client_data,
130                         XtPointer call_data) ;
131
132
133 /*+++++++++++++++++++++++++++++++++++++++*/
134 /* Internal Variables                    */
135 /*+++++++++++++++++++++++++++++++++++++++*/
136
137 typedef struct {
138     Widget   drawnButton;
139     char   **dirList;
140     int      dirCount;
141     char   **tmpBitmapNames;
142     int      tmpNumBitmaps;
143     int      tmpMaxNumBitmaps;
144     char   **bitmapNames;
145     char   **bitmapDescs;
146     Pixmap  *bitmaps;
147     int      numBitmaps;
148     int      maxNumBitmaps;
149     int      selected;
150     GC       gc;
151     int      width, height;
152     int      shadow;
153     Pixel    fg, bg;
154     char    *errStr;
155     char     noBitmaps;
156     Boolean  newColors;
157 } Backdrops, *BackdropsPtr;
158 static Backdrops backdrops; 
159
160 static saveRestore save = {FALSE, 0, };
161 char *BACKDROPSDLG = "backdropsDialog";
162
163 /*
164  *   copy of the system backdrop description file for the 
165  *   current locale in xrm form
166  */
167 static XrmDatabase sys_bd_DB = NULL;
168
169 /*
170  *   copy of the admin backdrop description file for the 
171  *   current locale in xrm form
172  */
173 static XrmDatabase adm_bd_DB = NULL;
174
175 /*
176  *   copy of the user's home backdrop description file for the 
177  *   current locale in xrm form
178  */
179 static XrmDatabase hm_bd_DB = NULL;
180
181 /*
182  *   final combination of the admin & system data bases 
183  */
184 static XrmDatabase bd_DB = NULL;
185
186
187
188 /*+++++++++++++++++++++++++++++++++++++++*/
189 /* build_dirList                         */
190 /*+++++++++++++++++++++++++++++++++++++++*/
191
192 char ** 
193 build_dirList(char * dirStr, 
194                  int * count)
195 {
196    char tokenSep[] = ":";
197    char * token;
198    char ** dirList = NULL;
199    int i = 0;
200    char * tmpStr;
201    int len = strlen(dirStr);
202    *count = 0;
203
204    tmpStr = (char *)XtCalloc(1, len + 1);
205    strcpy(tmpStr, dirStr);
206    token = strtok(tmpStr, tokenSep);
207    while(token != NULL)
208      {
209        ++(i);
210        token = strtok(NULL, tokenSep);
211      }
212
213    if (i == 0)
214        return (NULL);
215
216    dirList = (char **) XtCalloc(1, i * sizeof(char *));
217    if( dirList )
218      {
219        strcpy(tmpStr, dirStr); 
220        token = strtok(tmpStr, tokenSep);
221        *count=0;
222        while(token != NULL)
223          {
224            dirList[*count] = (char *) XtCalloc(1, strlen( token ) + 1);
225            strcpy(dirList[*count], token);
226            token = strtok(NULL, tokenSep);
227            ++(*count);
228          }
229      }
230
231    XtFree ((char *) tmpStr);
232    return(dirList);
233  }
234
235
236
237 /*+++++++++++++++++++++++++++++++++++++++*/
238 /* free_dirList                          */
239 /*+++++++++++++++++++++++++++++++++++++++*/
240
241 void
242 free_dirList(char ** dirList, 
243                     int count)
244
245 {
246   int   i;
247
248   if (dirList == NULL)
249     return;
250   for (i=0; i<count; i++)
251     XtFree((char *) dirList[i]);
252   
253   XtFree ((char *) dirList);
254 }
255
256
257 /************************************************************************
258  *  SelectCurrentBackdrop() - Selects current backdrop in list
259  *
260  ************************************************************************/
261 void SelectCurrentBackdrop(int callback)
262 {
263     DtWsmWorkspaceInfo   *wInfo=NULL;
264     Atom             aWS;
265     Widget list;
266     char *backdropName;
267     int i;
268
269     if ((DtWsmGetCurrentWorkspace (style.display, style.root, &aWS) 
270                 != Success) ||
271         (DtWsmGetWorkspaceInfo (style.display, style.root, aWS, &wInfo)
272                 != Success))
273     {
274       return;
275     }
276       
277     list = XtNameToWidget(style.backdropDialog, "*bitmapList");
278
279     backdropName = XmGetAtomName(style.display, wInfo->backdropName);
280
281     for (i = 0; i < backdrops.numBitmaps; i++) {
282       if (strcmp(backdrops.bitmapNames[i], backdropName) == 0) {
283         XmListSelectPos (list, i + 1, callback);
284         XmListSetPos(list, i + 1);
285         backdrops.selected = i;
286       }
287     }
288
289     XtFree((char *) backdropName);
290     XtFree((char *) wInfo);
291 }
292
293 /************************************************************************
294  *  BackdropDialog() - Create backdrop selection dialog first time up.
295  *           If it has already been created, map it.
296  ************************************************************************/
297 void 
298 BackdropDialog(
299         Widget parent )
300 {
301     int i;
302     
303     if (style.backdropDialog == NULL) 
304     {
305         _DtTurnOnHourGlass(parent);  
306         if (!CreateBackdropDialog(parent)) { 
307            _DtTurnOffHourGlass(parent);  
308            return;
309         }
310         SelectCurrentBackdrop(False);
311         XtManageChild(style.backdropDialog);
312         XSync(style.display, 0);
313         XmUpdateDisplay(style.backdropDialog);
314         _DtTurnOffHourGlass(parent);  
315
316     }
317     else
318     {
319         SelectCurrentBackdrop(True);
320         XtManageChild(style.backdropDialog);
321         raiseWindow(XtWindow(XtParent(style.backdropDialog)));
322         XmUpdateDisplay(style.backdropDialog);
323     }
324 }
325
326
327 /************************************************************************
328  *   CreateBackdropDialog()
329  *           Create the Backdrop Dialog
330  ************************************************************************/
331 static int 
332 CreateBackdropDialog(
333         Widget parent )
334 {
335     int     i, n;
336     Arg              args[20];
337     Widget           mainForm;
338     Widget           list;
339     XmString         strings[NUM_LABELS+1];
340     XmString        *listStrings;
341     char            *bd_desc;
342     char            *lang;
343
344
345     if (backdrops.noBitmaps) 
346     {
347         ErrDialog (backdrops.errStr, style.shell);
348         return 0;
349     }
350
351     /* initialize backdrop data */
352     backdrops.bitmapNames = NULL;
353     backdrops.bitmaps = NULL;
354     backdrops.numBitmaps = 0;
355     backdrops.maxNumBitmaps = 100;
356     backdrops.selected = -1;
357     backdrops.gc = NULL;
358     backdrops.errStr = NULL;
359     backdrops.shadow = 2;
360     backdrops.width = 200 - 2*backdrops.shadow;
361     backdrops.height = 200 - 2*backdrops.shadow;
362     backdrops.newColors = True;
363
364     
365     /* load the backdrop description data base for the given locale*/
366     /* from that locale's description file from the system location */
367     lang = setlocale (LC_CTYPE,NULL);
368
369 #ifdef hpux      /* hpux-specific parsing of the locale string */
370                  /* The following code is identical to the
371                     ExtractLocaleName function in WmResParse.c
372                     from dtwm
373                  */
374 #define MAXLOCALE       64      /* buffer size of locale name */
375
376 {   char           *start;
377     char           *end;
378     int             len;
379     static char     buf[MAXLOCALE];
380
381     /*  If lang has a substring ":<category>;", extract <category>
382      *  from the first such occurrence as the locale name.
383      */
384
385     start = lang;
386     if (start = strchr (lang, ':')) {
387         start++;
388         if (end = strchr (start, ';')) {
389             len = end - start;
390             strncpy(buf, start, len);
391             *(buf + len) = '\0';
392             lang = buf;
393       }
394     }
395 }
396 #endif  /* hpux */
397
398     bd_desc = (char *)XtMalloc(strlen("/usr/dt/backdrops/desc.") + strlen(lang) + 1);
399     strcpy (bd_desc,"/usr/dt/backdrops/desc.");
400     strcat (bd_desc, lang);
401     if(sys_bd_DB = XrmGetFileDatabase (bd_desc))
402         XrmMergeDatabases(sys_bd_DB, &bd_DB);
403     XtFree(bd_desc);
404     
405     /* load the backdrop description data base for the given locale*/
406     /* from that locale's description file from the admin location */
407     bd_desc = (char *)XtMalloc(strlen("/etc/dt/backdrops/desc.") + strlen(lang) + 1);
408     strcpy (bd_desc,"/etc/dt/backdrops/desc.");
409     strcat (bd_desc, lang);
410     if (adm_bd_DB = XrmGetFileDatabase (bd_desc))
411         XrmMergeDatabases(adm_bd_DB, &bd_DB);
412     XtFree(bd_desc);
413
414     /* load the backdrop description from the user's .dt/backdrops directory */
415     /* regardless of locale */
416     bd_desc = (char *)XtMalloc(strlen(style.home) + strlen("/.dt/backdrops/desc.backdrops") + 1);
417     strcpy (bd_desc, style.home);
418     strcat (bd_desc, "/.dt/backdrops/desc.backdrops");
419     if (hm_bd_DB = XrmGetFileDatabase (bd_desc))
420         XrmMergeDatabases(hm_bd_DB, &bd_DB);
421     XtFree(bd_desc);
422
423     /* Set up DialogBox button labels. */
424     strings[0] = XmStringCreateLocalized ((String) _DtOkString);
425     strings[1] = XmStringCreateLocalized ((String) _DtApplyString);
426     strings[2] = XmStringCreateLocalized ((String) _DtCloseString);
427     strings[3] = XmStringCreateLocalized ((String) _DtHelpString);
428
429     /* saveRestore
430      * Note that save.poscnt has been initialized elsewhere.
431      * save.posArgs may contain information from restoreBackdrop().*/
432
433     /* create the dialog box with shell */
434
435     XtSetArg (save.posArgs[save.poscnt], XmNbuttonCount, NUM_LABELS+1);
436                                                                  save.poscnt++;
437     XtSetArg (save.posArgs[save.poscnt], XmNbuttonLabelStrings, strings);
438                                                                  save.poscnt++;
439     XtSetArg (save.posArgs[save.poscnt], XmNdefaultPosition, False);
440                                                                  save.poscnt++;
441     XtSetArg (save.posArgs[save.poscnt], XmNallowOverlap, False);
442                                                                  save.poscnt++;
443     style.backdropDialog = __DtCreateDialogBoxDialog (parent, BACKDROPSDLG,
444                                                      save.posArgs, save.poscnt);
445     XtAddCallback(style.backdropDialog, XmNcallback, ButtonCB, NULL);
446     XtAddCallback(style.backdropDialog, XmNmapCallback, _DtMapCB, parent);
447     XtAddCallback(style.backdropDialog, XmNhelpCallback,
448             (XtCallbackProc)HelpRequestCB, (XtPointer)HELP_BACKDROP_DIALOG);
449
450     /* free compound strings now */
451     XmStringFree (strings[0]);
452     XmStringFree (strings[1]);
453     XmStringFree (strings[2]);
454     XmStringFree (strings[3]);
455
456     n = 0;
457     XtSetArg (args[n], XmNtitle, ((char *)GETMESSAGE(11, 12, "Style Manager - Backdrop"))); n++;
458     XtSetArg (args[n], XmNuseAsyncGeometry, True); n++;
459     XtSetValues (XtParent(style.backdropDialog), args, n);
460
461     /*  get bitmap data */
462     if (!ReadBitmaps())  return 0;         /* uses style.backdropDialog */
463
464     /* create the form to go in to dialog box as the work area */
465     n = 0;
466     XtSetArg(args[n], XmNhorizontalSpacing, style.horizontalSpacing); n++;
467     XtSetArg(args[n], XmNverticalSpacing, style.verticalSpacing); n++;
468     XtSetArg (args[n], XmNchildType, XmWORK_AREA);  n++;
469
470     XtSetArg (args[n], XmNallowOverlap, False);  n++;
471     mainForm = XmCreateForm (style.backdropDialog, "backdropsForm", args, n);
472
473     /* create the scrolled list of bitmap names... first create XmStrings */
474     listStrings = MakeListStrings ();
475     n = 0;
476     XtSetArg (args[n], XmNautomaticSelection, True);              n++;
477     XtSetArg (args[n], XmNselectionPolicy, XmBROWSE_SELECT);      n++;
478     XtSetArg (args[n], XmNitems, listStrings);                    n++;
479     XtSetArg (args[n], XmNitemCount, backdrops.numBitmaps);       n++;
480     list = XmCreateScrolledList (mainForm, "bitmapList", args, n);
481     XtAddCallback (list, XmNbrowseSelectionCallback, ListCB, (XtPointer)NULL);
482     FreeListStrings (listStrings);            /* after list has copied */
483
484     /* set up attachments for scrolled list itself */
485     n = 0;
486     XtSetArg (args[n], XmNtopAttachment, XmATTACH_FORM);          n++;
487     XtSetArg (args[n], XmNrightAttachment, XmATTACH_FORM);        n++;
488     XtSetArg (args[n], XmNbottomAttachment, XmATTACH_FORM);       n++;
489     XtSetValues (XtParent(list), args, n);
490
491     /*   Create drawing area for the bitmap  */
492     n = 0;
493     XtSetArg (args[n], XmNshadowType, XmSHADOW_IN);                     n++;
494     XtSetArg (args[n], XmNshadowThickness, backdrops.shadow);           n++;
495     XtSetArg (args[n], XmNhighlightThickness, 0);                       n++;
496     XtSetArg (args[n], XmNrightAttachment, XmATTACH_WIDGET);            n++;
497     XtSetArg (args[n], XmNrightWidget, XtParent(list));                 n++;
498     XtSetArg (args[n], XmNtopAttachment, XmATTACH_FORM);                n++;
499     XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM);               n++;
500     XtSetArg (args[n], XmNbottomAttachment, XmATTACH_FORM);             n++;
501     XtSetArg (args[n], XmNborderWidth, 0);                              n++;
502     XtSetArg (args[n], XmNwidth, backdrops.width+2*backdrops.shadow);   n++;
503     XtSetArg (args[n], XmNheight, backdrops.height+2*backdrops.shadow); n++;
504     XtSetArg (args[n], XmNtraversalOn, False);                          n++;  
505     backdrops.drawnButton = XmCreateDrawnButton (mainForm, "bitmap", args, n);
506     XtAddCallback (backdrops.drawnButton, XmNexposeCallback, DrawBitmap, NULL);
507     XtAddCallback (backdrops.drawnButton, XmNresizeCallback, SizeBitmap, NULL);
508
509     /* manage all of the widgets */
510     XtManageChild (mainForm);
511     XtManageChild (backdrops.drawnButton);
512     XtManageChild (list);
513
514     return 1;
515 }
516
517
518 /************************************************************************
519  *   MoreBitmaps()
520  *           Create space for more bitmap entries
521  ************************************************************************/
522 static void 
523 MoreBitmaps( void )
524 {
525     int   newSize;
526
527     /* allocate space for icon names */
528     newSize =  (backdrops.maxNumBitmaps + 100) * sizeof(char *);
529     backdrops.bitmapNames = (char **) XtRealloc((char *)backdrops.bitmapNames, 
530                                                 newSize);
531
532     /* now allocate new bitmap space */
533     newSize =  (backdrops.maxNumBitmaps + 100) * sizeof(Pixmap);
534     backdrops.bitmaps = (Pixmap *)XtRealloc((char *)backdrops.bitmaps, newSize);
535
536     backdrops.maxNumBitmaps += 100;
537 }
538
539 /************************************************************************
540  * cmpstringp()
541  * qsort() sort function, used for sorting bitmap names into alphabetical order
542  * can't use strcmp() due to char** rather than char*
543  ************************************************************************/
544 static int
545 cmpstringp(const void *p1, const void *p2)
546 {
547   return strcmp(*(char * const *) p1, *(char * const *) p2);
548 }
549
550 /************************************************************************
551  *   ReadBitmaps()
552  *   Create an array of bitmaps by reading backdrop directories in the
553  *   following order overriding any duplicates:
554  *   1) Read the system location /usr/dt/backdrops
555  *   2) Read the admin location /etc/dt/backdrops
556  *   3) Read the directories specified by the backdropDirectories
557  *      resource.
558  *   4) Read the user's home directory /$HOME/.dt/backdrops.
559  ************************************************************************/
560 static 
561      ReadBitmaps( void )
562 {
563   int            status;
564   Pixmap         tmpPix = 0;
565   int            width, height, x, y;
566   Window         win;
567   int            num;
568   int   i;
569   char          *string;
570   /* allocate space for temporary bitmap info */
571   backdrops.tmpBitmapNames = (char **)XtCalloc(100, sizeof(char *));
572   backdrops.tmpMaxNumBitmaps = 100;
573   backdrops.tmpNumBitmaps = 0;
574   
575   /* read system backdrop directory */
576     ReadBitmapDirectory("/usr/dt/backdrops");
577   /* read sys admin backdrop directory */
578   ReadBitmapDirectory("/etc/dt/backdrops");
579   
580   /* Parse the backdropDirectories resource to get the individual directories */
581   if (style.xrdb.backdropDir)
582     {
583       backdrops.dirList = build_dirList(style.xrdb.backdropDir, &backdrops.dirCount);
584       
585       /* compile the list of bitmaps */
586       for (i=0; i<backdrops.dirCount; i++)
587         ReadBitmapDirectory(backdrops.dirList[i]);
588     }
589   
590   /* read the directory $HOME/.dt/backdrops */
591   string = (char *)XtMalloc(strlen(style.home) + strlen("/.dt/backdrops") + 1);
592   if (string != NULL)
593   {
594     sprintf(string, "%s/.dt/backdrops", style.home);
595     ReadBitmapDirectory(string);
596     XtFree(string);
597   }
598
599   if (backdrops.tmpNumBitmaps == 0)
600     {
601       /* give error dialog, free space, and return */
602       backdrops.errStr = (char *)XtMalloc(strlen(ERR2) + 1);
603       sprintf(backdrops.errStr, "%s", ERR2);
604       ErrDialog (backdrops.errStr, style.shell); 
605       FreeAll();      
606       free_dirList(backdrops.dirList, backdrops.dirCount);
607       return 0;
608     }
609
610   /* Sort the list into alphanetical order */
611   qsort(backdrops.tmpBitmapNames, backdrops.tmpNumBitmaps, sizeof(char *), cmpstringp);
612   
613   /* get the fg/bg colors from Dtwm */
614   if (backdrops.newColors)
615     {
616       GetColors();
617       backdrops.newColors = False;
618     }   
619   
620     /* create all the pixmaps */
621   if (!CreatePixmaps())
622     {
623       /* give error dialog, free space, and return */
624       backdrops.errStr = (char *)XtMalloc(strlen(ERR2) + 1);
625       sprintf(backdrops.errStr, "%s", ERR2);
626       ErrDialog (backdrops.errStr, style.shell); 
627       FreeAll();  
628       free_dirList(backdrops.dirList, backdrops.dirCount);
629       return 0;
630     }
631   
632   
633   if (backdrops.selected == -1) backdrops.selected = 0;   
634   
635   return 1;
636 }
637
638
639
640 /************************************************************************
641  *   CreatePixmaps()
642  *           Create the pixmpas in the backdrop list
643              with workprocs 10 at a time
644  ************************************************************************/
645 static Boolean
646 CreatePixmaps( void )
647
648 {
649     static int     pixmapsCreated=0;
650     int            i;
651     Pixmap         tmpPixmap;
652     
653     backdrops.numBitmaps = 0;
654
655     /* allocate space for real bitmap info */
656     backdrops.bitmapNames = (char **)XtCalloc(100, sizeof(char *));
657     backdrops.bitmaps = (Pixmap *)XtCalloc(100, sizeof(Pixmap));
658
659     for (i=0; i<backdrops.tmpNumBitmaps; i++)
660     {
661         tmpPixmap = XmGetPixmap (style.screen, 
662                                  backdrops.tmpBitmapNames[i], 
663                                  backdrops.fg, backdrops.bg); 
664         if (tmpPixmap != XmUNSPECIFIED_PIXMAP)
665         {
666             if (backdrops.numBitmaps == backdrops.maxNumBitmaps)
667                 MoreBitmaps();
668
669             backdrops.bitmapNames[backdrops.numBitmaps] = 
670                     backdrops.tmpBitmapNames[i];
671             backdrops.bitmaps[backdrops.numBitmaps] = tmpPixmap;
672  
673             backdrops.numBitmaps++;
674         }
675
676     }
677     if (backdrops.numBitmaps)
678         return(True);
679     else
680         return(False);
681
682 }
683
684
685 /************************************************************************
686  *   ReadBitmapDirectory()
687  *           Create an array of bitmap names overriding duplicates
688  ************************************************************************/
689 static
690 ReadBitmapDirectory( 
691     char *dir )
692
693 {
694     DIR            *dirp;
695     struct dirent  *filep;
696     int             i;
697     Boolean         duplicate;
698     char           *name;
699     int             stat_result;
700     struct stat     stat_buf;
701     char           *statPath, *pStatPath;
702     int             newSize;
703
704     /* open the backdrops directory */
705     if ((dirp = opendir(dir)) == NULL)
706     {
707         /* print message to errorlog, free space, and return */
708       return 0;
709     }
710     
711     /* create string to contain complete path */
712     statPath = (char *) XtMalloc(strlen(dir) + MAX_STR_LEN + 2);
713     strcpy (statPath, dir);
714     strcat (statPath, "/");
715     pStatPath = statPath + strlen(statPath);
716
717     filep = readdir(dirp);
718
719     while (filep != NULL)
720     {
721         /* append filename to stat path */
722         strcpy (pStatPath, filep->d_name);
723
724         /* stat the file */
725         if ((stat_result = stat (statPath, &stat_buf)) != 0)
726         {
727             filep = readdir(dirp);
728             continue;
729         }
730             
731         /* skip directories */
732         if ((stat_buf.st_mode & S_IFMT) == S_IFDIR)
733         {
734             filep = readdir(dirp);
735             continue; 
736         }
737         
738         name = (char *) XtMalloc(strlen(filep->d_name) + 1);
739         strcpy (name, filep->d_name);
740
741         /* strip suffix off filename if it's a .pm or .bm
742          * motif requires other formats like jpg, png etc to
743          * have the extension on to work with the XmGetPixmap() calls */
744         if(strlen(name) > 3
745            && (0 == strcmp(name + strlen(name) - 3, ".pm")
746                || 0 == strcmp(name + strlen(name) - 3, ".bm")))
747         {
748           (void)strtok(name, ".");
749         }
750
751
752         /* check for duplicates */
753         duplicate = 0;
754         for (i=0; i<backdrops.tmpNumBitmaps; i++)
755         {
756             if (!strcmp(backdrops.tmpBitmapNames[i], name))
757             {
758                 duplicate = 1;
759                 break;                
760             }
761         }
762         
763         if (!duplicate)
764         {
765             /* add to the temporary bitmap list */
766
767             if (backdrops.tmpNumBitmaps == backdrops.tmpMaxNumBitmaps)
768             {
769                 /* allocate space for more temporary bitmap info */
770                 newSize =  (backdrops.tmpMaxNumBitmaps + 100) * sizeof(char *);
771                 backdrops.tmpBitmapNames = 
772                     (char **)XtRealloc((char *)backdrops.tmpBitmapNames, newSize);
773                 backdrops.tmpMaxNumBitmaps += 100;
774             }
775
776             backdrops.tmpBitmapNames[backdrops.tmpNumBitmaps] = 
777                 (char *) XtMalloc(strlen(name)+1);
778             strcpy (backdrops.tmpBitmapNames[backdrops.tmpNumBitmaps], name);
779
780             backdrops.tmpNumBitmaps++;
781         }
782
783         filep = readdir(dirp);
784         XtFree(name);
785     }
786
787     XtFree(statPath);
788
789
790     closedir (dirp);
791     return 1;
792 }
793
794
795 /************************************************************************
796  *   DrawBitmap()
797  *           This is the exposeCallback for the bitmap drawing area.
798  ************************************************************************/
799 static void 
800 DrawBitmap(
801         Widget w,
802         XtPointer client_data,
803         XtPointer call_data )
804 {
805     XGCValues     gcValues;
806     Arg           args[3];
807         
808     if (backdrops.selected == -1)
809         return;
810
811     if (backdrops.newColors)
812     {
813         GetColors();
814
815         /* we could keep track of which tile pixmaps need to be updated
816            since the last workspace change, but for now simply regenerate 
817            each pixmap as it is selected after a workspace change has 
818            occurred */
819
820         /* backdrops.newColors = False; */
821     }
822
823     if (backdrops.gc == NULL)
824     {
825         gcValues.background = backdrops.bg;
826         gcValues.foreground = backdrops.fg;
827         gcValues.fill_style = FillTiled;
828         gcValues.tile = backdrops.bitmaps[backdrops.selected];
829
830         backdrops.gc = XCreateGC (style.display, XtWindow(w), 
831                                 GCForeground | GCBackground | 
832                                 GCTile | GCFillStyle, &gcValues);
833     }
834
835     XFillRectangle (style.display, XtWindow(w), backdrops.gc, backdrops.shadow,
836                     backdrops.shadow, backdrops.width, backdrops.height);
837 }
838
839
840 /************************************************************************
841  *   SizeBitmap()
842  *           This is the resizeCallback for the bitmap drawing area.
843  ************************************************************************/
844 static void 
845 SizeBitmap(
846         Widget w,
847         XtPointer client_data,
848         XtPointer call_data )
849 {
850     backdrops.width = XtWidth(w) - 2*backdrops.shadow;
851     backdrops.height = XtHeight(w) - 2*backdrops.shadow;
852 }
853
854
855 /************************************************************************
856  *   MakeListStrings()
857  *           Make XmStrings from the bitmap descriptions, to pass into list.
858  *  
859  ************************************************************************/
860 static XmString * 
861 MakeListStrings( void )
862 {
863     int         i;
864     XmString   *list;
865     char       *name_str;
866     char       *class_str;
867     char       *str_type_return;
868     XrmValue    value_return;
869     
870     /* allocate space for bitmap descriptions */
871     backdrops.bitmapDescs = (char **)XtCalloc(backdrops.numBitmaps, sizeof(char *));
872     
873     for (i=0; i<backdrops.numBitmaps; i++)
874       {
875         if (bd_DB !=NULL)
876           {
877             name_str = (char *) XtMalloc(strlen("backdrops.") + 
878                                          strlen(backdrops.bitmapNames[i]) +
879                                          strlen(".desc") + 1);
880             
881             class_str = (char *) XtMalloc(strlen("Backdrops.") + 
882                                           strlen(backdrops.bitmapNames[i]) + 
883                                           strlen(".Desc") + 1);
884             strcpy(name_str, "backdrops.");
885             strcpy(class_str, "Backdrops.");
886             strcat(name_str, backdrops.bitmapNames[i]);
887             strcat(class_str, backdrops.bitmapNames[i]);
888             strcat(name_str, ".desc");
889             strcat(class_str, ".Desc");
890
891             if (XrmGetResource (bd_DB, name_str, class_str, &str_type_return, &value_return))
892               {
893                 /* make copy of resource value */
894                 backdrops.bitmapDescs[i] = (char *) XtMalloc(value_return.size + 1);
895                 strcpy (backdrops.bitmapDescs[i], value_return.addr);
896               }    
897             else
898               {   
899                 backdrops.bitmapDescs[i] = (char *) XtMalloc(strlen(backdrops.bitmapNames[i]) + 1);
900                 strcpy(backdrops.bitmapDescs[i], backdrops.bitmapNames[i]);
901               }
902           }
903         else
904           {       
905             backdrops.bitmapDescs[i] = (char *) XtMalloc(strlen(backdrops.bitmapNames[i]) + 1);
906             strcpy(backdrops.bitmapDescs[i], backdrops.bitmapNames[i]);
907           }
908       }
909
910     list = (XmString *) XtCalloc(backdrops.numBitmaps, sizeof(XmString));
911     
912     for (i = 0; i < backdrops.numBitmaps; i++)
913     {
914         list[i] = XmStringCreateLocalized (backdrops.bitmapDescs[i]);
915     }
916
917     return (list);
918 }
919
920
921 /************************************************************************
922  *   FreeListStrings()
923  *           Free XmStrings from the bitmap names, passed into list.
924  ************************************************************************/
925 static void 
926 FreeListStrings(
927         XmString *listPtr )
928 {
929     int         i;
930     int         n;
931     XmString   *list = listPtr;
932
933     for (i = 0; i < backdrops.numBitmaps; i++)
934     {
935         if (list[i]) XmStringFree(list[i]);
936     }
937     XtFree ((char *)list);
938 }
939
940
941 /************************************************************************
942  *   ListCB()
943  *           Get the bitmap selected from the list
944  ************************************************************************/
945 static void 
946 ListCB(
947         Widget w,
948         XtPointer client_data,
949         XtPointer call_data )
950 {
951     XmListCallbackStruct  *cb = (XmListCallbackStruct *)call_data;
952
953     backdrops.selected = cb->item_position - 1;
954
955     XSetTile (style.display, backdrops.gc, 
956               backdrops.bitmaps[backdrops.selected]);
957
958     DrawBitmap (backdrops.drawnButton, NULL, NULL);
959 }
960
961
962
963 /************************************************************************
964  *   ButtonCB()
965  *          
966  ************************************************************************/
967 static void 
968 ButtonCB(
969         Widget w,
970         XtPointer client_data,
971         XtPointer call_data )
972 {
973     int      n, num;
974     Arg      args[MAX_ARGS];
975
976     DtDialogBoxCallbackStruct *cb = (DtDialogBoxCallbackStruct *) call_data;
977
978     switch (cb->button_position)
979     {
980       case B_APPLY_BUTTON:
981           /* send message to update backdrop */
982
983           num = backdrops.selected;
984
985           _DtWsmChangeBackdrop(style.display, style.root, 
986                              backdrops.bitmapNames[num], 
987                              backdrops.bitmaps[num]);
988           break;
989
990       case B_OK_BUTTON:  
991           /* send message to update backdrop */
992
993           num = backdrops.selected;
994
995           _DtWsmChangeBackdrop(style.display, style.root,
996                              backdrops.bitmapNames[num],
997                              backdrops.bitmaps[num]);
998           XtUnmanageChild(w);
999           break;
1000
1001       case B_CANCEL_BUTTON:            /* close */
1002           XtUnmanageChild(w);
1003           break;
1004
1005       case B_HELP_BUTTON:
1006           XtCallCallbacks(style.backdropDialog, XmNhelpCallback, (XtPointer)NULL);
1007           break;
1008
1009       default:
1010           break;
1011     }
1012 }
1013
1014
1015 /************************************************************************
1016  *   CheckWorkspace()
1017  *           Workspace may have changed, so get current workspace
1018  *           colors and draw the backdrop bitmap
1019  *          
1020  ************************************************************************/
1021 void 
1022 CheckWorkspace( void )
1023 {
1024     backdrops.newColors = True;         /* need to get new colors */
1025     if (style.backdropDialog && XtIsManaged(style.backdropDialog))
1026     {
1027         DrawBitmap (backdrops.drawnButton, NULL, NULL);
1028     }
1029 }
1030
1031
1032 /************************************************************************
1033  *   GetColors()
1034  *           Get current workspace colors, and update GC if needed
1035  *          
1036  ************************************************************************/
1037 static void 
1038 GetColors( void )
1039 {
1040     DtWsmWorkspaceInfo   *wInfo=NULL;
1041     unsigned long    num=0;
1042     Pixel            fg, bg;
1043     XGCValues        gcValues;
1044     Atom             aWS;
1045
1046     if ((DtWsmGetCurrentWorkspace (style.display, style.root, &aWS) 
1047                 == Success) &&
1048         (DtWsmGetWorkspaceInfo (style.display, style.root, aWS, &wInfo)
1049                 == Success))
1050     {
1051         backdrops.bg = wInfo->bg;
1052         backdrops.fg = wInfo->fg;
1053         DtWsmFreeWorkspaceInfo (wInfo);
1054     }
1055     else 
1056     {
1057         backdrops.bg = 0;
1058         backdrops.fg = 1;
1059     }
1060
1061     if (backdrops.gc)      /* update the gc if there is one */
1062     {
1063         gcValues.background = backdrops.bg;
1064         gcValues.foreground = backdrops.fg;
1065
1066         /* free old pixmap */
1067         XmDestroyPixmap(style.screen, 
1068                         backdrops.bitmaps[backdrops.selected]);
1069
1070         /* allocate new pixmap */
1071         backdrops.bitmaps[backdrops.selected] = 
1072             XmGetPixmap (style.screen, 
1073                          backdrops.bitmapNames[backdrops.selected], 
1074                          backdrops.fg, backdrops.bg); 
1075
1076         gcValues.tile = backdrops.bitmaps[backdrops.selected];
1077
1078         XChangeGC (style.display, backdrops.gc, 
1079                    GCForeground | GCBackground | GCTile, &gcValues);
1080     }
1081 }
1082
1083
1084 /************************************************************************
1085  * FreeAll()
1086  *        Free some space that was allocated for backdrops
1087  ************************************************************************/
1088 static void 
1089 FreeAll( void )
1090 {
1091     int i;
1092
1093     /* set no bitmaps flag, so we won't try to get them next time */ 
1094     backdrops.noBitmaps = 1;
1095
1096     /* free temporary list of backdrop names */
1097     for (i = 0; i < backdrops.tmpNumBitmaps; i++)
1098         if (backdrops.tmpBitmapNames[i]) 
1099             XtFree(backdrops.tmpBitmapNames[i]);
1100     XtFree ((char *)backdrops.tmpBitmapNames);
1101     XtFree ((char *)backdrops.bitmapNames);
1102
1103     /* free backdrop bitmaps */
1104     for (i = 0; i < backdrops.numBitmaps; i++) {
1105         if (backdrops.bitmaps[i]) 
1106             XFreePixmap (style.display, backdrops.bitmaps[i]);
1107     if (backdrops.numBitmaps)
1108         XtFree((char *)backdrops.bitmaps);  
1109     }
1110
1111     /* destory widgets (via first parent) */
1112     XtDestroyWidget (XtParent(style.backdropDialog));
1113     style.backdropDialog = NULL;
1114 }
1115
1116
1117 /************************************************************************
1118  * _DtMapCB
1119  *
1120  ************************************************************************/
1121 static void 
1122 _DtMapCB(
1123         Widget w,
1124         XtPointer client_data,
1125         XtPointer call_data )
1126 {
1127
1128     DtWsmRemoveWorkspaceFunctions(style.display, XtWindow(XtParent(w)));
1129
1130     if (!save.restoreFlag)
1131         putDialog((Widget)client_data, w);
1132
1133     XtRemoveCallback(style.backdropDialog, XmNmapCallback, _DtMapCB, NULL);
1134 }
1135
1136
1137 /************************************************************************
1138  * restoreBackdrop()
1139  *
1140  * restore any state information saved with saveBackdrop.
1141  * This is called from restoreSession with the application
1142  * shell and the special xrm database retrieved for restore.
1143  ************************************************************************/
1144 void 
1145 restoreBackdrop(
1146         Widget shell,
1147         XrmDatabase db )
1148 {
1149     XrmName xrm_name[5];
1150     XrmRepresentation rep_type;
1151     XrmValue value;
1152
1153     xrm_name [0] = XrmStringToQuark (BACKDROPSDLG);
1154     xrm_name [2] = 0;
1155
1156     /* get x position */
1157     xrm_name [1] = XrmStringToQuark ("x");
1158     if (XrmQGetResource (db, xrm_name, xrm_name, &rep_type, &value)) {
1159         XtSetArg (save.posArgs[save.poscnt], XmNx, atoi((char *)value.addr)); 
1160         save.poscnt++;
1161         save.restoreFlag = True;
1162     }
1163
1164     /* get y position */
1165     xrm_name [1] = XrmStringToQuark ("y");
1166     if (XrmQGetResource (db, xrm_name, xrm_name, &rep_type, &value)) {
1167         XtSetArg (save.posArgs[save.poscnt], XmNy, atoi((char *)value.addr)); 
1168         save.poscnt++;
1169     }
1170
1171     /* get width */
1172     xrm_name [1] = XrmStringToQuark ("width");
1173     if (XrmQGetResource (db, xrm_name, xrm_name, &rep_type, &value)) {
1174         XtSetArg(save.posArgs[save.poscnt], XmNwidth, atoi((char *)value.addr));
1175         save.poscnt++;
1176     }
1177
1178     /* get height */
1179     xrm_name [1] = XrmStringToQuark ("height");
1180     if (XrmQGetResource (db, xrm_name, xrm_name, &rep_type, &value)) {
1181         XtSetArg(save.posArgs[save.poscnt],XmNheight, atoi((char *)value.addr));
1182         save.poscnt++;
1183     }
1184
1185     xrm_name [1] = XrmStringToQuark ("ismapped");
1186     XrmQGetResource (db, xrm_name, xrm_name, &rep_type, &value);
1187     /* Are we supposed to be mapped? */
1188     if (strcmp(value.addr, "True") == 0)
1189         BackdropDialog(shell);
1190 }
1191
1192
1193 /************************************************************************
1194  * saveBackdrop()
1195  *
1196  * This routine will write out to the passed file descriptor any state
1197  * information this dialog needs.  It is called from saveSessionCB with the
1198  * file already opened.
1199  * All information is saved in xrm format.  There is no restriction
1200  * on what can be saved.  It doesn't have to be defined or be part of any
1201  * widget or Xt definition.  Just name and save it here and recover it in
1202  * restoreBackdrop.  The suggested minimum is whether you are mapped, and your
1203  * location.
1204  ************************************************************************/
1205 void 
1206 saveBackdrop(
1207         int fd )
1208 {
1209     Position x,y;
1210     Dimension width, height;
1211     char *bufr = style.tmpBigStr;     /* size=[1024], make bigger if needed */
1212     XmVendorShellExtObject  vendorExt;
1213     XmWidgetExtData         extData;
1214
1215     if (style.backdropDialog != NULL) 
1216     {
1217         if (XtIsManaged(style.backdropDialog))
1218             sprintf(bufr, "*backdropsDialog.ismapped: True\n");
1219         else
1220             sprintf(bufr, "*backdropsDialog.ismapped: False\n");
1221
1222         /* Get and write out the geometry info for our Window */
1223         x = XtX (XtParent(style.backdropDialog));
1224         y = XtY (XtParent(style.backdropDialog));
1225         width = XtWidth (style.backdropDialog);
1226         height = XtHeight (style.backdropDialog);
1227
1228         /* Modify x & y to take into account window mgr frames
1229          * This is pretty bogus, but I don't know a better way to do it.
1230          */
1231         extData = _XmGetWidgetExtData(style.shell, XmSHELL_EXTENSION);
1232         vendorExt = (XmVendorShellExtObject)extData->widget;
1233         x -= vendorExt->vendor.xOffset;
1234         y -= vendorExt->vendor.yOffset;
1235
1236         sprintf(bufr, "%s*backdropsDialog.x: %d\n", bufr, x);
1237         sprintf(bufr, "%s*backdropsDialog.y: %d\n", bufr, y);
1238         sprintf(bufr, "%s*backdropsDialog.width: %d\n", bufr, width);
1239         sprintf(bufr, "%s*backdropsDialog.height: %d\n", bufr, height);
1240         sprintf(bufr, "%s*backdropsDialog.selectedItemNum: %d\n", bufr, 
1241                 backdrops.selected);
1242         sprintf(bufr, "%s*backdropsDialog.selectedItem: %s\n", bufr, 
1243                 backdrops.bitmapNames[backdrops.selected]);
1244         if(-1 == write (fd, bufr, strlen(bufr))) {
1245                         perror(strerror(errno));
1246                 }
1247     }
1248 }
1249
1250
1251