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