File: | src/xcms/cmsColNm.c |
Location: | line 432, column 7 |
Description: | Function call argument is an uninitialized value |
1 | ||||
2 | /* | |||
3 | * Code and supporting documentation (c) Copyright 1990 1991 Tektronix, Inc. | |||
4 | * All Rights Reserved | |||
5 | * | |||
6 | * This file is a component of an X Window System-specific implementation | |||
7 | * of Xcms based on the TekColor Color Management System. Permission is | |||
8 | * hereby granted to use, copy, modify, sell, and otherwise distribute this | |||
9 | * software and its documentation for any purpose and without fee, provided | |||
10 | * that this copyright, permission, and disclaimer notice is reproduced in | |||
11 | * all copies of this software and in supporting documentation. TekColor | |||
12 | * is a trademark of Tektronix, Inc. | |||
13 | * | |||
14 | * Tektronix makes no representation about the suitability of this software | |||
15 | * for any purpose. It is provided "as is" and with all faults. | |||
16 | * | |||
17 | * TEKTRONIX DISCLAIMS ALL WARRANTIES APPLICABLE TO THIS SOFTWARE, | |||
18 | * INCLUDING THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A | |||
19 | * PARTICULAR PURPOSE. IN NO EVENT SHALL TEKTRONIX BE LIABLE FOR ANY | |||
20 | * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER | |||
21 | * RESULTING FROM LOSS OF USE, DATA, OR PROFITS, WHETHER IN AN ACTION OF | |||
22 | * CONTRACT, NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | |||
23 | * CONNECTION WITH THE USE OR THE PERFORMANCE OF THIS SOFTWARE. | |||
24 | * | |||
25 | * NAME | |||
26 | * XcmsColNm.c | |||
27 | * | |||
28 | * DESCRIPTION | |||
29 | * Source for _XcmsLookupColorName(). | |||
30 | * | |||
31 | * | |||
32 | */ | |||
33 | ||||
34 | #ifdef HAVE_CONFIG_H1 | |||
35 | #include <config.h> | |||
36 | #endif | |||
37 | #include "Xlibint.h" | |||
38 | #include "Xcmsint.h" | |||
39 | #include <X11/Xos.h> | |||
40 | #include <sys/stat.h> | |||
41 | #include <stdio.h> | |||
42 | #include <ctype.h> | |||
43 | #include <limits.h> | |||
44 | #define XK_LATIN1 | |||
45 | #include <X11/keysymdef.h> | |||
46 | #include "Cv.h" | |||
47 | ||||
48 | /* forwards/locals */ | |||
49 | static Statusint LoadColornameDB(void); | |||
50 | ||||
51 | ||||
52 | /* | |||
53 | * LOCAL DEFINES | |||
54 | * #define declarations local to this package. | |||
55 | */ | |||
56 | #ifndef XCMSDB"/Users/jeremy/src/freedesktop/jhbuild/build/share/X11" "/Xcms.txt" | |||
57 | #define XCMSDB"/Users/jeremy/src/freedesktop/jhbuild/build/share/X11" "/Xcms.txt" XCMSDIR"/Users/jeremy/src/freedesktop/jhbuild/build/share/X11" "/Xcms.txt" | |||
58 | #endif | |||
59 | ||||
60 | #ifndef isgraph | |||
61 | # define isgraph(c)(isprint((c)) && !isspace((c))) (isprint((c)) && !isspace((c))) | |||
62 | #endif | |||
63 | ||||
64 | #ifndef XCMSDB_MAXLINELEN256 | |||
65 | # define XCMSDB_MAXLINELEN256 256 | |||
66 | #endif | |||
67 | ||||
68 | #define FORMAT_VERSION"0.1" "0.1" | |||
69 | #define START_TOKEN"XCMS_COLORDB_START" "XCMS_COLORDB_START" | |||
70 | #define END_TOKEN"XCMS_COLORDB_END" "XCMS_COLORDB_END" | |||
71 | #define DELIM_CHAR'\t' '\t' | |||
72 | ||||
73 | #define NOT_VISITED0x0 0x0 | |||
74 | #define VISITED0x1 0x1 | |||
75 | #define CYCLE0xFFFF 0xFFFF | |||
76 | #define XcmsDbInitNone-1 -1 | |||
77 | #define XcmsDbInitFailure0 0 | |||
78 | #define XcmsDbInitSuccess1 1 | |||
79 | ||||
80 | /* | |||
81 | * LOCAL TYPEDEFS | |||
82 | */ | |||
83 | typedef struct _XcmsPair { | |||
84 | const char *first; | |||
85 | const char *second; | |||
86 | int flag; | |||
87 | } XcmsPair; | |||
88 | ||||
89 | /* | |||
90 | * LOCAL VARIABLES | |||
91 | */ | |||
92 | static int XcmsColorDbState = XcmsDbInitNone-1; | |||
93 | static int nEntries; | |||
94 | static char *strings; | |||
95 | static XcmsPair *pairs; | |||
96 | static const char whitePtStr[] = "WhitePoint"; | |||
97 | ||||
98 | ||||
99 | /************************************************************************ | |||
100 | * * | |||
101 | * PRIVATE ROUTINES * | |||
102 | * * | |||
103 | ************************************************************************/ | |||
104 | ||||
105 | /* | |||
106 | * NAME | |||
107 | * _XcmsColorSpaceOfString | |||
108 | * | |||
109 | * SYNOPSIS | |||
110 | */ | |||
111 | static XcmsColorSpace * | |||
112 | _XcmsColorSpaceOfString( | |||
113 | XcmsCCC ccc, | |||
114 | const char *color_string) | |||
115 | /* | |||
116 | * DESCRIPTION | |||
117 | * Returns a pointer to the color space structure | |||
118 | * (XcmsColorSpace) associated with the specified color string. | |||
119 | * | |||
120 | * RETURNS | |||
121 | * Pointer to matching XcmsColorSpace structure if found; | |||
122 | * otherwise NULL. | |||
123 | * | |||
124 | * CAVEATS | |||
125 | * | |||
126 | */ | |||
127 | { | |||
128 | XcmsColorSpace **papColorSpaces; | |||
129 | size_t n; | |||
130 | char *pchar; | |||
131 | ||||
132 | if ((pchar = strchr(color_string, ':')) == NULL((void*)0)) { | |||
133 | return(XcmsFailure0); | |||
134 | } | |||
135 | n = (size_t)(pchar - color_string); | |||
136 | ||||
137 | if (ccc == NULL((void*)0)) { | |||
138 | return(NULL((void*)0)); | |||
139 | } | |||
140 | ||||
141 | /* | |||
142 | * First try Device-Independent color spaces | |||
143 | */ | |||
144 | papColorSpaces = _XcmsDIColorSpaces; | |||
145 | if (papColorSpaces != NULL((void*)0)) { | |||
146 | while (*papColorSpaces != NULL((void*)0)) { | |||
147 | if (strncmp((*papColorSpaces)->prefix, color_string, n) == 0 && | |||
148 | !((*papColorSpaces)->prefix)[n]) { | |||
149 | return(*papColorSpaces); | |||
150 | } | |||
151 | papColorSpaces++; | |||
152 | } | |||
153 | } | |||
154 | ||||
155 | /* | |||
156 | * Next try Device-Dependent color spaces | |||
157 | */ | |||
158 | papColorSpaces = ((XcmsFunctionSet *)ccc->pPerScrnInfo->functionSet)->DDColorSpaces; | |||
159 | if (papColorSpaces != NULL((void*)0)) { | |||
160 | while (*papColorSpaces != NULL((void*)0)) { | |||
161 | if (strncmp((*papColorSpaces)->prefix, color_string, n) == 0 && | |||
162 | !((*papColorSpaces)->prefix)[n]) { | |||
163 | return(*papColorSpaces); | |||
164 | } | |||
165 | papColorSpaces++; | |||
166 | } | |||
167 | } | |||
168 | ||||
169 | return(NULL((void*)0)); | |||
170 | } | |||
171 | ||||
172 | ||||
173 | /* | |||
174 | * NAME | |||
175 | * _XcmsParseColorString | |||
176 | * | |||
177 | * SYNOPSIS | |||
178 | */ | |||
179 | static int | |||
180 | _XcmsParseColorString( | |||
181 | XcmsCCC ccc, | |||
182 | const char *color_string, | |||
183 | XcmsColor *pColor) | |||
184 | /* | |||
185 | * DESCRIPTION | |||
186 | * Assuming color_string contains a numerical string color | |||
187 | * specification, attempts to parse a string into an | |||
188 | * XcmsColor structure. | |||
189 | * | |||
190 | * RETURNS | |||
191 | * 0 if failed; otherwise non-zero. | |||
192 | * | |||
193 | * CAVEATS | |||
194 | * A color string containing a numerical color specification | |||
195 | * must be in ISO Latin-1 encoding! | |||
196 | */ | |||
197 | { | |||
198 | XcmsColorSpace *pColorSpace; | |||
199 | char string_buf[64]; | |||
200 | char *string_lowered; | |||
201 | size_t len; | |||
202 | int res; | |||
203 | ||||
204 | if (ccc == NULL((void*)0)) { | |||
205 | return(0); | |||
206 | } | |||
207 | ||||
208 | /* | |||
209 | * While copying color_string to string_lowered, convert to lowercase | |||
210 | */ | |||
211 | if ((len = strlen(color_string)) >= sizeof(string_buf)) { | |||
212 | string_lowered = Xmalloc(len+1)malloc(((len+1) == 0 ? 1 : (len+1))); | |||
213 | } else { | |||
214 | string_lowered = string_buf; | |||
215 | } | |||
216 | ||||
217 | _XcmsCopyISOLatin1Lowered(string_lowered, color_string); | |||
218 | ||||
219 | if (*string_lowered == '#') { | |||
220 | if ((pColorSpace = _XcmsColorSpaceOfString(ccc, "rgb:")) != NULL((void*)0)) { | |||
221 | res = (*pColorSpace->parseString)(string_lowered, pColor); | |||
222 | if (len >= sizeof(string_buf)) Xfree(string_lowered)free((string_lowered)); | |||
223 | return res; | |||
224 | } | |||
225 | } | |||
226 | ||||
227 | if ((pColorSpace = _XcmsColorSpaceOfString(ccc, string_lowered)) != NULL((void*)0)) { | |||
228 | res = (*pColorSpace->parseString)(string_lowered, pColor); | |||
229 | if (len >= sizeof(string_buf)) Xfree(string_lowered)free((string_lowered)); | |||
230 | return res; | |||
231 | } | |||
232 | ||||
233 | if (len >= sizeof(string_buf)) Xfree(string_lowered)free((string_lowered)); | |||
234 | return(0); | |||
235 | } | |||
236 | ||||
237 | ||||
238 | /* | |||
239 | * NAME | |||
240 | * FirstCmp - Compare color names of pair recs | |||
241 | * | |||
242 | * SYNOPSIS | |||
243 | */ | |||
244 | static int | |||
245 | FirstCmp(const void *p1, const void *p2) | |||
246 | /* | |||
247 | * DESCRIPTION | |||
248 | * Compares the color names of XcmsColorTuples. | |||
249 | * This routine is public to allow access from qsort???. | |||
250 | * | |||
251 | * RETURNS | |||
252 | * 0 if equal; | |||
253 | * < 0 if first precedes second, | |||
254 | * > 0 if first succeeds second. | |||
255 | * | |||
256 | */ | |||
257 | { | |||
258 | return(strcmp(((const XcmsPair *)p1)->first, ((const XcmsPair *)p2)->first)); | |||
259 | } | |||
260 | ||||
261 | ||||
262 | ||||
263 | /* | |||
264 | * NAME | |||
265 | * stringSectionSize - determine memory needed for strings | |||
266 | * | |||
267 | * SYNOPSIS | |||
268 | */ | |||
269 | static void | |||
270 | SetNoVisit(void) | |||
271 | /* | |||
272 | * DESCRIPTION | |||
273 | * | |||
274 | * RETURNS | |||
275 | * void | |||
276 | * | |||
277 | */ | |||
278 | { | |||
279 | int i; | |||
280 | XcmsPair *pair = pairs; | |||
281 | ||||
282 | for (i = 0; i < nEntries; i++, pair++) { | |||
283 | if (pair->flag != CYCLE0xFFFF) { | |||
284 | pair->flag = NOT_VISITED0x0; | |||
285 | } | |||
286 | } | |||
287 | } | |||
288 | ||||
289 | ||||
290 | ||||
291 | ||||
292 | /* | |||
293 | * NAME | |||
294 | * field2 - extract two fields | |||
295 | * | |||
296 | * SYNOPSIS | |||
297 | */ | |||
298 | static int | |||
299 | field2( | |||
300 | char *pBuf, | |||
301 | char delim, /* in: field delimiter */ | |||
302 | char **p1, /* in/out: pointer to pointer to field 1 */ | |||
303 | char **p2) /* in/out: pointer to pointer to field 2 */ | |||
304 | /* | |||
305 | * DESCRIPTION | |||
306 | * Extracts two fields from a "record". | |||
307 | * | |||
308 | * RETURNS | |||
309 | * XcmsSuccess if succeeded, otherwise XcmsFailure. | |||
310 | * | |||
311 | */ | |||
312 | { | |||
313 | *p1 = *p2 = NULL((void*)0); | |||
314 | ||||
315 | /* Find Field 1 */ | |||
316 | while (!isgraph(*pBuf)(isprint((*pBuf)) && !isspace((*pBuf)))) { | |||
317 | if ((*pBuf == '\n') || (*pBuf == '\0')) { | |||
318 | return(XcmsFailure0); | |||
319 | } | |||
320 | if (isspace(*pBuf) || (*pBuf == delim)) { | |||
321 | pBuf++; | |||
322 | } | |||
323 | } | |||
324 | *p1 = pBuf; | |||
325 | ||||
326 | /* Find end of Field 2 */ | |||
327 | while (isprint(*pBuf) && (*pBuf != delim)) { | |||
328 | pBuf++; | |||
329 | } | |||
330 | if ((*pBuf == '\n') || (*pBuf == '\0')) { | |||
331 | return(XcmsFailure0); | |||
332 | } | |||
333 | if ((*pBuf == ' ') || (*pBuf == delim)) { | |||
334 | *pBuf++ = '\0'; /* stuff end of string character */ | |||
335 | } else { | |||
336 | return(XcmsFailure0); | |||
337 | } | |||
338 | ||||
339 | /* Find Field 2 */ | |||
340 | while (!isgraph(*pBuf)(isprint((*pBuf)) && !isspace((*pBuf)))) { | |||
341 | if ((*pBuf == '\n') || (*pBuf == '\0')) { | |||
342 | return(XcmsFailure0); | |||
343 | } | |||
344 | if (isspace(*pBuf) || (*pBuf == delim)) { | |||
345 | pBuf++; | |||
346 | } | |||
347 | } | |||
348 | *p2 = pBuf; | |||
349 | ||||
350 | /* Find end of Field 2 */ | |||
351 | while (isprint(*pBuf) && (*pBuf != delim)) { | |||
352 | pBuf++; | |||
353 | } | |||
354 | if (*pBuf != '\0') { | |||
355 | *pBuf = '\0'; /* stuff end of string character */ | |||
356 | } | |||
357 | ||||
358 | return(XcmsSuccess1); | |||
359 | } | |||
360 | ||||
361 | ||||
362 | /* | |||
363 | * NAME | |||
364 | * _XcmsLookupColorName - Lookup DB entry for a color name | |||
365 | * | |||
366 | * SYNOPSIS | |||
367 | */ | |||
368 | static Statusint | |||
369 | _XcmsLookupColorName( | |||
370 | XcmsCCC ccc, | |||
371 | const char **name, | |||
372 | XcmsColor *pColor) | |||
373 | /* | |||
374 | * DESCRIPTION | |||
375 | * Searches for an entry in the Device-Independent Color Name | |||
376 | * Database for the specified string. | |||
377 | * | |||
378 | * RETURNS | |||
379 | * XcmsFailure if failed to find a matching entry in | |||
380 | * the database. | |||
381 | * XcmsSuccess if succeeded in converting color name to | |||
382 | * XcmsColor. | |||
383 | * _XCMS_NEWNAME if succeeded in converting color string (which | |||
384 | * is a color name to yet another color name. Note | |||
385 | * that the new name is passed back via 'name'. | |||
386 | */ | |||
387 | { | |||
388 | Statusint retval = 0; | |||
389 | char name_lowered_64[64]; | |||
390 | char *name_lowered; | |||
391 | register int i, j, left, right; | |||
392 | int len; | |||
393 | const char *tmpName; | |||
394 | XcmsPair *pair = NULL((void*)0); | |||
395 | ||||
396 | /* | |||
397 | * Check state of Database: | |||
398 | * XcmsDbInitNone | |||
399 | * XcmsDbInitSuccess | |||
400 | * XcmsDbInitFailure | |||
401 | */ | |||
402 | if (XcmsColorDbState == XcmsDbInitFailure0) { | |||
403 | return(XcmsFailure0); | |||
404 | } | |||
405 | if (XcmsColorDbState == XcmsDbInitNone-1) { | |||
406 | if (!LoadColornameDB()) { | |||
407 | return(XcmsFailure0); | |||
408 | } | |||
409 | } | |||
410 | ||||
411 | SetNoVisit(); | |||
412 | ||||
413 | /* | |||
414 | * While copying name to name_lowered, convert to lowercase | |||
415 | */ | |||
416 | ||||
417 | tmpName = *name; | |||
418 | ||||
419 | Retry: | |||
420 | if ((len = strlen(tmpName)) > 63) { | |||
421 | name_lowered = Xmalloc(len+1)malloc(((len+1) == 0 ? 1 : (len+1))); | |||
422 | } else { | |||
423 | name_lowered = name_lowered_64; | |||
424 | } | |||
425 | ||||
426 | _XcmsCopyISOLatin1Lowered(name_lowered, tmpName); | |||
427 | ||||
428 | /* | |||
429 | * Now, remove spaces. | |||
430 | */ | |||
431 | for (i = 0, j = 0; j < len; j++) { | |||
432 | if (!isspace(name_lowered[j])) { | |||
| ||||
433 | name_lowered[i++] = name_lowered[j]; | |||
434 | } | |||
435 | } | |||
436 | name_lowered[i] = '\0'; | |||
437 | ||||
438 | left = 0; | |||
439 | right = nEntries - 1; | |||
440 | while (left <= right) { | |||
441 | i = (left + right) >> 1; | |||
442 | pair = &pairs[i]; | |||
443 | j = strcmp(name_lowered, pair->first); | |||
444 | if (j < 0) | |||
445 | right = i - 1; | |||
446 | else if (j > 0) | |||
447 | left = i + 1; | |||
448 | else { | |||
449 | break; | |||
450 | } | |||
451 | } | |||
452 | if (len > 63) Xfree(name_lowered)free((name_lowered)); | |||
453 | ||||
454 | if (left > right) { | |||
455 | if (retval == 2) { | |||
456 | if (*name != tmpName) { | |||
457 | *name = tmpName; | |||
458 | } | |||
459 | return(_XCMS_NEWNAME-1); | |||
460 | } | |||
461 | return(XcmsFailure0); | |||
462 | } | |||
463 | ||||
464 | if (pair->flag == CYCLE0xFFFF) { | |||
465 | return(XcmsFailure0); | |||
466 | } | |||
467 | if (pair->flag == VISITED0x1) { | |||
468 | pair->flag = CYCLE0xFFFF; | |||
469 | return(XcmsFailure0); | |||
470 | } | |||
471 | ||||
472 | if (_XcmsParseColorString(ccc, pair->second, pColor) == XcmsSuccess1) { | |||
473 | /* f2 contains a numerical string specification */ | |||
474 | return(XcmsSuccess1); | |||
475 | } else { | |||
476 | /* f2 does not contain a numerical string specification */ | |||
477 | tmpName = pair->second; | |||
478 | pair->flag = VISITED0x1; | |||
479 | retval = 2; | |||
480 | goto Retry; | |||
481 | } | |||
482 | } | |||
483 | ||||
484 | ||||
485 | /* | |||
486 | * NAME | |||
487 | * RemoveSpaces | |||
488 | * | |||
489 | * SYNOPSIS | |||
490 | */ | |||
491 | static int | |||
492 | RemoveSpaces( | |||
493 | char *pString) | |||
494 | /* | |||
495 | * DESCRIPTION | |||
496 | * Removes spaces from string. | |||
497 | * | |||
498 | * RETURNS | |||
499 | * Void | |||
500 | * | |||
501 | */ | |||
502 | { | |||
503 | int i, count = 0; | |||
504 | char *cptr; | |||
505 | ||||
506 | /* REMOVE SPACES */ | |||
507 | cptr = pString; | |||
508 | for (i = strlen(pString); i; i--, cptr++) { | |||
509 | if (!isspace(*cptr)) { | |||
510 | *pString++ = *cptr; | |||
511 | count++; | |||
512 | } | |||
513 | } | |||
514 | *pString = '\0'; | |||
515 | return(count); | |||
516 | } | |||
517 | ||||
518 | ||||
519 | /* | |||
520 | * NAME | |||
521 | * stringSectionSize - determine memory needed for strings | |||
522 | * | |||
523 | * SYNOPSIS | |||
524 | */ | |||
525 | static int | |||
526 | stringSectionSize( | |||
527 | FILE *stream, | |||
528 | int *pNumEntries, | |||
529 | int *pSectionSize) | |||
530 | /* | |||
531 | * DESCRIPTION | |||
532 | * Determines the amount of memory required to store the | |||
533 | * color name strings and also the number of strings. | |||
534 | * | |||
535 | * RETURNS | |||
536 | * XcmsSuccess if succeeded, otherwise XcmsFailure. | |||
537 | * | |||
538 | */ | |||
539 | { | |||
540 | char buf[XCMSDB_MAXLINELEN256]; | |||
541 | char token[XCMSDB_MAXLINELEN256]; | |||
542 | char token2[XCMSDB_MAXLINELEN256]; | |||
543 | char *pBuf; | |||
544 | char *f1; | |||
545 | char *f2; | |||
546 | size_t i; | |||
547 | ||||
548 | unsigned int numEntries = 0; | |||
549 | unsigned int sectionSize = 0; | |||
550 | ||||
551 | *pNumEntries = 0; | |||
552 | *pSectionSize = 0; | |||
553 | ||||
554 | /* | |||
555 | * Advance to START_TOKEN | |||
556 | * Anything before is just considered as comments. | |||
557 | */ | |||
558 | ||||
559 | while((pBuf = fgets(buf, XCMSDB_MAXLINELEN256, stream)) != NULL((void*)0)) { | |||
560 | if ((sscanf(buf, "%s %s", token, token2)) | |||
561 | && (strcmp(token, START_TOKEN"XCMS_COLORDB_START") == 0)) { | |||
562 | if (strcmp(token2, FORMAT_VERSION"0.1") != 0) { | |||
563 | /* text file not in the right format */ | |||
564 | return(XcmsFailure0); | |||
565 | } | |||
566 | break; | |||
567 | } /* else it was just a blank line or comment */ | |||
568 | } | |||
569 | ||||
570 | if (pBuf == NULL((void*)0)) { | |||
571 | return(XcmsFailure0); | |||
572 | } | |||
573 | ||||
574 | while((fgets(buf, XCMSDB_MAXLINELEN256, stream)) != NULL((void*)0)) { | |||
575 | if ((sscanf(buf, "%s", token)) && (strcmp(token, END_TOKEN"XCMS_COLORDB_END") == 0)) { | |||
576 | break; | |||
577 | } | |||
578 | ||||
579 | if (field2(buf, DELIM_CHAR'\t', &f1, &f2) != XcmsSuccess1) { | |||
580 | return(XcmsFailure0); | |||
581 | } | |||
582 | ||||
583 | numEntries++; | |||
584 | if (numEntries >= INT_MAX2147483647) | |||
585 | return(XcmsFailure0); | |||
586 | ||||
587 | i = strlen(f1); | |||
588 | if (i >= INT_MAX2147483647 - sectionSize) | |||
589 | return(XcmsFailure0); | |||
590 | sectionSize += i + 1; | |||
591 | for (; i; i--, f1++) { | |||
592 | /* REMOVE SPACES FROM COUNT */ | |||
593 | if (isspace(*f1)) { | |||
594 | sectionSize--; | |||
595 | } | |||
596 | } | |||
597 | ||||
598 | i = strlen(f2); | |||
599 | if (i >= INT_MAX2147483647 - sectionSize) | |||
600 | return(XcmsFailure0); | |||
601 | sectionSize += i + 1; | |||
602 | for (; i; i--, f2++) { | |||
603 | /* REMOVE SPACES FROM COUNT */ | |||
604 | if (isspace(*f2)) { | |||
605 | sectionSize--; | |||
606 | } | |||
607 | } | |||
608 | ||||
609 | } | |||
610 | ||||
611 | *pNumEntries = (int) numEntries; | |||
612 | *pSectionSize = (int) sectionSize; | |||
613 | ||||
614 | return(XcmsSuccess1); | |||
615 | } | |||
616 | ||||
617 | ||||
618 | /* | |||
619 | * NAME | |||
620 | * ReadColornameDB - Read the Color Name Database | |||
621 | * | |||
622 | * SYNOPSIS | |||
623 | */ | |||
624 | static Statusint | |||
625 | ReadColornameDB( | |||
626 | FILE *stream, | |||
627 | XcmsPair *pRec, | |||
628 | char *pString) | |||
629 | /* | |||
630 | * DESCRIPTION | |||
631 | * Loads the Color Name Database from a text file. | |||
632 | * | |||
633 | * RETURNS | |||
634 | * XcmsSuccess if succeeded, otherwise XcmsFailure. | |||
635 | * | |||
636 | */ | |||
637 | { | |||
638 | char buf[XCMSDB_MAXLINELEN256]; | |||
639 | char token[XCMSDB_MAXLINELEN256]; | |||
640 | char token2[XCMSDB_MAXLINELEN256]; | |||
641 | char *f1; | |||
642 | char *f2; | |||
643 | char *pBuf; | |||
644 | ||||
645 | /* | |||
646 | * Advance to START_TOKEN | |||
647 | * Anything before is just considered as comments. | |||
648 | */ | |||
649 | ||||
650 | while((pBuf = fgets(buf, XCMSDB_MAXLINELEN256, stream)) != NULL((void*)0)) { | |||
651 | if ((sscanf(buf, "%s %s", token, token2)) | |||
652 | && (strcmp(token, START_TOKEN"XCMS_COLORDB_START") == 0)) { | |||
653 | if (strcmp(token2, FORMAT_VERSION"0.1") != 0) { | |||
654 | /* text file not in the right format */ | |||
655 | return(XcmsFailure0); | |||
656 | } | |||
657 | break; | |||
658 | } /* else it was just a blank line or comment */ | |||
659 | } | |||
660 | ||||
661 | if (pBuf == NULL((void*)0)) { | |||
662 | return(XcmsFailure0); | |||
663 | } | |||
664 | ||||
665 | /* | |||
666 | * Process lines between START_TOKEN to END_TOKEN | |||
667 | */ | |||
668 | ||||
669 | while ((fgets(buf, XCMSDB_MAXLINELEN256, stream)) != NULL((void*)0)) { | |||
670 | if ((sscanf(buf, "%s", token)) && (strcmp(token, END_TOKEN"XCMS_COLORDB_END") == 0)) { | |||
671 | /* | |||
672 | * Found END_TOKEN so break out of for loop | |||
673 | */ | |||
674 | break; | |||
675 | } | |||
676 | ||||
677 | /* | |||
678 | * Get pairs | |||
679 | */ | |||
680 | if (field2(buf, DELIM_CHAR'\t', &f1, &f2) != XcmsSuccess1) { | |||
681 | /* Invalid line */ | |||
682 | continue; | |||
683 | } | |||
684 | ||||
685 | /* | |||
686 | * Add strings | |||
687 | */ | |||
688 | ||||
689 | /* Left String */ | |||
690 | pRec->first = pString; | |||
691 | _XcmsCopyISOLatin1Lowered(pString, f1); | |||
692 | pString += (1 + RemoveSpaces(pString)); | |||
693 | pRec->second = pString; | |||
694 | /* Right String */ | |||
695 | _XcmsCopyISOLatin1Lowered(pString, f2); | |||
696 | pString += RemoveSpaces(pString) + 1; | |||
697 | pRec++; | |||
698 | ||||
699 | } | |||
700 | ||||
701 | return(XcmsSuccess1); | |||
702 | } | |||
703 | ||||
704 | ||||
705 | /* | |||
706 | * NAME | |||
707 | * LoadColornameDB - Load the Color Name Database | |||
708 | * | |||
709 | * SYNOPSIS | |||
710 | */ | |||
711 | static Statusint | |||
712 | LoadColornameDB(void) | |||
713 | /* | |||
714 | * DESCRIPTION | |||
715 | * Loads the Color Name Database from a text file. | |||
716 | * | |||
717 | * RETURNS | |||
718 | * XcmsSuccess if succeeded, otherwise XcmsFailure. | |||
719 | * | |||
720 | */ | |||
721 | { | |||
722 | int size; | |||
723 | FILE *stream; | |||
724 | const char *pathname; | |||
725 | struct stat txt; | |||
726 | int length; | |||
727 | ||||
728 | /* use and name of this env var is not part of the standard */ | |||
729 | /* implementation-dependent feature */ | |||
730 | if ((pathname = getenv("XCMSDB")) == NULL((void*)0)) { | |||
731 | pathname = XCMSDB"/Users/jeremy/src/freedesktop/jhbuild/build/share/X11" "/Xcms.txt"; | |||
732 | } | |||
733 | #ifdef __UNIXOS2__ | |||
734 | pathname = __XOS2RedirRoot(pathname); | |||
735 | #endif | |||
736 | ||||
737 | length = strlen(pathname); | |||
738 | if ((length == 0) || (length >= (BUFSIZ1024 - 5))){ | |||
739 | XcmsColorDbState = XcmsDbInitFailure0; | |||
740 | return(XcmsFailure0); | |||
741 | } | |||
742 | ||||
743 | if (stat(pathname, &txt)) { | |||
744 | /* can't stat file */ | |||
745 | XcmsColorDbState = XcmsDbInitFailure0; | |||
746 | return(XcmsFailure0); | |||
747 | } | |||
748 | ||||
749 | if ((stream = _XFopenFile (pathname, "r")fopen(pathname,"r")) == NULL((void*)0)) { | |||
750 | /* can't open file */ | |||
751 | XcmsColorDbState = XcmsDbInitFailure0; | |||
752 | return(XcmsFailure0); | |||
753 | } | |||
754 | ||||
755 | if (stringSectionSize(stream, &nEntries, &size) != XcmsSuccess1 || | |||
756 | nEntries == 0) { | |||
757 | (void) fclose(stream); | |||
758 | XcmsColorDbState = XcmsDbInitFailure0; | |||
759 | return(XcmsFailure0); | |||
760 | } | |||
761 | rewind(stream); | |||
762 | ||||
763 | strings = Xmalloc(size)malloc(((size) == 0 ? 1 : (size))); | |||
764 | pairs = Xcalloc(nEntries, sizeof(XcmsPair))calloc(((nEntries) == 0 ? 1 : (nEntries)), (sizeof(XcmsPair)) ); | |||
765 | ||||
766 | ReadColornameDB(stream, pairs, strings); | |||
767 | (void) fclose(stream); | |||
768 | ||||
769 | /* | |||
770 | * sort the pair recs | |||
771 | */ | |||
772 | qsort((char *)pairs, nEntries, sizeof(XcmsPair), FirstCmp); | |||
773 | ||||
774 | XcmsColorDbState = XcmsDbInitSuccess1; | |||
775 | return(XcmsSuccess1); | |||
776 | } | |||
777 | ||||
778 | ||||
779 | /************************************************************************ | |||
780 | * * | |||
781 | * API PRIVATE ROUTINES * | |||
782 | * * | |||
783 | ************************************************************************/ | |||
784 | ||||
785 | /* | |||
786 | * NAME | |||
787 | * _XcmsCopyISOLatin1Lowered | |||
788 | * | |||
789 | * SYNOPSIS | |||
790 | */ | |||
791 | void | |||
792 | _XcmsCopyISOLatin1Lowered( | |||
793 | char *dst, | |||
794 | const char *src) | |||
795 | /* | |||
796 | * DESCRIPTION | |||
797 | * ISO Latin-1 case conversion routine | |||
798 | * Identical to XmuCopyISOLatin1Lowered() but provided here | |||
799 | * to eliminate need to link with libXmu.a. | |||
800 | * | |||
801 | * IMPLEMENTORS NOTE: | |||
802 | * This routine is also used in XcmsFormatOfPrefix. | |||
803 | * | |||
804 | * RETURNS | |||
805 | * Void | |||
806 | * | |||
807 | */ | |||
808 | { | |||
809 | register unsigned char *dest; | |||
810 | register const unsigned char *source; | |||
811 | ||||
812 | for (dest = (unsigned char *)dst, source = (const unsigned char *)src; | |||
813 | *source; | |||
814 | source++, dest++) | |||
815 | { | |||
816 | if ((*source >= XK_A0x0041) && (*source <= XK_Z0x005a)) | |||
817 | *dest = *source + (XK_a0x0061 - XK_A0x0041); | |||
818 | else if ((*source >= XK_Agrave0x00c0) && (*source <= XK_Odiaeresis0x00d6)) | |||
819 | *dest = *source + (XK_agrave0x00e0 - XK_Agrave0x00c0); | |||
820 | else if ((*source >= XK_Ooblique0x00d8) && (*source <= XK_Thorn0x00de)) | |||
821 | *dest = *source + (XK_oslash0x00f8 - XK_Ooblique0x00d8); | |||
822 | else | |||
823 | *dest = *source; | |||
824 | } | |||
825 | *dest = '\0'; | |||
826 | } | |||
827 | ||||
828 | ||||
829 | /* | |||
830 | * NAME | |||
831 | * _XcmsResolveColorString - | |||
832 | * | |||
833 | * SYNOPSIS | |||
834 | */ | |||
835 | Statusint | |||
836 | _XcmsResolveColorString ( | |||
837 | XcmsCCC ccc, | |||
838 | const char **color_string, | |||
839 | XcmsColor *pColor_exact_return, | |||
840 | XcmsColorFormat result_format) | |||
841 | /* | |||
842 | * DESCRIPTION | |||
843 | * The XcmsLookupColor function finds the color specification | |||
844 | * associated with a color name in the Device-Independent Color | |||
845 | * Name Database. | |||
846 | * RETURNS | |||
847 | * XcmsFailure if failed to convert valid color string. | |||
848 | * XcmsSuccess if succeeded in converting color string to | |||
849 | * XcmsColor. | |||
850 | * _XCMS_NEWNAME if failed to parse the string or find it in | |||
851 | * the database, or if succeeded in looking it up and | |||
852 | * found another name which is not in the database. | |||
853 | * Note that the new name is returned in color_string. | |||
854 | * | |||
855 | * This function returns both the color specification found in the | |||
856 | * database (db specification) and the color specification for the | |||
857 | * color displayable by the specified screen (screen | |||
858 | * specification). The calling routine sets the format for these | |||
859 | * returned specifications in the XcmsColor format component. | |||
860 | * If XcmsUndefinedFormat, the specification is returned in the | |||
861 | * format used to store the color in the database. | |||
862 | */ | |||
863 | { | |||
864 | XcmsColor dbWhitePt; /* whitePt associated with pColor_exact_return*/ | |||
865 | /* the screen's white point */ | |||
866 | XcmsColor *pClientWhitePt; | |||
867 | int retval; | |||
868 | const char *strptr = whitePtStr; | |||
869 | ||||
870 | /* | |||
871 | * 0. Check for invalid arguments. | |||
872 | */ | |||
873 | if (ccc == NULL((void*)0) || (*color_string)[0] == '\0' || pColor_exact_return == NULL((void*)0)) { | |||
| ||||
874 | return(XcmsFailure0); | |||
875 | } | |||
876 | ||||
877 | /* | |||
878 | * 1. First attempt to parse the string | |||
879 | * If successful, then convert the specification to the target format | |||
880 | * and return. | |||
881 | */ | |||
882 | if (_XcmsParseColorString(ccc, *color_string, pColor_exact_return) | |||
883 | == 1) { | |||
884 | if (result_format != XcmsUndefinedFormat(XcmsColorFormat)0x00000000 | |||
885 | && pColor_exact_return->format != result_format) { | |||
886 | /* need to be converted to the target format */ | |||
887 | return(XcmsConvertColors(ccc, pColor_exact_return, 1, | |||
888 | result_format, (Boolint *)NULL((void*)0))); | |||
889 | } else { | |||
890 | return(XcmsSuccess1); | |||
891 | } | |||
892 | } | |||
893 | ||||
894 | /* | |||
895 | * 2. Attempt to find it in the DI Color Name Database | |||
896 | */ | |||
897 | ||||
898 | /* | |||
899 | * a. Convert String into a XcmsColor structure | |||
900 | * Attempt to extract the specification for color_string from the | |||
901 | * DI Database (pColor_exact_return). If the DI Database does not | |||
902 | * have this entry, then return failure. | |||
903 | */ | |||
904 | retval = _XcmsLookupColorName(ccc, color_string, pColor_exact_return); | |||
905 | ||||
906 | if (retval != XcmsSuccess1) { | |||
907 | /* color_string replaced with a color name, or not found */ | |||
908 | return(_XCMS_NEWNAME-1); | |||
909 | } | |||
910 | ||||
911 | if (pColor_exact_return->format == XcmsUndefinedFormat(XcmsColorFormat)0x00000000) { | |||
912 | return(XcmsFailure0); | |||
913 | } | |||
914 | ||||
915 | /* | |||
916 | * b. If result_format not defined, then assume target format | |||
917 | * is the exact format. | |||
918 | */ | |||
919 | if (result_format == XcmsUndefinedFormat(XcmsColorFormat)0x00000000) { | |||
920 | result_format = pColor_exact_return->format; | |||
921 | } | |||
922 | ||||
923 | if ((ClientWhitePointOfCCC(ccc)(&(ccc)->clientWhitePt))->format == XcmsUndefinedFormat(XcmsColorFormat)0x00000000) { | |||
924 | pClientWhitePt = ScreenWhitePointOfCCC(ccc)(&(ccc)->pPerScrnInfo->screenWhitePt); | |||
925 | } else { | |||
926 | pClientWhitePt = ClientWhitePointOfCCC(ccc)(&(ccc)->clientWhitePt); | |||
927 | } | |||
928 | ||||
929 | /* | |||
930 | * c. Convert to the target format, making adjustments for white | |||
931 | * point differences as necessary. | |||
932 | */ | |||
933 | if (XCMS_DD_ID(pColor_exact_return->format)((pColor_exact_return->format) & (XcmsColorFormat)0x80000000 )) { | |||
934 | /* | |||
935 | * The spec format is Device-Dependent, therefore assume the | |||
936 | * its white point is the Screen White Point. | |||
937 | */ | |||
938 | if (XCMS_DD_ID(result_format)((result_format) & (XcmsColorFormat)0x80000000)) { | |||
939 | /* | |||
940 | * Target format is Device-Dependent | |||
941 | * Therefore, DD --> DD conversion | |||
942 | */ | |||
943 | return(_XcmsDDConvertColors(ccc, pColor_exact_return, | |||
944 | 1, result_format, (Boolint *) NULL((void*)0))); | |||
945 | } else { | |||
946 | /* | |||
947 | * Target format is Device-Independent | |||
948 | * Therefore, DD --> DI conversion | |||
949 | */ | |||
950 | if (ccc->whitePtAdjProc && !_XcmsEqualWhitePts(ccc, | |||
951 | pClientWhitePt, ScreenWhitePointOfCCC(ccc)(&(ccc)->pPerScrnInfo->screenWhitePt))) { | |||
952 | return((*ccc->whitePtAdjProc)(ccc, ScreenWhitePointOfCCC(ccc)(&(ccc)->pPerScrnInfo->screenWhitePt), | |||
953 | pClientWhitePt, result_format, | |||
954 | pColor_exact_return, 1, (Boolint *) NULL((void*)0))); | |||
955 | } else { | |||
956 | if (_XcmsDDConvertColors(ccc, pColor_exact_return, 1, | |||
957 | XcmsCIEXYZFormat(XcmsColorFormat)0x00000001, (Boolint *) NULL((void*)0)) == XcmsFailure0) { | |||
958 | return(XcmsFailure0); | |||
959 | } | |||
960 | return(_XcmsDIConvertColors(ccc, pColor_exact_return, | |||
961 | pClientWhitePt, 1, result_format)); | |||
962 | } | |||
963 | } | |||
964 | } else { | |||
965 | /* | |||
966 | * The spec format is Device-Independent, therefore attempt | |||
967 | * to find a database white point. | |||
968 | * | |||
969 | * If the Database does not have a white point, then assume the | |||
970 | * database white point is the same as the Screen White Point. | |||
971 | */ | |||
972 | ||||
973 | if (_XcmsLookupColorName(ccc, &strptr, &dbWhitePt) != 1) { | |||
974 | memcpy((char *)&dbWhitePt,__builtin___memcpy_chk ((char *)&dbWhitePt, (char *)& ccc->pPerScrnInfo->screenWhitePt, sizeof(XcmsColor), __builtin_object_size ((char *)&dbWhitePt, 0)) | |||
975 | (char *)&ccc->pPerScrnInfo->screenWhitePt,__builtin___memcpy_chk ((char *)&dbWhitePt, (char *)& ccc->pPerScrnInfo->screenWhitePt, sizeof(XcmsColor), __builtin_object_size ((char *)&dbWhitePt, 0)) | |||
976 | sizeof(XcmsColor))__builtin___memcpy_chk ((char *)&dbWhitePt, (char *)& ccc->pPerScrnInfo->screenWhitePt, sizeof(XcmsColor), __builtin_object_size ((char *)&dbWhitePt, 0)); | |||
977 | } | |||
978 | if (XCMS_DD_ID(result_format)((result_format) & (XcmsColorFormat)0x80000000)) { | |||
979 | /* | |||
980 | * Target format is Device-Dependent | |||
981 | * Therefore, DI --> DD conversion | |||
982 | */ | |||
983 | if (ccc->whitePtAdjProc && !_XcmsEqualWhitePts(ccc, | |||
984 | &dbWhitePt, ScreenWhitePointOfCCC(ccc)(&(ccc)->pPerScrnInfo->screenWhitePt))) { | |||
985 | return((*ccc->whitePtAdjProc)(ccc, &dbWhitePt, | |||
986 | ScreenWhitePointOfCCC(ccc)(&(ccc)->pPerScrnInfo->screenWhitePt), result_format, | |||
987 | pColor_exact_return, 1, (Boolint *)NULL((void*)0))); | |||
988 | } else { | |||
989 | if (pColor_exact_return->format != XcmsCIEXYZFormat(XcmsColorFormat)0x00000001) { | |||
990 | if (_XcmsDIConvertColors(ccc, pColor_exact_return, | |||
991 | &dbWhitePt, 1, XcmsCIEXYZFormat(XcmsColorFormat)0x00000001) == XcmsFailure0) { | |||
992 | return(XcmsFailure0); | |||
993 | } | |||
994 | } | |||
995 | return (_XcmsDDConvertColors(ccc, pColor_exact_return, 1, | |||
996 | result_format, (Boolint *)NULL((void*)0))); | |||
997 | } | |||
998 | } else { | |||
999 | /* | |||
1000 | * Target format is Device-Independent | |||
1001 | * Therefore, DI --> DI conversion | |||
1002 | */ | |||
1003 | if (ccc->whitePtAdjProc && !_XcmsEqualWhitePts(ccc, | |||
1004 | &dbWhitePt, pClientWhitePt)) { | |||
1005 | /* | |||
1006 | * The calling routine wants to resolve this color | |||
1007 | * in terms if it's white point (i.e. Client White Point). | |||
1008 | * Therefore, apply white adjustment for the displacement | |||
1009 | * between dbWhitePt to clientWhitePt. | |||
1010 | */ | |||
1011 | return((*ccc->whitePtAdjProc)(ccc, &dbWhitePt, | |||
1012 | pClientWhitePt, result_format, | |||
1013 | pColor_exact_return, 1, (Boolint *)NULL((void*)0))); | |||
1014 | } else if (_XcmsEqualWhitePts(ccc, | |||
1015 | &dbWhitePt, pClientWhitePt)) { | |||
1016 | /* | |||
1017 | * Can use either dbWhitePt or pClientWhitePt to | |||
1018 | * convert to the result_format. | |||
1019 | */ | |||
1020 | if (pColor_exact_return->format == result_format) { | |||
1021 | return(XcmsSuccess1); | |||
1022 | } else { | |||
1023 | return (_XcmsDIConvertColors(ccc, pColor_exact_return, | |||
1024 | &dbWhitePt, 1, result_format)); | |||
1025 | } | |||
1026 | } else { | |||
1027 | /* | |||
1028 | * Need to convert to a white point independent color | |||
1029 | * space (let's choose CIEXYZ) then convert to the | |||
1030 | * target color space. Why? Lets assume that | |||
1031 | * pColor_exact_return->format and result format | |||
1032 | * are white point dependent format (e.g., CIELUV, CIELAB, | |||
1033 | * TekHVC ... same or any combination). If so, we'll | |||
1034 | * need to convert the color with dbWhitePt to an absolute | |||
1035 | * spec (i.e. non-white point dependent) then convert that | |||
1036 | * absolute value with clientWhitePt to the result_format. | |||
1037 | */ | |||
1038 | if (pColor_exact_return->format != XcmsCIEXYZFormat(XcmsColorFormat)0x00000001) { | |||
1039 | if (_XcmsDIConvertColors(ccc, pColor_exact_return, | |||
1040 | &dbWhitePt, 1, XcmsCIEXYZFormat(XcmsColorFormat)0x00000001) == XcmsFailure0) { | |||
1041 | return(XcmsFailure0); | |||
1042 | } | |||
1043 | } | |||
1044 | if (result_format == XcmsCIEXYZFormat(XcmsColorFormat)0x00000001) { | |||
1045 | return(XcmsSuccess1); | |||
1046 | } else { | |||
1047 | return(_XcmsDIConvertColors(ccc, pColor_exact_return, | |||
1048 | pClientWhitePt, 1, result_format)); | |||
1049 | } | |||
1050 | } | |||
1051 | } | |||
1052 | } | |||
1053 | } |