dcbeeab2505c8d4df06ab640d8e5b78ace3a00ce
[oweals/cde.git] / cde / programs / dtstyle / ColorFile.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 /************************************<+>*************************************
24  ****************************************************************************
25  **
26  **   File:        ColorFile.c
27  **
28  **   Project:     DT 3.0
29  **
30  **   Description:
31  **
32  **
33  **  (c) Copyright Hewlett-Packard Company, 1990.  
34  **
35  **
36  **
37  ****************************************************************************
38  ************************************<+>*************************************/
39 /* $XConsortium: ColorFile.c /main/5 1995/10/30 13:08:20 rswiston $ */
40 /*+++++++++++++++++++++++++++++++++++++++*/
41 /* include files                         */
42 /*+++++++++++++++++++++++++++++++++++++++*/
43
44 #include <stdio.h>
45 #include <fcntl.h>
46 #include <errno.h>
47
48 #include <X11/Xlib.h>
49
50 #ifdef __hpux
51 #include <ndir.h>               /*   opendir(), directory(3C) */
52 #else
53 #if SVR4 || sco
54 #include <dirent.h>             /* opendir(), directory(3C) */
55 #else
56 #include <sys/dir.h>
57 #ifdef __apollo
58 #include <X11/apollosys.h>      /* needed for S_ISDIR macro */
59 #endif
60 #endif
61 #endif
62
63
64 #include <Xm/Xm.h>
65
66 #include <Dt/UserMsg.h>
67 #include <Dt/DtNlUtils.h>
68
69 #include "Main.h"
70 #include "ColorMain.h"
71 #include "ColorEdit.h"
72
73 /*+++++++++++++++++++++++++++++++++++++++*/
74 /* include extern functions              */
75 /*+++++++++++++++++++++++++++++++++++++++*/
76 #include "ColorFile.h"
77
78 /*+++++++++++++++++++++++++++++++++++++++*/
79 /* Local #defines                        */
80 /*+++++++++++++++++++++++++++++++++++++++*/
81 #define MAX_NUM_DIRECTORIES  12
82 #define BUFSIZE              1024
83 #define TMP_DEFAULT_NAME     "tmppalette"
84
85 /* these defines used to create error dialog */
86 #define  ERR1  ((char *)GETMESSAGE(16, 11, "Unable to delete '%s'.\n"))
87 #define  ERR2  ((char *)GETMESSAGE(16, 12, "Check $HOME/.dt/errorlog for hints."))
88 #define  ERR3  ((char *)GETMESSAGE(16, 19, "Could not open directory %s."))
89 #define  ERR4  ((char *)GETMESSAGE(16, 20, "Could not open %s."))
90 #define  ERR5  ((char *)GETMESSAGE(16, 21, "%s is an invalid palette file.\n"))
91 #define  ERR9  ((char *)GETMESSAGE(16, 18, "Warning, Too many directories listed in the resource paletteDirectories,\n Maximum number is %d."))
92
93 #ifndef CDE_INSTALLATION_TOP
94 #define CDE_INSTALLATION_TOP "/opt/dt"
95 #endif
96
97 /*+++++++++++++++++++++++++++++++++++++++*/
98 /* Local typedefs                        */
99 /*+++++++++++++++++++++++++++++++++++++++*/
100 /* Palette Directories structure */
101
102 typedef struct {
103    int NumOfDirectories;
104    char *directories[MAX_NUM_DIRECTORIES];
105 } Dir_data;
106
107 Dir_data palette_dirs;
108
109
110 /*+++++++++++++++++++++++++++++++++++++++*/
111 /* Internal Functions                    */
112 /*+++++++++++++++++++++++++++++++++++++++*/
113
114
115 static void SwitchAItoPS( palette *new_palette );
116 static palette *RemovePaletteFromList( palette *tmp_palette );
117 static void SetColors(
118                         int num_of_colors,
119                         palette *new_palette) ;
120 static void ReadInInfo(
121                         char *buf,
122                         int nbytes,
123                         palette *new_palette );
124 static void InitializeBW(
125                         unsigned long color,
126                         int num_of_colors,
127                         palette *new_palette ) ;
128
129
130
131 /*+++++++++++++++++++++++++++++++++++++++*/
132 /* Internal Variables                    */
133 /*+++++++++++++++++++++++++++++++++++++++*/
134 int NumOfPalettes = 0;
135
136 static char *PALETTE_DIR = CDE_INSTALLATION_TOP "/palettes/";
137 static char *PALETTE_DIR_ADM = "/etc/dt/palettes/";
138 static char *DEFAULT_FILENAME = "palette.dt";
139 static char *B_O_W = "BlackWhite.dp";
140 static char *W_O_B = "WhiteBlack.dp";
141 static char *W_ONLY = "White.dp";
142 static char *B_ONLY = "Black.dp";
143 static char *home_palette_dir;
144
145 static int loopcount = 0;
146 static DIR  *dirp;
147 #ifdef __hpux
148 static struct direct *file_descpt;
149 #else
150 static struct dirent *file_descpt;
151 #endif /* __hpux */
152 static Boolean open_dir = False;
153 extern XrmDatabase hm_pl_DB;
154
155 XColor saved_color[2];
156
157
158 /*
159 ** readinpalettes reads in the different palettes for the customizer.
160 **
161 ** The directories read from include:
162 **     1. the system palettes (PALETTE_DIR)
163 **     2. the user defined directories specified by the resource PaletteDir. 
164 **     3. the users $HOME/.dt/palettes
165 */
166
167 void 
168 ReadInPalettes(
169         char *text )
170 {
171 /*
172 **  if text is NULL then open only the global dir and user dir, 
173 **  otherwise open all the directories listed *text. 
174 */
175    AddSystemPath();
176
177    if (text != NULL)
178       AddDirectories(text);
179
180    AddHomePath();
181    
182    ReadPaletteLoop(False);
183
184 }
185
186 /*
187 **  ReadPalette reads the contents of the file in_filename, allocates space
188 **  for a new palette, and puts it in there.
189 **  The varible in_filename passed in should be just the filename 
190 **  of the file.  The absolute file name is constructed in this routine.
191 **  i.e.  directory/file.
192 **  Finally this routine ups the count for number of palettes in the
193 **  customizer.
194 **  The parameter length, which is passed in, is the length of the in_filename
195 **  string.
196 **  After the system palettes are read in, if there are duplicate copies 
197 **  of palette names, the first one encountered is the one that is used.  
198 **  Subsequent palettes with the same name are discarded.
199 **  Then when the users home palette directory is read, if there are
200 **  duplicates, the users home palettes is kept.
201 */
202 void 
203 ReadPalette(
204         char *directory,
205         char *in_filename,
206 #if NeedWidePrototypes
207         int length )
208 #else
209         short length )
210 #endif
211 {
212    char *filename;
213    int  i, fd, nbytes;
214    char buf[BUFSIZE];
215    palette *new_palette, *tmp_palette;
216    Boolean  modify, add, found;
217    char *tmpStr;
218    char *p;
219
220    modify = FALSE;
221    if (strcmp(directory, PALETTE_DIR) == 0)
222        add = TRUE;
223    else
224        add = FALSE;
225        
226 /* Allocate space for this new palette.*/
227    new_palette = (palette *)XtMalloc( sizeof(palette) + 1);
228
229 /* create the filename to be read by adding directory in front of it */
230    filename = (char *)XtMalloc( strlen(directory) + length + 2);
231    strcpy(filename, directory); 
232
233    if(DtCharCount(DtStrrchr(directory, '/')) != 1)
234         strcat(filename, "/"); 
235    strcat(filename, in_filename); 
236
237 /* open the file for reading */
238    if( (fd = open( filename, O_RDONLY)) == -1)
239    {
240       tmpStr = (char *)XtMalloc(strlen(ERR4) + strlen(filename) + 1);
241       sprintf(tmpStr, ERR4, filename);
242       _DtSimpleErrnoError (progName, DtWarning, NULL, tmpStr, NULL);
243       XtFree(tmpStr);
244       XtFree(filename);
245       return;
246    }
247    else 
248    {
249     /* determine number of bytes in the name of the palette */
250        i = strlen(in_filename) - strlen(PALETTE_SUFFIX);
251
252     /* allocate enough space for the name */
253       new_palette->name = (char *)XtMalloc(i + 1);
254
255     /* load the filename into the name element */
256       p = strstr (in_filename, PALETTE_SUFFIX);
257       *p = '\0';
258       strcpy(new_palette->name, in_filename);
259
260 /* 
261 ** Now we have a name lets check to see if it is already in the linked
262 ** list.  If it is and it is from the system palettes, replace it.
263 ** If it is already in the list but is not from the system palettes,
264 ** don't overwrite it - discard the one just read and go on to next palette.
265 */
266       if(pHeadPalette != NULL)
267       {
268          found = FALSE;
269          tmp_palette = pHeadPalette;
270          while(tmp_palette->next != NULL )
271          {
272             if(strcmp(tmp_palette->name, new_palette->name)) 
273                tmp_palette = tmp_palette->next;
274             else
275             {
276                found = TRUE;
277                if ((strcmp(tmp_palette->directory, PALETTE_DIR) == 0) ||
278                    (strcmp(directory, home_palette_dir) == 0))
279                {
280                    XtFree(new_palette->name);   
281                    XtFree((char *)new_palette);   
282                    XtFree(tmp_palette->directory);   
283                    new_palette = tmp_palette;
284                    modify = TRUE;
285                }
286                else
287                {
288                    XtFree(new_palette->name);   
289                    XtFree((char *)new_palette);   
290                }
291                break;
292             }
293          }
294         /* check the last palette */
295          if (!found)
296          {
297              if (strcmp(tmp_palette->name, new_palette->name) == 0) 
298
299                  if ((strcmp(tmp_palette->directory, PALETTE_DIR) == 0) ||
300                      (strcmp(directory, home_palette_dir) == 0))
301                  {
302                     XtFree(new_palette->name);
303                     XtFree((char *)new_palette);
304                     XtFree(tmp_palette->directory);
305                     new_palette = tmp_palette;
306                     modify = TRUE;
307                  }
308                  else 
309                  {
310                     if (!add) /* not system palettes */
311                     {
312                        XtFree(new_palette->name);   
313                        XtFree((char *)new_palette);   
314                     }
315                  }
316
317              else
318                 add = TRUE;
319          }
320       }
321
322       if ((modify == TRUE)||(add == TRUE))
323       {
324         /* allocate enough space for the directory */
325           new_palette->directory = (char *)XtMalloc(strlen(directory) + 1);
326
327         /* load the directory name into the directory element */
328           strcpy(new_palette->directory, directory);
329
330         /* set the num_of_colors  to 0 */
331           new_palette->num_of_colors = 0;
332
333           nbytes = read(fd, buf, BUFSIZE);
334           if( nbytes == BUFSIZE || nbytes == 0)
335           {
336              tmpStr = (char *)XtMalloc(strlen(ERR5) + strlen(filename) + 1);
337              sprintf(tmpStr, ERR5, filename);
338              _DtSimpleError (progName, DtWarning, NULL, tmpStr, NULL);
339              XtFree(filename);
340              XtFree(tmpStr);
341              close(fd);
342              return;
343           }
344           else
345           {
346            /* go parse the data from the palette file */
347              ReadInInfo(buf, nbytes, new_palette);
348           } 
349
350       } /* modify == TRUE */
351
352       /* close the file */
353       close(fd); 
354
355     } /* else */
356
357 /*
358 **  Find the next available location within the linked list of palettes to 
359 **  store the palette just created.  If it is the first one store it in
360 **  pHeadPalettes, else store it in the first place a NULL is encountered
361 **  for the next member of the palette structure.
362 */
363     if (add == TRUE)
364     {
365       /* set the next pointer to NULL*/
366        new_palette->next = NULL;
367
368       /* increment the total number of palettes in the customizer */
369        NumOfPalettes++;
370
371        if( pHeadPalette == NULL /* First entry */
372           || (pHeadPalette != NULL && strcmp(pHeadPalette->name, new_palette->name) > 0)) /* Earlier entry than current list head */
373        {
374            new_palette->item_position = 1;
375            if(pHeadPalette)
376            {
377                new_palette->next = pHeadPalette;
378                /* Increment position poineter of other items in the list */
379                tmp_palette = pHeadPalette;
380                while( tmp_palette != NULL)
381                {
382                    tmp_palette->item_position += 1;
383                    tmp_palette = tmp_palette->next;
384                }
385            }
386
387            pHeadPalette = new_palette;
388        }
389        else
390        {
391            tmp_palette = pHeadPalette;
392
393            /* Search through the linked list to find the first entry with a 
394               name > new entries name, new item will be inserted after it */
395            while(tmp_palette->next && strcmp(tmp_palette->next->name, new_palette->name) < 0) 
396            {
397                tmp_palette = tmp_palette->next;
398            }
399
400            /* Insert the new palette */
401            new_palette->next = tmp_palette->next;
402            tmp_palette->next = new_palette;
403            new_palette->item_position = tmp_palette->item_position + 1;
404
405            /* Now continue incrementing through the list increasing the position
406               count of all items following the new entry */
407            tmp_palette = new_palette->next;
408            while( tmp_palette != NULL)
409            {
410               tmp_palette->item_position += 1;
411               tmp_palette = tmp_palette->next;
412            }
413        }
414     }
415
416   /* done with filename so XtFree it */
417    XtFree(filename);
418
419 }
420 /***************************************************************************
421  *
422  * WriteOutPalette -
423  * This routine writes out a file (palette) to the users .dt/palettes
424  * directory. The palette name is passed into the routine. 
425  *
426  ***************************************************************************/
427 int 
428 WriteOutPalette(
429         char *paletteName )
430 {
431    char *temp, *tmpStr;
432    char *filename;
433    int  i, fd;
434
435   /* use the $HOME environment varible then constuct the full file name */
436    filename = (char *)XtMalloc(strlen(style.home) + 
437                                strlen(DT_PAL_DIR) +
438                                strlen(paletteName) + 
439                                strlen(PALETTE_SUFFIX) + 2);
440
441   /* create the full path name plus file name */
442    strcpy(filename, style.home);
443    strcat(filename, DT_PAL_DIR);
444    strcat(filename, paletteName);
445    strcat(filename, PALETTE_SUFFIX);
446
447    /* open the file for writing */
448 #if defined(__linux__)
449    if( (fd = open( filename, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR)) == -1)
450 #else
451    if( (fd = open( filename, O_RDWR | O_CREAT)) == -1)
452 #endif
453    {
454        tmpStr = (char *)XtMalloc(strlen(ERR4) + strlen(filename) + 1);
455        sprintf (tmpStr, ERR4, filename);
456        _DtSimpleErrnoError (progName, DtWarning, NULL, tmpStr, NULL);
457        XtFree(tmpStr);
458        XtFree(filename);
459        return(-1);
460    }
461    else
462    {
463        temp = (char *)XtMalloc(60);
464        for(i = 0; i < XmCO_MAX_NUM_COLORS; i++)
465        {
466         /* put the colors of the palette in the form #RRRRGGGGBBBB */   
467            if(TypeOfMonitor == XmCO_LOW_COLOR && (i == 0 || i == 1))
468                sprintf(temp,"#%04x%04x%04x\n", saved_color[i].red, 
469                                                saved_color[i].green, 
470                                                saved_color[i].blue);
471            else if(TypeOfMonitor == XmCO_LOW_COLOR && i == 2)
472                sprintf(temp,"#%04x%04x%04x\n",
473                                    pCurrentPalette->color[1].bg.red,
474                                    pCurrentPalette->color[1].bg.green,
475                                    pCurrentPalette->color[1].bg.blue);
476            else if(TypeOfMonitor == XmCO_LOW_COLOR && i == 3)
477                sprintf(temp,"#%04x%04x%04x\n",
478                                    pCurrentPalette->color[0].bg.red,
479                                    pCurrentPalette->color[0].bg.green,
480                                    pCurrentPalette->color[0].bg.blue);
481            else
482                sprintf(temp,"#%04x%04x%04x\n",
483                                    pCurrentPalette->color[i].bg.red,
484                                    pCurrentPalette->color[i].bg.green,
485                                    pCurrentPalette->color[i].bg.blue);
486            if(-1 == write(fd, temp, strlen(temp))) {
487                    perror(strerror(errno));
488                    XtFree(temp);
489                    close(fd);
490                    return(-1);
491            }
492        }
493        XtFree(temp);
494    }
495    close(fd);
496    /* make sure the file is read/writable */
497    chmod(filename,438);
498    XtFree(filename);
499    return(0);
500 }
501
502 /***************************************************************************
503  *
504  * WriteOutDesc -
505  * This routine writes out the description file for the added palette in the 
506  * user's .dt/palettes directory.
507  ***************************************************************************/
508 int 
509 WriteOutDesc(
510         palette *tmp_palette )
511 {
512    char *desc_file;
513    char *desc_name;
514
515    /* write the description resource to the user's home data base and write out */
516    /* the database to the user's palatte directory */
517  
518    desc_name = (char *) XtMalloc(strlen("Palettes*") + 
519                                  strlen(tmp_palette->name) + 
520                                  strlen(".desc") + 1);
521    
522    sprintf(desc_name, "Palettes*%s.desc", tmp_palette->name);
523    
524    XrmPutStringResource(&hm_pl_DB, desc_name, tmp_palette->desc); 
525     
526    /* write out the description file */
527    desc_file = (char *) XtMalloc(strlen(style.home) +(strlen("/.dt/palettes/desc.palettes") + 1));
528    strcpy (desc_file, style.home);
529    strcat (desc_file, "/.dt/palettes/desc.palettes");
530    if (hm_pl_DB )
531      XrmPutFileDatabase(hm_pl_DB, desc_file);
532    /* make the file read, write */
533    chmod(desc_file,438);
534    XtFree(desc_file);
535    XtFree(desc_name);
536
537    return(0);
538 }
539
540 /*
541 ** This routine removes a palette.  
542 ** It actually creates a file in the users home palette directory with 
543 ** the current palette name preceded by a '~'.
544 ** If the current palette is from the users home palette directory, that
545 ** file is removed.
546 */
547 Boolean 
548 RemovePalette( void )
549 {
550     int  result;
551     char *filename1, *filename2;
552     char *tmpStr;
553
554     /* prepend the palette name with '~' */
555
556     filename1 = (char *)XtMalloc(strlen(pCurrentPalette->name) +2); 
557     strcpy(filename1, "~");
558     strcat(filename1, pCurrentPalette->name);
559
560     if (WriteOutPalette(filename1) != 0)
561     {
562        tmpStr = (char *)XtMalloc(strlen(ERR1) + 
563                        strlen(pCurrentPalette->name) + strlen(ERR2) + 1);
564        sprintf(tmpStr, ERR1, pCurrentPalette->name);
565        strcat(tmpStr,ERR2);
566        ErrDialog (tmpStr, style.colorDialog);
567        XtFree (tmpStr);
568        XtFree (filename1);
569        return(False);
570     }
571
572     if (strcmp(pCurrentPalette->directory, home_palette_dir) == 0)
573     {
574         /* get the $HOME environment varible and constuct the full file name */
575         filename2 = (char *)XtMalloc(strlen(style.home) + strlen(DT_PAL_DIR) +
576                    strlen(pCurrentPalette->name) + strlen(PALETTE_SUFFIX) + 1);
577
578         /* create the full path name plus file name */
579         strcpy(filename2, style.home);
580         strcat(filename2, DT_PAL_DIR);
581         strcat(filename2, pCurrentPalette->name);
582         strcat(filename2, PALETTE_SUFFIX);
583
584         result = unlink(filename2);
585
586         if(result != 0)
587         {
588             tmpStr = (char *)XtMalloc(strlen(ERR1) + strlen(filename2) + 1); 
589             sprintf (tmpStr, ERR1, filename2);
590             _DtSimpleErrnoError (progName, DtWarning, NULL, tmpStr, NULL);
591             XtFree(tmpStr);
592
593             tmpStr = (char *)XtMalloc(strlen(ERR1) +
594                         strlen(pCurrentPalette->name) + strlen(ERR2) + 1);
595             sprintf(tmpStr, ERR1, pCurrentPalette->name);
596             strcat(tmpStr, ERR2);
597             ErrDialog (tmpStr, style.colorDialog);
598             XtFree (tmpStr);
599             XtFree(filename1);
600             XtFree(filename2);
601             return(False);
602         }
603
604         XtFree(filename2);
605     }
606
607     XtFree(filename1);
608     return(True);
609
610 }
611
612 /************************************************************************
613  *
614  * AddSystemPath - adds the system palettes to the directory structure.
615  *
616  ************************************************************************/
617 void 
618 AddSystemPath( void )
619 {
620   if(style.count > 4)
621     return;
622   
623   /*
624    ** Null out the head of the palette linked list
625    */
626   pHeadPalette = NULL;
627   
628   /* set the number of directories to search to 0, this is the first path
629      added  */
630   palette_dirs.NumOfDirectories = 0;
631   
632   /* store the system PALETTE_DIR in the palette_dirs structure */
633   palette_dirs.directories[palette_dirs.NumOfDirectories] = 
634     (char *) XtMalloc(strlen(PALETTE_DIR) + 1);
635   strcpy(palette_dirs.directories[palette_dirs.NumOfDirectories], 
636          PALETTE_DIR);
637   
638   /* increment the Number of directories to search */
639   palette_dirs.NumOfDirectories++;
640
641   style.count++;
642   
643   /* store the admin PALETTE_DIR_ADM in the palette_dirs structure */
644   palette_dirs.directories[palette_dirs.NumOfDirectories] = 
645     (char *) XtMalloc(strlen(PALETTE_DIR_ADM) + 1);
646   strcpy(palette_dirs.directories[palette_dirs.NumOfDirectories], 
647          PALETTE_DIR_ADM);
648   
649   /* increment the Number of directories to search */
650   palette_dirs.NumOfDirectories++;
651   
652 }
653
654 /************************************************************************
655  *
656  * AddHomePath - adds the users home directory to the directory structure.
657  *
658  ************************************************************************/
659 void 
660 AddHomePath( void )
661 {
662    int  result;
663    char *tmpStr;
664    
665    if(style.count > 6)
666       return;
667
668   /* get the $HOME environment varible and constuct the full path */
669    home_palette_dir = (char *)XtMalloc(strlen(style.home) 
670         + strlen(DT_PAL_DIR) + 1);
671
672   /* create the full path name plus file name */
673    strcpy(home_palette_dir, style.home);
674    strcat(home_palette_dir, DT_PAL_DIR);
675
676   /* open $HOME/.dt/palettes */
677    if( (dirp = opendir(home_palette_dir)) == NULL)
678    {
679        /*  create .dt/palettes if it does not exit */
680        result = mkdir(home_palette_dir, 511);
681        if(result == -1)
682        {
683            tmpStr = (char *)XtMalloc(strlen(ERR3) + 
684                 strlen(home_palette_dir) +1);
685            sprintf(tmpStr, ERR4, home_palette_dir);
686            _DtSimpleError (progName, DtWarning, NULL, tmpStr, NULL);
687            XtFree(tmpStr);
688        }
689    }
690                                          
691   /* store the directory in the palette_dirs structure */
692    palette_dirs.directories[palette_dirs.NumOfDirectories] = 
693                   (char *) XtMalloc(strlen(home_palette_dir) + 1);
694    strcpy(palette_dirs.directories[palette_dirs.NumOfDirectories], 
695                   home_palette_dir);
696   /* increment the Number of directories to search */
697    palette_dirs.NumOfDirectories++;
698
699    style.count++;
700 }
701
702 /************************************************************************
703  *
704  * AddDirectories - adds the directories listed in the string text
705  *     to the list of directories which must be checked for valid
706  *     palette files.
707  *
708  ************************************************************************/
709 void 
710 AddDirectories( char *text )
711 {
712    char *filename, *tmpStr;
713    int i, count;
714
715    if(style.count > 5)
716       return;
717
718   /* alloc enough space for temp length */
719    filename = (char *)XtMalloc(strlen(text) + 1);
720
721    count = 0;
722    while(1)
723    {
724      /* copy directory name into the  name .. look for NULL or space */
725       for(i=count; text[i] != ':' && text[i] != '\0'; i++)
726           filename[i - count] = text[i];
727       filename[i - count] = '\0';
728
729      /* store the directory in the palette_dirs structure */
730       palette_dirs.directories[palette_dirs.NumOfDirectories] = 
731                    (char *)XtMalloc(strlen(filename) + 1);
732       strcpy(palette_dirs.directories[palette_dirs.NumOfDirectories], 
733                    filename);
734
735      /* increment number of directories in the structure */
736       palette_dirs.NumOfDirectories++;
737
738      /* if the number of directories read is the maximum number of 
739          directories then break */
740       if (palette_dirs.NumOfDirectories == MAX_NUM_DIRECTORIES-1)
741       {
742           tmpStr = (char *)XtMalloc(strlen(ERR9) + 5);
743           sprintf(tmpStr, ERR9, MAX_NUM_DIRECTORIES-2);
744           _DtSimpleError (progName, DtWarning, NULL, tmpStr, NULL);
745           XtFree(tmpStr);
746           break;
747       }
748
749      /* if the last value was a NULL then all done,  Break out */
750       if (text[i] == '\0')
751          break;
752
753       count = i + 1;
754
755    } /* while(1) */
756
757    XtFree(filename);
758    style.count++;
759 }
760
761 /********************************************************************
762  * 
763  * CheckForDeletedFile - This routine looks through the linked list
764  *     of palettes for the file name passed in.  If it finds it, that
765  *     member of the linked list must be deleted. 
766  *
767  ********************************************************************/
768 void
769 CheckForDeletedFile(
770 #ifdef __hpux
771         struct direct *file_descpt )
772 #else
773         struct dirent *file_descpt )
774 #endif /* __hpux */
775 {
776    char *filename;
777    int i;
778    palette *tmp_palette;
779
780   /* alloc enough space for the name of the ~ file  */
781    filename = (char *)XtMalloc(strlen (file_descpt->d_name) + 1);
782
783   /* copy the name into filename taking out the ~ */
784    for(i=0; i < strlen (file_descpt->d_name) - (strlen(PALETTE_SUFFIX) + 1); i++)
785       filename[i] = file_descpt->d_name[i+1];
786    filename[i] = '\0';
787
788   /* now go see if the filename is in the palette link list */
789    tmp_palette = pHeadPalette;
790    while(tmp_palette->next != NULL )
791      if(strcmp(tmp_palette->name, filename)) 
792         tmp_palette = tmp_palette->next;
793      else
794         tmp_palette = RemovePaletteFromList(tmp_palette);
795
796    /* check the last palette */
797    if(tmp_palette->next == NULL && (strcmp(tmp_palette->name, filename) == 0))
798       (void) RemovePaletteFromList(tmp_palette);
799
800    XtFree(filename);
801 }
802
803 /****************************************************************************
804  *
805  * ReadInInfo - the routine used to actual parse the data from a palette
806  *       file.  It parses 8 different background colors.  
807  *
808  ****************************************************************************/
809 static void
810 ReadInInfo(
811         char *buf,
812         int nbytes,
813         palette *new_palette )
814 {
815    int buf_count, count, result;
816    char tmpbuf[50];
817    XColor tmp_color;
818    int  hue, sat, val;
819    int num_of_colors = 0;
820
821    for( buf_count = 0; buf_count < nbytes;)
822    {
823        count = 0;
824    
825      /* read in a background color */
826        while( buf[buf_count] != '\012' && buf[buf_count] != ':' )
827           tmpbuf[count++] = buf[buf_count++];
828        tmpbuf[count] = '\0';
829
830      /* temporary for now until all palettes are updated not to use : */
831        if(buf[buf_count] == ':')
832           while(buf[buf_count] != '\012')
833              buf_count++;
834        buf_count++;
835    
836       /* Parse the background color */
837        result = XParseColor(style.display, style.colormap, tmpbuf, &tmp_color);
838
839       /* if the result == 0 then the parse came back bad, uses the motif
840          default background (#729FFF) */
841        if(result == 0)
842        {
843           new_palette->color[num_of_colors].bg.red = 29184;
844           new_palette->color[num_of_colors].bg.green = 40704;
845           new_palette->color[num_of_colors].bg.blue = 65280;
846        }
847        else
848        {
849           new_palette->color[num_of_colors].bg.red = tmp_color.red;
850           new_palette->color[num_of_colors].bg.green = tmp_color.green;
851           new_palette->color[num_of_colors].bg.blue = tmp_color.blue;
852        }
853    
854       /* use the motif routine to generate fg, sc, ts, and bs */
855        if(TypeOfMonitor != XmCO_BLACK_WHITE) {
856           if (edit.calcRGB == NULL) edit.calcRGB = XmGetColorCalculation();
857           (*edit.calcRGB)(&tmp_color, 
858                                   &(new_palette->color[num_of_colors].fg),
859                                   &(new_palette->color[num_of_colors].sc),
860                                   &(new_palette->color[num_of_colors].ts),
861                                   &(new_palette->color[num_of_colors].bs));
862
863            RGBtoHSV(new_palette->color[num_of_colors].bg.red,
864                       new_palette->color[num_of_colors].bg.green,
865                       new_palette->color[num_of_colors].bg.blue,
866                       &hue, &sat, &val);
867    
868
869           SetColors(num_of_colors, new_palette);
870        }
871        else /* XmCO_BLACK_WHITE */
872           InitializeBW(tmp_color.red, num_of_colors, new_palette);
873
874        new_palette->num_of_colors++;
875        num_of_colors++;
876        if (num_of_colors == 8)
877             break;
878    
879    } /* for */
880
881   /* have now read in complete palette file .. set number of colors 
882      appropriatly because every palette has 8 entries */
883    if(TypeOfMonitor == XmCO_LOW_COLOR || TypeOfMonitor == XmCO_BLACK_WHITE)
884        new_palette->num_of_colors = 2;
885    
886    if(TypeOfMonitor == XmCO_MEDIUM_COLOR)
887        new_palette->num_of_colors = 4;
888
889    if(TypeOfMonitor == XmCO_LOW_COLOR)
890    {
891       SwitchAItoPS(new_palette);
892    }
893
894
895 /***************************************************************************
896  *
897  * SetColors - 
898  *       It sets bs and ts if Pixmaps are to be used for topshadow 
899  *       and bottomshadow.
900  *
901  ***************************************************************************/
902 static void 
903 SetColors(
904         int num_of_colors,
905         palette *new_palette )
906 {
907
908 /*
909 **  Set the foreground pixel to either black or white depending on brightness
910 */
911    if (FgColor != DYNAMIC) 
912    {
913       if (FgColor == BLACK)
914       {
915          new_palette->color[num_of_colors].fg.red = 0;
916          new_palette->color[num_of_colors].fg.blue = 0;
917          new_palette->color[num_of_colors].fg.green = 0;
918       }
919       else /* WHITE */
920       {
921          new_palette->color[num_of_colors].fg.red = 65535;
922          new_palette->color[num_of_colors].fg.blue = 65535;
923          new_palette->color[num_of_colors].fg.green = 65535;
924       }
925    }
926
927
928 /*
929 ** Now set ts and bs if the user is using pixmaps
930 */
931    if(UsePixmaps != FALSE)
932    {
933        new_palette->color[num_of_colors].ts.red = 65535; 
934        new_palette->color[num_of_colors].ts.blue = 65535;
935        new_palette->color[num_of_colors].ts.green = 65535;
936    
937        new_palette->color[num_of_colors].bs.red = 0;
938        new_palette->color[num_of_colors].bs.blue = 0;
939        new_palette->color[num_of_colors].bs.green = 0;
940    }
941
942 }
943
944 /***************************************************************************
945  *
946  * InitializeBW - initializes the RGB values for the WhiteOnBlack and
947  *        BlackOnWhite palettes.  The color passed in is used to determine
948  *        if its White on Black or Black on White.
949  *
950  ***************************************************************************/
951 static void
952 InitializeBW(
953         unsigned long color,
954         int num_of_colors,
955         palette *new_palette )
956 {
957   /* if color passed in is black(background) its white on black so
958      set everything to white */
959    if(color == 0)
960    {
961        new_palette->color[num_of_colors].fg.red = 65535; 
962        new_palette->color[num_of_colors].fg.blue = 65535;
963        new_palette->color[num_of_colors].fg.green = 65535;
964    
965        new_palette->color[num_of_colors].sc.red = 65535;
966        new_palette->color[num_of_colors].sc.blue = 65535;
967        new_palette->color[num_of_colors].sc.green = 65535;
968    
969        new_palette->color[num_of_colors].ts.red = 0; 
970        new_palette->color[num_of_colors].ts.blue = 0;
971        new_palette->color[num_of_colors].ts.green = 0;
972       
973        new_palette->color[num_of_colors].bs.red = 65535;
974        new_palette->color[num_of_colors].bs.blue = 65535;
975        new_palette->color[num_of_colors].bs.green = 65535;
976    }
977    else
978    {
979        new_palette->color[num_of_colors].fg.red = 0; 
980        new_palette->color[num_of_colors].fg.blue = 0;
981        new_palette->color[num_of_colors].fg.green = 0;
982    
983        new_palette->color[num_of_colors].sc.red = 65535;
984        new_palette->color[num_of_colors].sc.blue = 65535;
985        new_palette->color[num_of_colors].sc.green = 65535;
986    
987        new_palette->color[num_of_colors].ts.red = 0; 
988        new_palette->color[num_of_colors].ts.blue = 0;
989        new_palette->color[num_of_colors].ts.green = 0;
990    
991        new_palette->color[num_of_colors].bs.red = 0;
992        new_palette->color[num_of_colors].bs.blue = 0;
993        new_palette->color[num_of_colors].bs.green = 0;
994    }
995 }
996
997 /****************************************************************************
998  *
999  * SwitchAItoPS - used to in a XmCO_LOW_COLOR system to switch the Acitive and
1000  *    Inactive colorsets to use the Primary and Secondary colorsets.  It
1001  *    was determined that this would look much better to the user.
1002  *
1003  **************************************************************************/
1004 static void 
1005 SwitchAItoPS( palette *new_palette )
1006 {
1007    saved_color[0].red = new_palette->color[0].bg.red;
1008    saved_color[0].green = new_palette->color[0].bg.green;
1009    saved_color[0].blue = new_palette->color[0].bg.blue;
1010
1011    saved_color[1].red = new_palette->color[1].bg.red;
1012    saved_color[1].green = new_palette->color[1].bg.green;
1013    saved_color[1].blue = new_palette->color[1].bg.blue;
1014
1015    new_palette->color[0].bg.red = new_palette->color[3].bg.red;
1016    new_palette->color[0].bg.green = new_palette->color[3].bg.green;
1017    new_palette->color[0].bg.blue = new_palette->color[3].bg.blue;
1018
1019    new_palette->color[0].fg.red = new_palette->color[3].fg.red;
1020    new_palette->color[0].fg.green = new_palette->color[3].fg.green;
1021    new_palette->color[0].fg.blue = new_palette->color[3].fg.blue;
1022
1023    new_palette->color[0].ts.red = new_palette->color[3].ts.red;
1024    new_palette->color[0].ts.green = new_palette->color[3].ts.green;
1025    new_palette->color[0].ts.blue = new_palette->color[3].ts.blue;
1026
1027    new_palette->color[0].bs.red = new_palette->color[3].bs.red;
1028    new_palette->color[0].bs.green = new_palette->color[3].bs.green;
1029    new_palette->color[0].bs.blue = new_palette->color[3].bs.blue;
1030
1031    new_palette->color[0].sc.red = new_palette->color[3].sc.red;
1032    new_palette->color[0].sc.green = new_palette->color[3].sc.green;
1033    new_palette->color[0].sc.blue = new_palette->color[3].sc.blue;
1034
1035    new_palette->color[1].bg.red = new_palette->color[2].bg.red;
1036    new_palette->color[1].bg.green = new_palette->color[2].bg.green;
1037    new_palette->color[1].bg.blue = new_palette->color[2].bg.blue;
1038
1039    new_palette->color[1].fg.red = new_palette->color[2].fg.red;
1040    new_palette->color[1].fg.green = new_palette->color[2].fg.green;
1041    new_palette->color[1].fg.blue = new_palette->color[2].fg.blue;
1042
1043    new_palette->color[1].ts.red = new_palette->color[2].ts.red;
1044    new_palette->color[1].ts.green = new_palette->color[2].ts.green;
1045    new_palette->color[1].ts.blue = new_palette->color[2].ts.blue;
1046
1047    new_palette->color[1].bs.red = new_palette->color[2].bs.red;
1048    new_palette->color[1].bs.green = new_palette->color[2].bs.green;
1049    new_palette->color[1].bs.blue = new_palette->color[2].bs.blue;
1050
1051    new_palette->color[1].sc.red = new_palette->color[2].sc.red;
1052    new_palette->color[1].sc.green = new_palette->color[2].sc.green;
1053    new_palette->color[1].sc.blue = new_palette->color[2].sc.blue;
1054
1055 }
1056
1057 /****************************************************************************
1058  *
1059  * RemovePaletteFromList - used to remove the palette pointed to by 
1060  *    tmp_palette from the linked list of palettes.  The returned palette
1061  *    is the palette immediately before the deleted palette 
1062  *
1063  **************************************************************************/
1064 static palette * 
1065 RemovePaletteFromList( palette *tmp_palette )
1066
1067    palette *tmp2_palette; 
1068    int i, count;
1069
1070  /* it is in here ... get rid of this entry in the link list */
1071    if (tmp_palette->item_position == 1)
1072    {
1073        pHeadPalette = tmp_palette->next;
1074        tmp2_palette = pHeadPalette;
1075    }
1076    else
1077    {
1078      /* find palette just above the one being deleted */
1079        tmp2_palette = pHeadPalette;
1080        for (i=1; i < tmp_palette->item_position-1; i++)
1081            tmp2_palette = tmp2_palette->next;
1082
1083       /* set the palette before's next to the one being deleted next */
1084        tmp2_palette->next = tmp_palette->next;
1085    }
1086
1087     /* deallocate the palette structure */
1088    XtFree(tmp_palette->name);
1089    XtFree(tmp_palette->directory);
1090    XtFree((char *)tmp_palette);
1091
1092      /* make sure the item_positions are correct*/
1093    count = 1;
1094    tmp_palette = pHeadPalette;
1095    while(tmp_palette->next != NULL )
1096    {
1097       tmp_palette->item_position = count++;
1098       tmp_palette = tmp_palette->next;
1099    }
1100    tmp_palette->item_position = count;
1101
1102   /* decrease the number of palettes */
1103    NumOfPalettes--;
1104
1105   return(tmp2_palette);
1106 }
1107
1108 /*************************************************************************
1109  *
1110  * CheckFileType() - Determine if the system supports long file names
1111  *   or not .. set a flag accoringly.
1112  *
1113  ***********************************************************************/
1114 void
1115 CheckFileType( void )
1116 {
1117    char *filename1 = "abcdefghijklmno";
1118    char *filename2 = "abcdefghijklmn";
1119    int  fd, fd1;
1120    char *tmpfile1, *tmpfile2;
1121  
1122   /* get the $HOME environment varible and constuct the full file name */
1123    tmpfile1 = (char *)XtMalloc(strlen(style.home) + strlen(DT_PAL_DIR) +
1124                                                      strlen(filename1) + 2);
1125
1126   /* create the full path name plus file name */
1127    strcpy(tmpfile1, style.home);
1128    strcat(tmpfile1, DT_PAL_DIR);
1129    strcat(tmpfile1, filename1);
1130
1131 #if defined(__linux__)
1132    if( (fd = open( tmpfile1, O_CREAT, S_IRUSR | S_IWUSR)) == -1)
1133 #else
1134    if( (fd = open( tmpfile1, O_CREAT)) == -1)
1135 #endif
1136    {
1137         style. longfilename = False;
1138         XtFree(tmpfile1);
1139         style.count++;
1140         return;
1141    }
1142   /* get the $HOME environment varible and constuct the full file name */
1143    tmpfile2 = (char *)XtMalloc(strlen(style.home) + strlen(DT_PAL_DIR) +
1144                                                      strlen(filename2) + 2);
1145
1146   /* create the full path name plus file name */
1147    strcpy(tmpfile2, style.home);
1148    strcat(tmpfile2, DT_PAL_DIR);
1149    strcat(tmpfile2, filename2);
1150
1151 #if defined(__linux__)
1152    if( (fd1 = open(tmpfile2, O_CREAT | O_EXCL, S_IRUSR | S_IWUSR)) == -1)
1153 #else
1154    if( (fd1 = open(tmpfile2, O_CREAT | O_EXCL)) == -1)
1155 #endif
1156    {
1157        style.longfilename = False; 
1158    }
1159    else
1160    {
1161        style.longfilename = True;
1162        unlink(tmpfile2);
1163    }
1164
1165    unlink(tmpfile1);
1166    XtFree(tmpfile1);
1167    XtFree(tmpfile2);
1168    close(fd);
1169    close(fd1);
1170    
1171 }
1172
1173 Boolean 
1174 ReadPaletteLoop( 
1175 #if NeedWidePrototypes
1176         int startup )
1177 #else
1178         Boolean startup )
1179 #endif
1180 {
1181    char *tmpStr;
1182
1183    if(style.count > 7)
1184       return(True);
1185
1186    /* read all files from all directories */
1187    while(loopcount<palette_dirs.NumOfDirectories && loopcount<MAX_NUM_DIRECTORIES)
1188    {
1189          
1190 /*
1191 ** Open the directory .
1192 **   dirp is a pointer to the directory stream
1193 */
1194       if( open_dir == False )
1195       {
1196          if( (dirp = opendir(palette_dirs.directories[loopcount])) == NULL)
1197          {
1198             /* note: if there is an error in opening a directory,
1199              * the directory is not deleted from the palette_dirs
1200              * structure.
1201              */
1202             loopcount++; 
1203             if(loopcount < palette_dirs.NumOfDirectories &&
1204                                           loopcount < MAX_NUM_DIRECTORIES)
1205                return(False);
1206             style.count++;
1207             return(True);
1208          }
1209          else {
1210             open_dir = True;
1211 /*
1212 ** get a pointer to the next file entry .. file_descpt
1213 **    the structure for direct looks like:
1214 **       struct direct {
1215 **              long    d_fileno;     #file number of entry
1216 **              short   d_reclen;     #length of this record
1217 **              short   d_namlen;     #length of string in d_name
1218 **              char    d_name[256];  #name 
1219 **            };
1220 */
1221              file_descpt = readdir(dirp);
1222           }
1223       }
1224
1225       while( file_descpt != NULL)
1226       {
1227        /* check for a valid palette file */
1228          if(!(strncmp(PALETTE_SUFFIX, DtStrrchr(file_descpt->d_name, '.'),
1229                                           strlen(PALETTE_SUFFIX)))) 
1230          {
1231 /*
1232 ** A file in the users home palette directory which begins with a ~
1233 ** is a palette that the user doesn't want.  Remove it from
1234 ** the palette link list.
1235 */
1236              if((strcmp(palette_dirs.directories[loopcount],
1237                                               home_palette_dir) == 0) && 
1238                           (strncmp(file_descpt->d_name, "~", 1) == 0) &&
1239                            pHeadPalette != NULL)
1240              {
1241                 CheckForDeletedFile(file_descpt);
1242              }
1243              else if (strncmp(file_descpt->d_name, "~", 1) != 0) 
1244              {
1245                /* make sure if Black and white monitor the file is one that
1246                   can be read for a XmCO_BLACK_WHITE monitor */
1247              if(TypeOfMonitor != XmCO_BLACK_WHITE ) 
1248              { 
1249                 if((fnmatch(file_descpt->d_name, B_O_W, 0) != 0) &&
1250                         (fnmatch(file_descpt->d_name, W_O_B, 0)  !=0 ) &&
1251                         (fnmatch(file_descpt->d_name, W_ONLY, 0) !=0 ) &&
1252                         (fnmatch(file_descpt->d_name, B_ONLY, 0) !=0 ))
1253                    ReadPalette(palette_dirs.directories[loopcount], 
1254                                          file_descpt->d_name,
1255                                          strlen (file_descpt->d_name));
1256               }
1257               else
1258               {
1259                  if((fnmatch(file_descpt->d_name, B_O_W, 0) == 0) ||
1260                         (fnmatch(file_descpt->d_name, W_O_B, 0)  == 0) ||
1261                         (fnmatch(file_descpt->d_name, W_ONLY, 0) == 0) ||
1262                         (fnmatch(file_descpt->d_name, B_ONLY, 0) == 0))
1263                     ReadPalette(palette_dirs.directories[loopcount], 
1264                                          file_descpt->d_name,
1265                                          strlen (file_descpt->d_name));
1266                }
1267            } 
1268
1269       }  /* if valid palette file */
1270
1271      /* read the next file */
1272       file_descpt = readdir(dirp);
1273
1274       if(startup == True)
1275          return(False);
1276
1277       } /* while( file_descpt != NULL) */
1278
1279       closedir(dirp);
1280       open_dir = False;
1281
1282       loopcount++;
1283
1284    } /* while */
1285
1286    style.count++;
1287    return(True);
1288
1289 }