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