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