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