rgb.c revision 2e2dd055
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 */
58int
59xpmReadRgbNames(
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 */
119char *
120xpmGetRgbName(
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 */
146void
147xpmFreeRgbNames(
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
163int
164xpmReadRgbNames(
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 */
179char *
180xpmGetRgbName(
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 */
205int
206xpmGetRGBfromName(
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
279void
280xpmFreeRgbNames(
281    xpmRgbName	rgbn[],
282    int		rgbn_max)
283{
284    /* nothing to do */
285}
286
287#endif					/* MSW part */
288