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