dtcm: Coverity 88353
[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    if(chmod(desc_file,438) == -1) {
530       fprintf(stderr, "failed to chmod '%s', %s\n", desc_file, strerror(errno));
531    }
532
533    XtFree(desc_file);
534    XtFree(desc_name);
535
536    return(0);
537 }
538
539 /*
540 ** This routine removes a palette.  
541 ** It actually creates a file in the users home palette directory with 
542 ** the current palette name preceded by a '~'.
543 ** If the current palette is from the users home palette directory, that
544 ** file is removed.
545 */
546 Boolean 
547 RemovePalette( void )
548 {
549     int  result;
550     char *filename1, *filename2;
551     char *tmpStr;
552
553     /* prepend the palette name with '~' */
554
555     filename1 = (char *)XtMalloc(strlen(pCurrentPalette->name) +2); 
556     strcpy(filename1, "~");
557     strcat(filename1, pCurrentPalette->name);
558
559     if (WriteOutPalette(filename1) != 0)
560     {
561        tmpStr = (char *)XtMalloc(strlen(ERR1) + 
562                        strlen(pCurrentPalette->name) + strlen(ERR2) + 1);
563        sprintf(tmpStr, ERR1, pCurrentPalette->name);
564        strcat(tmpStr,ERR2);
565        ErrDialog (tmpStr, style.colorDialog);
566        XtFree (tmpStr);
567        XtFree (filename1);
568        return(False);
569     }
570
571     if (strcmp(pCurrentPalette->directory, home_palette_dir) == 0)
572     {
573         /* get the $HOME environment varible and constuct the full file name */
574         filename2 = (char *)XtMalloc(strlen(style.home) + strlen(DT_PAL_DIR) +
575                    strlen(pCurrentPalette->name) + strlen(PALETTE_SUFFIX) + 1);
576
577         /* create the full path name plus file name */
578         strcpy(filename2, style.home);
579         strcat(filename2, DT_PAL_DIR);
580         strcat(filename2, pCurrentPalette->name);
581         strcat(filename2, PALETTE_SUFFIX);
582
583         result = unlink(filename2);
584
585         if(result != 0)
586         {
587             tmpStr = (char *)XtMalloc(strlen(ERR1) + strlen(filename2) + 1); 
588             sprintf (tmpStr, ERR1, filename2);
589             _DtSimpleErrnoError (progName, DtWarning, NULL, tmpStr, NULL);
590             XtFree(tmpStr);
591
592             tmpStr = (char *)XtMalloc(strlen(ERR1) +
593                         strlen(pCurrentPalette->name) + strlen(ERR2) + 1);
594             sprintf(tmpStr, ERR1, pCurrentPalette->name);
595             strcat(tmpStr, ERR2);
596             ErrDialog (tmpStr, style.colorDialog);
597             XtFree (tmpStr);
598             XtFree(filename1);
599             XtFree(filename2);
600             return(False);
601         }
602
603         XtFree(filename2);
604     }
605
606     XtFree(filename1);
607     return(True);
608
609 }
610
611 /************************************************************************
612  *
613  * AddSystemPath - adds the system palettes to the directory structure.
614  *
615  ************************************************************************/
616 void 
617 AddSystemPath( void )
618 {
619   if(style.count > 4)
620     return;
621   
622   /*
623    ** Null out the head of the palette linked list
624    */
625   pHeadPalette = NULL;
626   
627   /* set the number of directories to search to 0, this is the first path
628      added  */
629   palette_dirs.NumOfDirectories = 0;
630   
631   /* store the system PALETTE_DIR in the palette_dirs structure */
632   palette_dirs.directories[palette_dirs.NumOfDirectories] = 
633     (char *) XtMalloc(strlen(PALETTE_DIR) + 1);
634   strcpy(palette_dirs.directories[palette_dirs.NumOfDirectories], 
635          PALETTE_DIR);
636   
637   /* increment the Number of directories to search */
638   palette_dirs.NumOfDirectories++;
639
640   style.count++;
641   
642   /* store the admin PALETTE_DIR_ADM in the palette_dirs structure */
643   palette_dirs.directories[palette_dirs.NumOfDirectories] = 
644     (char *) XtMalloc(strlen(PALETTE_DIR_ADM) + 1);
645   strcpy(palette_dirs.directories[palette_dirs.NumOfDirectories], 
646          PALETTE_DIR_ADM);
647   
648   /* increment the Number of directories to search */
649   palette_dirs.NumOfDirectories++;
650   
651 }
652
653 /************************************************************************
654  *
655  * AddHomePath - adds the users home directory to the directory structure.
656  *
657  ************************************************************************/
658 void 
659 AddHomePath( void )
660 {
661    int  result;
662    char *tmpStr;
663    
664    if(style.count > 6)
665       return;
666
667   /* get the $HOME environment varible and constuct the full path */
668    home_palette_dir = (char *)XtMalloc(strlen(style.home) 
669         + strlen(DT_PAL_DIR) + 1);
670
671   /* create the full path name plus file name */
672    strcpy(home_palette_dir, style.home);
673    strcat(home_palette_dir, DT_PAL_DIR);
674
675   /* open $HOME/.dt/palettes */
676    if( (dirp = opendir(home_palette_dir)) == NULL)
677    {
678        /*  create .dt/palettes if it does not exit */
679        result = mkdir(home_palette_dir, 511);
680        if(result == -1)
681        {
682            tmpStr = (char *)XtMalloc(strlen(ERR3) + 
683                 strlen(home_palette_dir) +1);
684            sprintf(tmpStr, ERR4, home_palette_dir);
685            _DtSimpleError (progName, DtWarning, NULL, tmpStr, NULL);
686            XtFree(tmpStr);
687        }
688    }
689                                          
690   /* store the directory in the palette_dirs structure */
691    palette_dirs.directories[palette_dirs.NumOfDirectories] = 
692                   (char *) XtMalloc(strlen(home_palette_dir) + 1);
693    strcpy(palette_dirs.directories[palette_dirs.NumOfDirectories], 
694                   home_palette_dir);
695   /* increment the Number of directories to search */
696    palette_dirs.NumOfDirectories++;
697
698    style.count++;
699 }
700
701 /************************************************************************
702  *
703  * AddDirectories - adds the directories listed in the string text
704  *     to the list of directories which must be checked for valid
705  *     palette files.
706  *
707  ************************************************************************/
708 void 
709 AddDirectories( char *text )
710 {
711    char *filename, *tmpStr;
712    int i, count;
713
714    if(style.count > 5)
715       return;
716
717   /* alloc enough space for temp length */
718    filename = (char *)XtMalloc(strlen(text) + 1);
719
720    count = 0;
721    while(1)
722    {
723      /* copy directory name into the  name .. look for NULL or space */
724       for(i=count; text[i] != ':' && text[i] != '\0'; i++)
725           filename[i - count] = text[i];
726       filename[i - count] = '\0';
727
728      /* store the directory in the palette_dirs structure */
729       palette_dirs.directories[palette_dirs.NumOfDirectories] = 
730                    (char *)XtMalloc(strlen(filename) + 1);
731       strcpy(palette_dirs.directories[palette_dirs.NumOfDirectories], 
732                    filename);
733
734      /* increment number of directories in the structure */
735       palette_dirs.NumOfDirectories++;
736
737      /* if the number of directories read is the maximum number of 
738          directories then break */
739       if (palette_dirs.NumOfDirectories == MAX_NUM_DIRECTORIES-1)
740       {
741           tmpStr = (char *)XtMalloc(strlen(ERR9) + 5);
742           sprintf(tmpStr, ERR9, MAX_NUM_DIRECTORIES-2);
743           _DtSimpleError (progName, DtWarning, NULL, tmpStr, NULL);
744           XtFree(tmpStr);
745           break;
746       }
747
748      /* if the last value was a NULL then all done,  Break out */
749       if (text[i] == '\0')
750          break;
751
752       count = i + 1;
753
754    } /* while(1) */
755
756    XtFree(filename);
757    style.count++;
758 }
759
760 /********************************************************************
761  * 
762  * CheckForDeletedFile - This routine looks through the linked list
763  *     of palettes for the file name passed in.  If it finds it, that
764  *     member of the linked list must be deleted. 
765  *
766  ********************************************************************/
767 void
768 CheckForDeletedFile(
769 #ifdef __hpux
770         struct direct *file_descpt )
771 #else
772         struct dirent *file_descpt )
773 #endif /* __hpux */
774 {
775    char *filename;
776    int i;
777    palette *tmp_palette;
778
779   /* alloc enough space for the name of the ~ file  */
780    filename = (char *)XtMalloc(strlen (file_descpt->d_name) + 1);
781
782   /* copy the name into filename taking out the ~ */
783    for(i=0; i < strlen (file_descpt->d_name) - (strlen(PALETTE_SUFFIX) + 1); i++)
784       filename[i] = file_descpt->d_name[i+1];
785    filename[i] = '\0';
786
787   /* now go see if the filename is in the palette link list */
788    tmp_palette = pHeadPalette;
789    while(tmp_palette->next != NULL )
790      if(strcmp(tmp_palette->name, filename)) 
791         tmp_palette = tmp_palette->next;
792      else
793         tmp_palette = RemovePaletteFromList(tmp_palette);
794
795    /* check the last palette */
796    if(tmp_palette->next == NULL && (strcmp(tmp_palette->name, filename) == 0))
797       (void) RemovePaletteFromList(tmp_palette);
798
799    XtFree(filename);
800 }
801
802 /****************************************************************************
803  *
804  * ReadInInfo - the routine used to actual parse the data from a palette
805  *       file.  It parses 8 different background colors.  
806  *
807  ****************************************************************************/
808 static void
809 ReadInInfo(
810         char *buf,
811         int nbytes,
812         palette *new_palette )
813 {
814    int buf_count, count, result;
815    char tmpbuf[50];
816    XColor tmp_color;
817    int  hue, sat, val;
818    int num_of_colors = 0;
819
820    for( buf_count = 0; buf_count < nbytes;)
821    {
822        count = 0;
823    
824      /* read in a background color */
825        while( buf[buf_count] != '\012' && buf[buf_count] != ':' )
826           tmpbuf[count++] = buf[buf_count++];
827        tmpbuf[count] = '\0';
828
829      /* temporary for now until all palettes are updated not to use : */
830        if(buf[buf_count] == ':')
831           while(buf[buf_count] != '\012')
832              buf_count++;
833        buf_count++;
834    
835       /* Parse the background color */
836        result = XParseColor(style.display, style.colormap, tmpbuf, &tmp_color);
837
838       /* if the result == 0 then the parse came back bad, uses the motif
839          default background (#729FFF) */
840        if(result == 0)
841        {
842           new_palette->color[num_of_colors].bg.red = 29184;
843           new_palette->color[num_of_colors].bg.green = 40704;
844           new_palette->color[num_of_colors].bg.blue = 65280;
845        }
846        else
847        {
848           new_palette->color[num_of_colors].bg.red = tmp_color.red;
849           new_palette->color[num_of_colors].bg.green = tmp_color.green;
850           new_palette->color[num_of_colors].bg.blue = tmp_color.blue;
851        }
852    
853       /* use the motif routine to generate fg, sc, ts, and bs */
854        if(TypeOfMonitor != XmCO_BLACK_WHITE) {
855           if (edit.calcRGB == NULL) edit.calcRGB = XmGetColorCalculation();
856           (*edit.calcRGB)(&tmp_color, 
857                                   &(new_palette->color[num_of_colors].fg),
858                                   &(new_palette->color[num_of_colors].sc),
859                                   &(new_palette->color[num_of_colors].ts),
860                                   &(new_palette->color[num_of_colors].bs));
861
862            RGBtoHSV(new_palette->color[num_of_colors].bg.red,
863                       new_palette->color[num_of_colors].bg.green,
864                       new_palette->color[num_of_colors].bg.blue,
865                       &hue, &sat, &val);
866    
867
868           SetColors(num_of_colors, new_palette);
869        }
870        else /* XmCO_BLACK_WHITE */
871           InitializeBW(tmp_color.red, num_of_colors, new_palette);
872
873        new_palette->num_of_colors++;
874        num_of_colors++;
875        if (num_of_colors == 8)
876             break;
877    
878    } /* for */
879
880   /* have now read in complete palette file .. set number of colors 
881      appropriatly because every palette has 8 entries */
882    if(TypeOfMonitor == XmCO_LOW_COLOR || TypeOfMonitor == XmCO_BLACK_WHITE)
883        new_palette->num_of_colors = 2;
884    
885    if(TypeOfMonitor == XmCO_MEDIUM_COLOR)
886        new_palette->num_of_colors = 4;
887
888    if(TypeOfMonitor == XmCO_LOW_COLOR)
889    {
890       SwitchAItoPS(new_palette);
891    }
892
893
894 /***************************************************************************
895  *
896  * SetColors - 
897  *       It sets bs and ts if Pixmaps are to be used for topshadow 
898  *       and bottomshadow.
899  *
900  ***************************************************************************/
901 static void 
902 SetColors(
903         int num_of_colors,
904         palette *new_palette )
905 {
906
907 /*
908 **  Set the foreground pixel to either black or white depending on brightness
909 */
910    if (FgColor != DYNAMIC) 
911    {
912       if (FgColor == BLACK)
913       {
914          new_palette->color[num_of_colors].fg.red = 0;
915          new_palette->color[num_of_colors].fg.blue = 0;
916          new_palette->color[num_of_colors].fg.green = 0;
917       }
918       else /* WHITE */
919       {
920          new_palette->color[num_of_colors].fg.red = 65535;
921          new_palette->color[num_of_colors].fg.blue = 65535;
922          new_palette->color[num_of_colors].fg.green = 65535;
923       }
924    }
925
926
927 /*
928 ** Now set ts and bs if the user is using pixmaps
929 */
930    if(UsePixmaps != FALSE)
931    {
932        new_palette->color[num_of_colors].ts.red = 65535; 
933        new_palette->color[num_of_colors].ts.blue = 65535;
934        new_palette->color[num_of_colors].ts.green = 65535;
935    
936        new_palette->color[num_of_colors].bs.red = 0;
937        new_palette->color[num_of_colors].bs.blue = 0;
938        new_palette->color[num_of_colors].bs.green = 0;
939    }
940
941 }
942
943 /***************************************************************************
944  *
945  * InitializeBW - initializes the RGB values for the WhiteOnBlack and
946  *        BlackOnWhite palettes.  The color passed in is used to determine
947  *        if its White on Black or Black on White.
948  *
949  ***************************************************************************/
950 static void
951 InitializeBW(
952         unsigned long color,
953         int num_of_colors,
954         palette *new_palette )
955 {
956   /* if color passed in is black(background) its white on black so
957      set everything to white */
958    if(color == 0)
959    {
960        new_palette->color[num_of_colors].fg.red = 65535; 
961        new_palette->color[num_of_colors].fg.blue = 65535;
962        new_palette->color[num_of_colors].fg.green = 65535;
963    
964        new_palette->color[num_of_colors].sc.red = 65535;
965        new_palette->color[num_of_colors].sc.blue = 65535;
966        new_palette->color[num_of_colors].sc.green = 65535;
967    
968        new_palette->color[num_of_colors].ts.red = 0; 
969        new_palette->color[num_of_colors].ts.blue = 0;
970        new_palette->color[num_of_colors].ts.green = 0;
971       
972        new_palette->color[num_of_colors].bs.red = 65535;
973        new_palette->color[num_of_colors].bs.blue = 65535;
974        new_palette->color[num_of_colors].bs.green = 65535;
975    }
976    else
977    {
978        new_palette->color[num_of_colors].fg.red = 0; 
979        new_palette->color[num_of_colors].fg.blue = 0;
980        new_palette->color[num_of_colors].fg.green = 0;
981    
982        new_palette->color[num_of_colors].sc.red = 65535;
983        new_palette->color[num_of_colors].sc.blue = 65535;
984        new_palette->color[num_of_colors].sc.green = 65535;
985    
986        new_palette->color[num_of_colors].ts.red = 0; 
987        new_palette->color[num_of_colors].ts.blue = 0;
988        new_palette->color[num_of_colors].ts.green = 0;
989    
990        new_palette->color[num_of_colors].bs.red = 0;
991        new_palette->color[num_of_colors].bs.blue = 0;
992        new_palette->color[num_of_colors].bs.green = 0;
993    }
994 }
995
996 /****************************************************************************
997  *
998  * SwitchAItoPS - used to in a XmCO_LOW_COLOR system to switch the Acitive and
999  *    Inactive colorsets to use the Primary and Secondary colorsets.  It
1000  *    was determined that this would look much better to the user.
1001  *
1002  **************************************************************************/
1003 static void 
1004 SwitchAItoPS( palette *new_palette )
1005 {
1006    saved_color[0].red = new_palette->color[0].bg.red;
1007    saved_color[0].green = new_palette->color[0].bg.green;
1008    saved_color[0].blue = new_palette->color[0].bg.blue;
1009
1010    saved_color[1].red = new_palette->color[1].bg.red;
1011    saved_color[1].green = new_palette->color[1].bg.green;
1012    saved_color[1].blue = new_palette->color[1].bg.blue;
1013
1014    new_palette->color[0].bg.red = new_palette->color[3].bg.red;
1015    new_palette->color[0].bg.green = new_palette->color[3].bg.green;
1016    new_palette->color[0].bg.blue = new_palette->color[3].bg.blue;
1017
1018    new_palette->color[0].fg.red = new_palette->color[3].fg.red;
1019    new_palette->color[0].fg.green = new_palette->color[3].fg.green;
1020    new_palette->color[0].fg.blue = new_palette->color[3].fg.blue;
1021
1022    new_palette->color[0].ts.red = new_palette->color[3].ts.red;
1023    new_palette->color[0].ts.green = new_palette->color[3].ts.green;
1024    new_palette->color[0].ts.blue = new_palette->color[3].ts.blue;
1025
1026    new_palette->color[0].bs.red = new_palette->color[3].bs.red;
1027    new_palette->color[0].bs.green = new_palette->color[3].bs.green;
1028    new_palette->color[0].bs.blue = new_palette->color[3].bs.blue;
1029
1030    new_palette->color[0].sc.red = new_palette->color[3].sc.red;
1031    new_palette->color[0].sc.green = new_palette->color[3].sc.green;
1032    new_palette->color[0].sc.blue = new_palette->color[3].sc.blue;
1033
1034    new_palette->color[1].bg.red = new_palette->color[2].bg.red;
1035    new_palette->color[1].bg.green = new_palette->color[2].bg.green;
1036    new_palette->color[1].bg.blue = new_palette->color[2].bg.blue;
1037
1038    new_palette->color[1].fg.red = new_palette->color[2].fg.red;
1039    new_palette->color[1].fg.green = new_palette->color[2].fg.green;
1040    new_palette->color[1].fg.blue = new_palette->color[2].fg.blue;
1041
1042    new_palette->color[1].ts.red = new_palette->color[2].ts.red;
1043    new_palette->color[1].ts.green = new_palette->color[2].ts.green;
1044    new_palette->color[1].ts.blue = new_palette->color[2].ts.blue;
1045
1046    new_palette->color[1].bs.red = new_palette->color[2].bs.red;
1047    new_palette->color[1].bs.green = new_palette->color[2].bs.green;
1048    new_palette->color[1].bs.blue = new_palette->color[2].bs.blue;
1049
1050    new_palette->color[1].sc.red = new_palette->color[2].sc.red;
1051    new_palette->color[1].sc.green = new_palette->color[2].sc.green;
1052    new_palette->color[1].sc.blue = new_palette->color[2].sc.blue;
1053
1054 }
1055
1056 /****************************************************************************
1057  *
1058  * RemovePaletteFromList - used to remove the palette pointed to by 
1059  *    tmp_palette from the linked list of palettes.  The returned palette
1060  *    is the palette immediately before the deleted palette 
1061  *
1062  **************************************************************************/
1063 static palette * 
1064 RemovePaletteFromList( palette *tmp_palette )
1065
1066    palette *tmp2_palette; 
1067    int i, count;
1068
1069  /* it is in here ... get rid of this entry in the link list */
1070    if (tmp_palette->item_position == 1)
1071    {
1072        pHeadPalette = tmp_palette->next;
1073        tmp2_palette = pHeadPalette;
1074    }
1075    else
1076    {
1077      /* find palette just above the one being deleted */
1078        tmp2_palette = pHeadPalette;
1079        for (i=1; i < tmp_palette->item_position-1; i++)
1080            tmp2_palette = tmp2_palette->next;
1081
1082       /* set the palette before's next to the one being deleted next */
1083        tmp2_palette->next = tmp_palette->next;
1084    }
1085
1086     /* deallocate the palette structure */
1087    XtFree(tmp_palette->name);
1088    XtFree(tmp_palette->directory);
1089    XtFree((char *)tmp_palette);
1090
1091      /* make sure the item_positions are correct*/
1092    count = 1;
1093    tmp_palette = pHeadPalette;
1094    while(tmp_palette->next != NULL )
1095    {
1096       tmp_palette->item_position = count++;
1097       tmp_palette = tmp_palette->next;
1098    }
1099    tmp_palette->item_position = count;
1100
1101   /* decrease the number of palettes */
1102    NumOfPalettes--;
1103
1104   return(tmp2_palette);
1105 }
1106
1107 /*************************************************************************
1108  *
1109  * CheckFileType() - Determine if the system supports long file names
1110  *   or not .. set a flag accoringly.
1111  *
1112  ***********************************************************************/
1113 void
1114 CheckFileType( void )
1115 {
1116    char *filename1 = "abcdefghijklmno";
1117    char *filename2 = "abcdefghijklmn";
1118    int  fd = -1, fd1 = -1;
1119    char *tmpfile1, *tmpfile2;
1120  
1121   /* get the $HOME environment varible and constuct the full file name */
1122    tmpfile1 = (char *)XtMalloc(strlen(style.home) + strlen(DT_PAL_DIR) +
1123                                                      strlen(filename1) + 2);
1124
1125   /* create the full path name plus file name */
1126    strcpy(tmpfile1, style.home);
1127    strcat(tmpfile1, DT_PAL_DIR);
1128    strcat(tmpfile1, filename1);
1129
1130 #if defined(__linux__)
1131    if( (fd = open( tmpfile1, O_CREAT, S_IRUSR | S_IWUSR)) == -1)
1132 #else
1133    if( (fd = open( tmpfile1, O_CREAT)) == -1)
1134 #endif
1135    {
1136         style. longfilename = False;
1137         XtFree(tmpfile1);
1138         style.count++;
1139         return;
1140    }
1141   /* get the $HOME environment varible and constuct the full file name */
1142    tmpfile2 = (char *)XtMalloc(strlen(style.home) + strlen(DT_PAL_DIR) +
1143                                                      strlen(filename2) + 2);
1144
1145   /* create the full path name plus file name */
1146    strcpy(tmpfile2, style.home);
1147    strcat(tmpfile2, DT_PAL_DIR);
1148    strcat(tmpfile2, filename2);
1149
1150 #if defined(__linux__)
1151    if( (fd1 = open(tmpfile2, O_CREAT | O_EXCL, S_IRUSR | S_IWUSR)) == -1)
1152 #else
1153    if( (fd1 = open(tmpfile2, O_CREAT | O_EXCL)) == -1)
1154 #endif
1155    {
1156        style.longfilename = False; 
1157    }
1158    else
1159    {
1160        style.longfilename = True;
1161        unlink(tmpfile2);
1162    }
1163
1164    unlink(tmpfile1);
1165    XtFree(tmpfile1);
1166    XtFree(tmpfile2);
1167    close(fd);
1168    if(fd1 != -1) {
1169       close(fd1);
1170    }
1171    
1172 }
1173
1174 Boolean 
1175 ReadPaletteLoop( 
1176 #if NeedWidePrototypes
1177         int startup )
1178 #else
1179         Boolean startup )
1180 #endif
1181 {
1182    char *tmpStr;
1183
1184    if(style.count > 7)
1185       return(True);
1186
1187    /* read all files from all directories */
1188    while(loopcount<palette_dirs.NumOfDirectories && loopcount<MAX_NUM_DIRECTORIES)
1189    {
1190          
1191 /*
1192 ** Open the directory .
1193 **   dirp is a pointer to the directory stream
1194 */
1195       if( open_dir == False )
1196       {
1197          if( (dirp = opendir(palette_dirs.directories[loopcount])) == NULL)
1198          {
1199             /* note: if there is an error in opening a directory,
1200              * the directory is not deleted from the palette_dirs
1201              * structure.
1202              */
1203             loopcount++; 
1204             if(loopcount < palette_dirs.NumOfDirectories &&
1205                                           loopcount < MAX_NUM_DIRECTORIES)
1206                return(False);
1207             style.count++;
1208             return(True);
1209          }
1210          else {
1211             open_dir = True;
1212 /*
1213 ** get a pointer to the next file entry .. file_descpt
1214 **    the structure for direct looks like:
1215 **       struct direct {
1216 **              long    d_fileno;     #file number of entry
1217 **              short   d_reclen;     #length of this record
1218 **              short   d_namlen;     #length of string in d_name
1219 **              char    d_name[256];  #name 
1220 **            };
1221 */
1222              file_descpt = readdir(dirp);
1223           }
1224       }
1225
1226       while( file_descpt != NULL)
1227       {
1228        /* check for a valid palette file */
1229          if(!(strncmp(PALETTE_SUFFIX, DtStrrchr(file_descpt->d_name, '.'),
1230                                           strlen(PALETTE_SUFFIX)))) 
1231          {
1232 /*
1233 ** A file in the users home palette directory which begins with a ~
1234 ** is a palette that the user doesn't want.  Remove it from
1235 ** the palette link list.
1236 */
1237              if((strcmp(palette_dirs.directories[loopcount],
1238                                               home_palette_dir) == 0) && 
1239                           (strncmp(file_descpt->d_name, "~", 1) == 0) &&
1240                            pHeadPalette != NULL)
1241              {
1242                 CheckForDeletedFile(file_descpt);
1243              }
1244              else if (strncmp(file_descpt->d_name, "~", 1) != 0) 
1245              {
1246                /* make sure if Black and white monitor the file is one that
1247                   can be read for a XmCO_BLACK_WHITE monitor */
1248              if(TypeOfMonitor != XmCO_BLACK_WHITE ) 
1249              { 
1250                 if((fnmatch(file_descpt->d_name, B_O_W, 0) != 0) &&
1251                         (fnmatch(file_descpt->d_name, W_O_B, 0)  !=0 ) &&
1252                         (fnmatch(file_descpt->d_name, W_ONLY, 0) !=0 ) &&
1253                         (fnmatch(file_descpt->d_name, B_ONLY, 0) !=0 ))
1254                    ReadPalette(palette_dirs.directories[loopcount], 
1255                                          file_descpt->d_name,
1256                                          strlen (file_descpt->d_name));
1257               }
1258               else
1259               {
1260                  if((fnmatch(file_descpt->d_name, B_O_W, 0) == 0) ||
1261                         (fnmatch(file_descpt->d_name, W_O_B, 0)  == 0) ||
1262                         (fnmatch(file_descpt->d_name, W_ONLY, 0) == 0) ||
1263                         (fnmatch(file_descpt->d_name, B_ONLY, 0) == 0))
1264                     ReadPalette(palette_dirs.directories[loopcount], 
1265                                          file_descpt->d_name,
1266                                          strlen (file_descpt->d_name));
1267                }
1268            } 
1269
1270       }  /* if valid palette file */
1271
1272      /* read the next file */
1273       file_descpt = readdir(dirp);
1274
1275       if(startup == True)
1276          return(False);
1277
1278       } /* while( file_descpt != NULL) */
1279
1280       closedir(dirp);
1281       open_dir = False;
1282
1283       loopcount++;
1284
1285    } /* while */
1286
1287    style.count++;
1288    return(True);
1289
1290 }