1 /*
2  * Copyright (C) 1989-95 GROUPE BULL
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a copy
5  * of this software and associated documentation files (the "Software"), to
6  * deal in the Software without restriction, including without limitation the
7  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
8  * sell copies of the Software, and to permit persons to whom the Software is
9  * furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17  * GROUPE BULL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18  * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20  *
21  * Except as contained in this notice, the name of GROUPE BULL shall not be
22  * used in advertising or otherwise to promote the sale, use or other dealings
23  * in this Software without prior written authorization from GROUPE BULL.
24  */
25 
26 /*****************************************************************************\
27 * rgb.c:                                                                      *
28 *                                                                             *
29 *  XPM library                                                                *
30 *  Rgb file utilities                                                         *
31 *                                                                             *
32 *  Developed by Arnaud Le Hors                                                *
33 \*****************************************************************************/
34 
35 /*
36  * The code related to FOR_MSW has been added by
37  * HeDu (hedu@cul-ipn.uni-kiel.de) 4/94
38  */
39 
40 /*
41  * Part of this code has been taken from the ppmtoxpm.c file written by Mark
42  * W. Snitily but has been modified for my special need
43  */
44 
45 #ifdef HAVE_CONFIG_H
46 #include <config.h>
47 #endif
48 #include "XpmI.h"
49 #include <ctype.h>
50 
51 #ifndef FOR_MSW				/* normal part first, MSW part at
52 					 * the end, (huge ifdef!) */
53 /*
54  * Read a rgb text file.  It stores the rgb values (0->65535)
55  * and the rgb mnemonics (malloc'ed) into the "rgbn" array.  Returns the
56  * number of entries stored.
57  */
58 int
xpmReadRgbNames(char * rgb_fname,xpmRgbName rgbn[])59 xpmReadRgbNames(
60     char	*rgb_fname,
61     xpmRgbName	 rgbn[])
62 {
63     FILE *rgbf;
64     int n, items, red, green, blue;
65     char line[512], name[512], *rgbname, *s1, *s2;
66     xpmRgbName *rgb;
67 
68     /* Open the rgb text file.  Abort if error. */
69     if ((rgbf = fopen(rgb_fname, "r")) == NULL)
70 	return 0;
71 
72     /* Loop reading each line in the file. */
73     n = 0;
74     rgb = rgbn;
75     /* Quit if rgb text file has too many entries. */
76     while (fgets(line, sizeof(line), rgbf) && n < MAX_RGBNAMES) {
77 
78 	/* Skip silently if line is bad. */
79 	items = sscanf(line, "%d %d %d %[^\n]\n", &red, &green, &blue, name);
80 	if (items != 4)
81 	    continue;
82 
83 	/*
84 	 * Make sure rgb values are within 0->255 range. Skip silently if
85 	 * bad.
86 	 */
87 	if (red < 0 || red > 0xFF ||
88 	    green < 0 || green > 0xFF ||
89 	    blue < 0 || blue > 0xFF)
90 	    continue;
91 
92 	/* Allocate memory for ascii name. If error give up here. */
93 	if (!(rgbname = (char *) XpmMalloc(strlen(name) + 1)))
94 	    break;
95 
96 	/* Copy string to ascii name and lowercase it. */
97 	for (s1 = name, s2 = rgbname; *s1; s1++)
98 	    *s2++ = tolower(*s1);
99 	*s2 = '\0';
100 
101 	/* Save the rgb values and ascii name in the array. */
102 	rgb->r = red * 257;		/* 65535/255 = 257 */
103 	rgb->g = green * 257;
104 	rgb->b = blue * 257;
105 	rgb->name = rgbname;
106 	rgb++;
107 	n++;
108     }
109 
110     fclose(rgbf);
111 
112     /* Return the number of read rgb names. */
113     return n < 0 ? 0 : n;
114 }
115 
116 /*
117  * Return the color name corresponding to the given rgb values
118  */
119 char *
xpmGetRgbName(xpmRgbName rgbn[],int rgbn_max,int red,int green,int blue)120 xpmGetRgbName(
121     xpmRgbName	rgbn[],		/* rgb mnemonics from rgb text file */
122     int		rgbn_max,	/* number of rgb mnemonics in table */
123     int		red,		/* rgb values */
124     int		green,
125     int		blue)
126 {
127     int i;
128     xpmRgbName *rgb;
129 
130     /*
131      * Just perform a dumb linear search over the rgb values of the color
132      * mnemonics.  One could speed things up by sorting the rgb values and
133      * using a binary search, or building a hash table, etc...
134      */
135     for (i = 0, rgb = rgbn; i < rgbn_max; i++, rgb++)
136 	if (red == rgb->r && green == rgb->g && blue == rgb->b)
137 	    return rgb->name;
138 
139     /* if not found return NULL */
140     return NULL;
141 }
142 
143 /*
144  * Free the strings which have been malloc'ed in xpmReadRgbNames
145  */
146 void
xpmFreeRgbNames(xpmRgbName rgbn[],int rgbn_max)147 xpmFreeRgbNames(
148     xpmRgbName	rgbn[],
149     int		rgbn_max)
150 {
151     int i;
152     xpmRgbName *rgb;
153 
154     for (i = 0, rgb = rgbn; i < rgbn_max; i++, rgb++)
155 	XpmFree(rgb->name);
156 }
157 
158 #else					/* here comes the MSW part, the
159 					 * second part of the  huge ifdef */
160 
161 #include "rgbtab.h"			/* hard coded rgb.txt table */
162 
163 int
xpmReadRgbNames(char * rgb_fname,xpmRgbName rgbn[])164 xpmReadRgbNames(
165     char	*rgb_fname,
166     xpmRgbName	 rgbn[])
167 {
168     /*
169      * check for consistency???
170      * table has to be sorted for calls on strcasecmp
171      */
172     return (numTheRGBRecords);
173 }
174 
175 /*
176  * MSW rgb values are made from 3 BYTEs, this is different from X XColor.red,
177  * which has something like #0303 for one color
178  */
179 char *
xpmGetRgbName(xpmRgbName rgbn[],int rgbn_max,int red,int green,int blue)180 xpmGetRgbName(
181     xpmRgbName rgbn[],		/* rgb mnemonics from rgb text file
182 				 * not used */
183     int		rgbn_max,	/* not used */
184     int		red, 		/* rgb values */
185     int		green,
186     int		blue)
187 
188 {
189     int i;
190     unsigned long rgbVal;
191 
192     i = 0;
193     while (i < numTheRGBRecords) {
194 	rgbVal = theRGBRecords[i].rgb;
195 	if (GetRValue(rgbVal) == red &&
196 	    GetGValue(rgbVal) == green &&
197 	    GetBValue(rgbVal) == blue)
198 	    return (theRGBRecords[i].name);
199 	i++;
200     }
201     return (NULL);
202 }
203 
204 /* used in XParseColor in simx.c */
205 int
xpmGetRGBfromName(char * inname,int * r,int * g,int * b)206 xpmGetRGBfromName(
207     char	*inname,
208     int		*r,
209     int		*g,
210     int		*b)
211 {
212     int left, right, middle;
213     int cmp;
214     unsigned long rgbVal;
215     char *name;
216     char *grey, *p;
217 
218     name = xpmstrdup(inname);
219 
220     /*
221      * the table in rgbtab.c has no names with spaces, and no grey, but a
222      * lot of gray
223      */
224     /* so first extract ' ' */
225     while (p = strchr(name, ' ')) {
226 	while (*(p)) {			/* till eof of string */
227 	    *p = *(p + 1);		/* copy to the left */
228 	    p++;
229 	}
230     }
231     /* fold to lower case */
232     p = name;
233     while (*p) {
234 	*p = tolower(*p);
235 	p++;
236     }
237 
238     /*
239      * substitute Grey with Gray, else rgbtab.h would have more than 100
240      * 'duplicate' entries
241      */
242     if (grey = strstr(name, "grey"))
243 	grey[2] = 'a';
244 
245     /* binary search */
246     left = 0;
247     right = numTheRGBRecords - 1;
248     do {
249 	middle = (left + right) / 2;
250 	cmp = xpmstrcasecmp(name, theRGBRecords[middle].name);
251 	if (cmp == 0) {
252 	    rgbVal = theRGBRecords[middle].rgb;
253 	    *r = GetRValue(rgbVal);
254 	    *g = GetGValue(rgbVal);
255 	    *b = GetBValue(rgbVal);
256 	    free(name);
257 	    return (1);
258 	} else if (cmp < 0) {
259 	    right = middle - 1;
260 	} else {			/* > 0 */
261 	    left = middle + 1;
262 	}
263     } while (left <= right);
264 
265     /*
266      * I don't like to run in a ColorInvalid error and to see no pixmap at
267      * all, so simply return a red pixel. Should be wrapped in an #ifdef
268      * HeDu
269      */
270 
271     *r = 255;
272     *g = 0;
273     *b = 0;				/* red error pixel */
274 
275     free(name);
276     return (1);
277 }
278 
279 void
xpmFreeRgbNames(xpmRgbName rgbn[],int rgbn_max)280 xpmFreeRgbNames(
281     xpmRgbName	rgbn[],
282     int		rgbn_max)
283 {
284     /* nothing to do */
285 }
286 
287 #endif					/* MSW part */
288