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