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