loadData.c revision c1e8faa6
1/* $Xorg: loadData.c,v 1.4 2000/08/17 19:54:13 cpqbld Exp $ */
2
3/*
4 * (c) Copyright 1990 Tektronix Inc.
5 * 	All Rights Reserved
6 *
7 * Permission to use, copy, modify, and distribute this software and its
8 * documentation for any purpose and without fee is hereby granted,
9 * provided that the above copyright notice appear in all copies and that
10 * both that copyright notice and this permission notice appear in
11 * supporting documentation, and that the name of Tektronix not be used
12 * in advertising or publicity pertaining to distribution of the software
13 * without specific, written prior permission.
14 *
15 * Tektronix disclaims all warranties with regard to this software, including
16 * all implied warranties of merchantability and fitness, in no event shall
17 * Tektronix be liable for any special, indirect or consequential damages or
18 * any damages whatsoever resulting from loss of use, data or profits,
19 * whether in an action of contract, negligence or other tortious action,
20 * arising out of or in connection with the use or performance of this
21 * software.
22 *
23 *
24 *	NAME
25 *		LoadSCCData.c
26 *
27 *	DESCRIPTION
28 *		TekCMS API routine that reads screen data from a file
29 *	        and then loads the data on the root window of the screen.
30 *
31 *
32 *
33 */
34/* $XFree86: xc/programs/xcmsdb/loadData.c,v 3.3 2001/07/25 15:05:18 dawes Exp $ */
35
36/*
37 *      INCLUDES
38 */
39
40#ifdef HAVE_CONFIG_H
41#include "config.h"
42#endif
43
44#include <X11/Xos.h>
45#include <sys/stat.h>
46#include <stdio.h>
47
48#include <X11/Xlib.h>
49#include <X11/Xatom.h>
50#include "SCCDFile.h"
51
52
53/*
54 *      EXTERNS
55 *              External declarations required locally to this package
56 *              that are not already declared in any of the included header
57 *		files (external includes or internal includes).
58 */
59
60#include <stdlib.h>
61
62/*
63 *      LOCAL TYPEDEFS
64 *              typedefs local to this package (for use with local vars).
65 *
66 */
67
68typedef const struct _DefineEntry {
69    const char	*pString;
70    int		define;
71} DefineEntry;
72
73
74/*
75 *      LOCAL VARIABLES
76 */
77static int linenum = 0;
78
79static DefineEntry KeyTbl[] = {
80    { SC_BEGIN_KEYWORD,			SC_BEGIN },
81    { SC_END_KEYWORD,			SC_END },
82    { COMMENT_KEYWORD,			COMMENT },
83    { NAME_KEYWORD,			NAME },
84    { MODEL_KEYWORD,			MODEL },
85    { PART_NUMBER_KEYWORD,		PART_NUMBER },
86    { SERIAL_NUMBER_KEYWORD,		SERIAL_NUMBER },
87    { REVISION_KEYWORD,			REVISION },
88    { SCREEN_CLASS_KEYWORD,		SCREEN_CLASS },
89    { COLORIMETRIC_BEGIN_KEYWORD,	COLORIMETRIC_BEGIN },
90    { COLORIMETRIC_END_KEYWORD,		COLORIMETRIC_END },
91    { XYZTORGBMAT_BEGIN_KEYWORD,	XYZTORGBMAT_BEGIN },
92    { XYZTORGBMAT_END_KEYWORD,		XYZTORGBMAT_END },
93    { WHITEPT_XYZ_BEGIN_KEYWORD,	WHITEPT_XYZ_BEGIN },
94    { WHITEPT_XYZ_END_KEYWORD,		WHITEPT_XYZ_END },
95    { RGBTOXYZMAT_BEGIN_KEYWORD,	RGBTOXYZMAT_BEGIN },
96    { RGBTOXYZMAT_END_KEYWORD,		RGBTOXYZMAT_END },
97    { IPROFILE_BEGIN_KEYWORD,		IPROFILE_BEGIN },
98    { IPROFILE_END_KEYWORD,		IPROFILE_END },
99    { ITBL_BEGIN_KEYWORD,		ITBL_BEGIN },
100    { ITBL_END_KEYWORD,			ITBL_END },
101    { "",				-1 }
102};
103
104static DefineEntry ScrnClassTbl[] = {
105    { VIDEO_RGB_KEYWORD,		VIDEO_RGB },
106#ifdef GRAY
107    { VIDEO_GRAY_KEYWORD,		VIDEO_GRAY },
108#endif /* GRAY */
109    { "",				-1 }
110};
111
112#define KEY_VISUALID		1
113#define KEY_DEPTH		2
114#define KEY_CLASS		3
115#define KEY_RED_MASK		4
116#define KEY_GREEN_MASK		5
117#define KEY_BLUE_MASK		6
118#define KEY_COLORMAP_SIZE	7
119#define KEY_BITS_PER_RGB	8
120
121static DefineEntry VisualOptKeyTbl[] = {
122    { "visualid",		KEY_VISUALID },
123    { "depth",			KEY_DEPTH },
124    { "class",			KEY_CLASS },
125    { "red_mask",		KEY_RED_MASK },
126    { "green_mask",		KEY_GREEN_MASK },
127    { "blue_mask",		KEY_BLUE_MASK },
128    { "colormap_size",		KEY_COLORMAP_SIZE },
129    { "bits_per_rgb",		KEY_BITS_PER_RGB },
130    { "",			-1 }
131};
132
133static DefineEntry VisualClassTbl[] = {
134    { "StaticGray",		StaticGray },
135    { "GrayScale",		GrayScale },
136    { "StaticColor",		StaticColor },
137    { "PseudoColor",		PseudoColor },
138    { "TrueColor",		TrueColor },
139    { "DirectColor",		DirectColor },
140    { "",			-1 }
141};
142
143
144/************************************************************************
145 *									*
146 *			 PRIVATE ROUTINES				*
147 *									*
148 ************************************************************************/
149
150/*
151 *	NAME
152 *		StrToDefine - convert a string to a define
153 *
154 *	SYNOPSIS
155 */
156static int
157StrToDefine(DefineEntry pde[],   /* IN: table of X string-define pairs     */
158                                 /*     last entry must contain pair "", 0 */
159            const char *pstring) /* IN: string to be looked up in that table */
160/*
161 *	DESCRIPTION
162 *		Converts a string to an integer define.
163 *
164 *		Looks up the string in the table and returns the integer
165 *		associated with the string.
166 *
167 *		Later may need similar function for unsigned long define.
168 *
169 *
170 *
171 *	RETURNS
172 *		The int equivalent of the defined string.
173 *		-1 if the string is not found in table
174 *
175 */
176{
177    while (strcmp(pde->pString, "") != 0) {
178        if (strcmp(pde->pString, pstring) == 0) {
179            return (pde->define);
180        }
181        pde++;
182    }
183    return (-1);
184}
185
186/*
187 *	NAME
188 *		DefineToStr
189 *
190 *	SYNOPSIS
191 */
192static const char *
193DefineToStr(DefineEntry pde[],  /* IN: table of X string-define pairs */
194                                /*     last entry must contain pair "", 0 */
195            int id)             /* IN: id to be looked up in that table   */
196/*
197 *	DESCRIPTION
198 *		Converts an integer define to a string.
199 *
200 *		Looks up the integer in the table and returns the string
201 *		associated with the integer.
202 *
203 *		Later may need similar function for unsigned long define.
204 *
205 *
206 *
207 *	RETURNS
208 *		The int equivalent of the defined string.
209 *		NULL if the string is not found in table
210 *
211 */
212{
213    while (pde->define != -1) {
214        if (pde->define == id) {
215            return (pde->pString);
216        }
217        pde++;
218    }
219    return (NULL);
220}
221
222/*
223 *	NAME
224 *		SCKeyOf - convert keyword into key ID
225 *
226 *	SYNOPSIS
227 */
228static int
229SCKeyOf(const char *string)
230/*
231 *	DESCRIPTION
232 *		Converts a string to an integer define.
233 *
234 *		Looks up the string in the table and returns the integer
235 *		associated with the string.
236 *
237 *		Later may need similar function for unsigned long define.
238 *
239 *
240 *
241 *	RETURNS
242 *		The int equivalent of the defined string.
243 *		-1 if the string is not found in table
244 *
245 */
246{
247    return (StrToDefine(KeyTbl, string));
248}
249
250/*
251 *	NAME
252 *		SCScrnClassOf - convert screen class string into class ID
253 *
254 *	SYNOPSIS
255 */
256static int
257SCScrnClassOf(const char *string)
258/*
259 *	DESCRIPTION
260 *		Converts a string to an integer define.
261 *
262 *		Looks up the string in the table and returns the integer
263 *		associated with the string.
264 *
265 *		Later may need similar function for unsigned long define.
266 *
267 *
268 *
269 *	RETURNS
270 *		The int equivalent of the defined string.
271 *		-1 if the string is not found in table
272 *
273 */
274{
275    return (StrToDefine(ScrnClassTbl, string));
276}
277
278/*
279 *	NAME
280 *		SCScrnClassStringOf - convert screen class id into class string
281 *
282 *	SYNOPSIS
283 */
284static const char *
285SCScrnClassStringOf(int id)
286/*
287 *	DESCRIPTION
288 *		Converts a id to astring
289 *
290 *	RETURNS
291 *		Pointer to string if found; otherwise "unknown".
292 *
293 */
294{
295    const char *str = DefineToStr(ScrnClassTbl, id);
296
297    if (str != NULL)
298        return str;
299    else
300        return "unknown";
301}
302
303/* close the stream and return any memory allocated. */
304static void
305closeS(FILE *stream, XDCCC_Correction *pCorrection)
306{
307    if (stream) {
308        fclose(stream);
309    }
310    while (pCorrection) {
311        XDCCC_Correction *pNext = pCorrection->next;
312        free(pCorrection);
313        pCorrection = pNext;
314    }
315}
316
317/*
318 *  Get a line of text from the stream.
319 */
320static char *
321nextline(char *buf, int maxch, FILE *stream)
322{
323    linenum++;
324    return (fgets(buf, maxch, stream));
325}
326
327static int
328ProcessColorimetric(FILE *stream, XDCCC_Matrix *pMatrix, int VisualFlag)
329{
330    char buf[BUFSIZ];
331    char keyword[BUFSIZ];
332    char token[BUFSIZ];
333    unsigned int matrices_processed = 0;
334		/* bit 0 for XYZtoRGB matrix */
335		/* bit 1 for RGBtoXYZ matrix */
336    int	 state = 0;
337		 /* 0 -- looking for matrix */
338		 /* 1 -- processing data from matrix */
339		 /* 2 -- both matrices processed */
340		 /* Note: the order of the matrices is not important. */
341    int	 count = -1;
342    XcmsFloat *pElement = NULL;
343
344    while ((nextline(buf, BUFSIZ, stream)) != NULL) {
345        int ntok = sscanf(buf, "%1023s %1023s", keyword, token);
346
347        if (ntok > 0) {
348            switch (SCKeyOf(keyword)) {
349            case XYZTORGBMAT_BEGIN:
350                if (VisualFlag != VIDEO_RGB) {
351                    fprintf(stderr,
352                            "Line %d: Keyword XYZTORGBMAT_BEGIN mismatch for visual %s.\n",
353                            linenum, SCScrnClassStringOf(VisualFlag));
354                    return (0);
355                }
356                if (state != 0) {
357                    fprintf(stderr,
358                            "Line %d: Extraneous keyword %s.\n",
359                            linenum, keyword);
360                    return (0);
361                }
362                state = 1;
363                count = 0;
364                pElement = (XcmsFloat *) pMatrix->XYZtoRGBmatrix;
365                break;
366            case XYZTORGBMAT_END:
367                if (VisualFlag != VIDEO_RGB) {
368                    fprintf(stderr,
369                            "Line %d: Keyword XYZTORGBMAT_END mismatch for visual %s.\n",
370                            linenum, SCScrnClassStringOf(VisualFlag));
371                    return (0);
372                }
373                if ((state != 1) || (count != 9)) {
374                    fprintf(stderr,
375                            "Line %d: Incomplete XYZtoRGB matrix -- Premature %s\n",
376                            linenum, keyword);
377                    return (0);
378                }
379                matrices_processed |= 0x1;
380                if (matrices_processed == 3) {
381                    state = 2;
382                }
383                else {
384                    state = 0;
385                }
386                break;
387            case RGBTOXYZMAT_BEGIN:
388                if (VisualFlag != VIDEO_RGB) {
389                    fprintf(stderr,
390                            "Line %d: Keyword RGBTOXYZMAT_BEGIN mismatch for visual %s.\n",
391                            linenum, SCScrnClassStringOf(VisualFlag));
392                    return (0);
393                }
394                if (state != 0) {
395                    fprintf(stderr, "Line %d: Extraneous keyword %s.\n",
396                            linenum, keyword);
397                    return (0);
398                }
399                state = 1;
400                count = 0;
401                pElement = (XcmsFloat *) pMatrix->RGBtoXYZmatrix;
402                break;
403            case RGBTOXYZMAT_END:
404                if (VisualFlag != VIDEO_RGB) {
405                    fprintf(stderr,
406                            "Line %d: Keyword RGBTOXYZMAT_END mismatch for visual %s.\n",
407                            linenum, SCScrnClassStringOf(VisualFlag));
408                    return (0);
409                }
410                if ((state != 1) || (count != 9)) {
411                    fprintf(stderr,
412                            "Line %d: Incomplete RGBtoXYZ matrix -- Premature %s\n",
413                            linenum, keyword);
414                    return (0);
415                }
416                matrices_processed |= 0x2;
417                if (matrices_processed == 3) {
418                    state = 2;
419                }
420                else {
421                    state = 0;
422                }
423                break;
424#ifdef GRAY
425            case WHITEPT_XYZ_BEGIN:
426                if (VisualFlag != VIDEO_GRAY) {
427                    fprintf(stderr,
428                            "Line %d: Keyword WHITEPT_XYZ_BEGIN mismatch for visual %s.\n",
429                            linenum, SCScrnClassStringOf(VisualFlag));
430                    return (0);
431                }
432                if (state != 0) {
433                    fprintf(stderr,
434                            "Line %d: Extraneous keyword %s.\n",
435                            linenum, keyword);
436                    return (0);
437                }
438                state = 1;
439                count = 0;
440                pElement = (XcmsFloat *) pMatrix->XYZtoRGBmatrix;
441                break;
442            case WHITEPT_XYZ_END:
443                if (VisualFlag != VIDEO_GRAY) {
444                    fprintf(stderr,
445                            "Line %d: Keyword WHITEPT_XYZ_END mismatch for visual %s.\n",
446                            linenum, SCScrnClassStringOf(VisualFlag));
447                    return (0);
448                }
449                if ((state != 1) || (count != 3)) {
450                    fprintf(stderr,
451                            "Line %d: Incomplete white point -- Premature %s\n",
452                            linenum, keyword);
453                    return (0);
454                }
455                state = 2;
456                break;
457#endif /* GRAY */
458            case DATA:
459                for (char *ptoken = strtok(buf, DATA_DELIMS); ptoken != NULL;
460                     ptoken = strtok(NULL, DATA_DELIMS)) {
461                    if (sscanf(ptoken, "%lf", pElement) != 1) {
462                        if (VisualFlag == VIDEO_RGB) {
463                            fprintf(stderr,
464                                    "Line %d: Invalid matrix value %s.",
465                                    linenum, ptoken);
466                        }
467                        else {
468                            fprintf(stderr,
469                                    "Line %d: Invalid CIEXYZ value %s.\n",
470                                    linenum, ptoken);
471                        }
472                        return (0);
473                    }
474                    pElement++;
475                    if (VisualFlag == VIDEO_RGB) {
476                        if (++count > 9) {
477                            fprintf(stderr,
478                                    "Line %d: Extra matrix value %s\n",
479                                    linenum, ptoken);
480                            return (0);
481                        }
482                    }
483                    else {
484                        if (++count > 3) {
485                            fprintf(stderr,
486                                    "Line %d: Extra CIEXYZ value %s.\n",
487                                    linenum, ptoken);
488                            return (0);
489                        }
490                    }
491                }
492                break;
493            case COLORIMETRIC_BEGIN:
494                fprintf(stderr,
495                        "Line %d: Extraneous keyword %s.\n", linenum, keyword);
496                return (0);
497            case COLORIMETRIC_END:
498                if (state != 2) {
499                    fprintf(stderr,
500                            "Line %d: Incomplete Colorimetric data -- Premature %s\n",
501                            linenum, keyword);
502                    return (0);
503                }
504                return (1);
505            case COMMENT:
506                /* Currently, do nothing. */
507                break;
508            default:
509                fprintf(stderr,
510                        "Line %d: Unexpected keyword %s\n", linenum, keyword);
511                return (0);
512            }
513        }
514        else if (ntok < 0) {
515            /* mismatch */
516            fprintf(stderr, "Line %d: Unrecognized keyword\n", linenum);
517            return (0);
518        }
519    }
520    return (0);
521}
522
523static int
524ProcessIProfile(FILE *stream, XDCCC_Correction *pCorrection)
525{
526    char buf[BUFSIZ];
527    char *tableStr, *sizeStr;
528    int  size;
529    int  state = 0;
530         /************************************************
531	  * 0 -- Looking for Intensity Table(s)          *
532	  * 1 -- Processing Intensity Table(s)           *
533          ************************************************/
534    int  nTbl = 0;
535    int  count = 0;
536    IntensityRec *pIRec = NULL;
537
538    while ((nextline(buf, BUFSIZ, stream)) != NULL) {
539        char *ptoken = strtok(buf, DATA_DELIMS);
540        char *keyword = ptoken;
541
542        if (keyword != NULL) {
543            switch (SCKeyOf(keyword)) {
544            case ITBL_BEGIN:
545                if (state != 0) {
546                    fprintf(stderr, "Line %d: unexpected keyword %s\n",
547                            linenum, keyword);
548                    return (0);
549                }
550                tableStr = strtok(NULL, DATA_DELIMS);
551                sizeStr = strtok(NULL, DATA_DELIMS);
552                if ((sizeStr == NULL) ||
553                    sscanf(sizeStr, "%d", &size) != 1) {
554                    fprintf(stderr,
555                            "Line %d: invalid Intensity Table size, %s.\n",
556                            linenum, sizeStr ? sizeStr : "\"\"");
557                    return (0);
558                }
559                if (size < 0) {
560                    fprintf(stderr,
561                            "Line %d: count %d < 0 for Intensity Table.\n",
562                            linenum, size);
563                    return (0);
564                }
565                if (strcmp(tableStr, "GREEN") == 0) {
566                    if (pCorrection->nTables != 3) {
567                        fprintf(stderr, "Line %d: incorrect number of tables\n",
568                                linenum);
569                        return (0);
570                    }
571                    if (pCorrection->pGreenTbl->pBase != NULL) {
572                        fprintf(stderr,
573                                "Line %d: multiple GREEN Intensity Profiles\n",
574                                linenum);
575                        return (0);
576                    }
577                    pCorrection->pGreenTbl->nEntries = size;
578                    pCorrection->pGreenTbl->pBase =
579                        calloc(size, sizeof(IntensityRec));
580                    if (pCorrection->pGreenTbl->pBase == NULL) {
581                        fprintf(stderr,
582                                "Line %d: Unable to allocate space for GREEN Intensity Profile\n",
583                                linenum);
584                        return (0);
585                    }
586                    pIRec = pCorrection->pGreenTbl->pBase;
587                }
588                else if (strcmp(tableStr, "BLUE") == 0) {
589                    if (pCorrection->nTables != 3) {
590                        fprintf(stderr,
591                                "Line %d: incorrect number of tables\n",
592                                linenum);
593                        return (0);
594                    }
595                    if (pCorrection->pBlueTbl->pBase != NULL) {
596                        fprintf(stderr,
597                                "Line %d: multiple BLUE Intensity Profiles\n",
598                                linenum);
599                        return (0);
600                    }
601                    pCorrection->pBlueTbl->nEntries = size;
602                    pCorrection->pBlueTbl->pBase =
603                        calloc(size, sizeof(IntensityRec));
604                    if (pCorrection->pBlueTbl->pBase == NULL) {
605                        fprintf(stderr,
606                                "Line %d: Unable to allocate space for BLUE Intensity Profile\n",
607                                linenum);
608                        return (0);
609                    }
610                    pIRec = pCorrection->pBlueTbl->pBase;
611                }
612                else {
613                    if (!strcmp(tableStr, "RGB") && pCorrection->nTables != 1) {
614                        fprintf(stderr,
615                                "Line %d: multiple RGB Intensity Tables",
616                                linenum);
617                        return (0);
618                    }
619                    if (pCorrection->pRedTbl->pBase != NULL) {
620                        fprintf(stderr,
621                                "Line %d: multiple RED or GREEN or BLUE Intensity Tables\n",
622                                linenum);
623                        return (0);
624                    }
625                    pCorrection->pRedTbl->nEntries = size;
626                    pCorrection->pRedTbl->pBase =
627                        calloc(size, sizeof(IntensityRec));
628                    if (pCorrection->pRedTbl->pBase == NULL) {
629                        fprintf(stderr,
630                                "Line %d: Unable to allocate space for intensity table\n",
631                                linenum);
632                        return (0);
633                    }
634                    pIRec = pCorrection->pRedTbl->pBase;
635                }
636                state = 1;
637                count = 0;
638                break;
639            case ITBL_END:
640                if ((state != 1) || (count != size)) {
641                    fprintf(stderr,
642                            "Line %d: incomplete Intensity Table -- Premature %s\n",
643                            linenum, keyword);
644                    return (0);
645                }
646                nTbl++;
647                state = 0;
648                break;
649            case DATA:
650                if (pIRec == NULL) {
651                    fprintf(stderr,
652                            "Line %d: Invalid Intensity Profile -- Premature %s\n",
653                            linenum, keyword);
654                    return (0);
655                }
656                do {
657                    /********************************************************
658		     * Note: tableType should only be 0 or 1 at this point.
659		     *       0 indicates value and intensity stored.
660		     *       1 indicates only intensity stored.
661		     ********************************************************/
662                    if (pCorrection->tableType) {
663                        if (sscanf(ptoken, "%lf", &pIRec->intensity) != 1) {
664                            fprintf(stderr,
665                                    "Line %d: invalid Intensity Profile value %s\n",
666                                    linenum, ptoken);
667                            return (0);
668                        }
669                        /* With tableType 1 only store the intensity. */
670                        pIRec++;
671                    }
672                    else {
673                        short tmp;
674
675                        /* Note ANSI C can handle 0x preceding hex number */
676                        if (sscanf(ptoken, "%hi", &tmp) != 1) {
677                            fprintf(stderr,
678                                    "Line %d: invalid Intensity Profile value %s\n",
679                                    linenum, ptoken);
680                            return (0);
681                        }
682                        else
683                            pIRec->value = tmp;
684                        if ((ptoken = strtok(NULL, DATA_DELIMS)) == NULL) {
685                            fprintf(stderr,
686                                    "Line %d: missing Intensity Profile value\n",
687                                    linenum);
688                            return (0);
689                        }
690                        if (sscanf(ptoken, "%lf", &pIRec->intensity) != 1) {
691                            fprintf(stderr,
692                                    "Line %d: invalid Intensity Profile intensity %s\n",
693                                    linenum, ptoken);
694                            return (0);
695                        }
696                        /* With tableType 0 only store both value & intensity */
697                        pIRec++;
698                    }
699                    if (++count > size) {
700                        fprintf(stderr,
701                                "Line %d: extra Intensity value %s\n",
702                                linenum, ptoken);
703                        return (0);
704                    }
705                    ptoken = strtok(NULL, DATA_DELIMS);
706                } while (ptoken != NULL);
707                break;
708            case IPROFILE_BEGIN:
709                fprintf(stderr, "Line %d: extraneous keyword %s\n",
710                        linenum, keyword);
711                return (0);
712            case IPROFILE_END:
713                if ((state != 0) || (nTbl != pCorrection->nTables)) {
714                    fprintf(stderr,
715                            "Line %d: incomplete Intensity Profile data -- Premature %s\n",
716                            linenum, keyword);
717                    return (0);
718                }
719                return (1);
720            case COMMENT:
721                /* ignore line */
722                break;
723            default:
724                fprintf(stderr, "Line %d: unexpected keyword %s\n",
725                        linenum, keyword);
726                return (0);
727            }
728        }                       /* else its was just a blank line */
729    }
730    return (0);
731}
732
733static void
734PutTableType0Card8(IntensityTbl *pTbl, unsigned char **pCard8)
735{
736    unsigned int count;
737    IntensityRec *pIRec;
738
739    pIRec = pTbl->pBase;
740    count = pTbl->nEntries;
741    **pCard8 = count - 1;
742    *pCard8 += 1;
743    for (; count; count--, pIRec++) {
744        **pCard8 = pIRec->value >> 8;
745        *pCard8 += 1;
746        **pCard8 = pIRec->intensity * 255.0;
747        *pCard8 += 1;
748    }
749}
750
751static void
752PutTableType1Card8(IntensityTbl *pTbl, unsigned char **pCard8)
753{
754    unsigned int count;
755    IntensityRec *pIRec;
756
757    pIRec = pTbl->pBase;
758    count = pTbl->nEntries;
759    **pCard8 = count - 1;
760    *pCard8 += 1;
761    for (; count; count--, pIRec++) {
762        **pCard8 = pIRec->intensity * 255.0;
763        *pCard8 += 1;
764    }
765}
766
767static void
768PutTableType0Card16(IntensityTbl *pTbl, unsigned short **pCard16)
769{
770    unsigned int count;
771    IntensityRec *pIRec;
772
773    pIRec = pTbl->pBase;
774    count = pTbl->nEntries;
775    **pCard16 = count - 1;
776    *pCard16 += 1;
777    for (; count; count--, pIRec++) {
778        **pCard16 = pIRec->value;
779        *pCard16 += 1;
780        **pCard16 = pIRec->intensity * 65535.0;
781        *pCard16 += 1;
782    }
783}
784
785static void
786PutTableType1Card16(IntensityTbl *pTbl, unsigned short **pCard16)
787{
788    unsigned int count;
789    IntensityRec *pIRec;
790
791    pIRec = pTbl->pBase;
792    count = pTbl->nEntries;
793    **pCard16 = count - 1;
794    *pCard16 += 1;
795    for (; count; count--, pIRec++) {
796        **pCard16 = pIRec->intensity * 65535.0;
797        *pCard16 += 1;
798    }
799}
800
801static void
802PutTableType0Card32(IntensityTbl *pTbl, unsigned long **pCard32)
803{
804    unsigned int count;
805    IntensityRec *pIRec;
806
807    pIRec = pTbl->pBase;
808    count = pTbl->nEntries;
809    **pCard32 = count - 1;
810    *pCard32 += 1;
811    for (; count; count--, pIRec++) {
812        **pCard32 = pIRec->value;
813        *pCard32 += 1;
814        **pCard32 = pIRec->intensity * 4294967295.0;
815        *pCard32 += 1;
816    }
817}
818
819static void
820PutTableType1Card32(IntensityTbl *pTbl, unsigned long **pCard32)
821{
822    unsigned int count;
823    IntensityRec *pIRec;
824
825    pIRec = pTbl->pBase;
826    count = pTbl->nEntries;
827    **pCard32 = count - 1;
828    *pCard32 += 1;
829    for (; count; count--, pIRec++) {
830        **pCard32 = pIRec->intensity * 4294967295.0;
831        *pCard32 += 1;
832    }
833}
834
835static void
836LoadMatrix(Display * pDpy, Window root, XDCCC_Matrix * pMatrix)
837{
838    int count;
839    unsigned long *pCard32;
840    unsigned long Card32Array[18];
841    Atom MatricesAtom;
842    XcmsFloat *pValue;
843
844    /*
845     * Store the XDCCC_LINEAR_RGB_MATRICES
846     */
847    pCard32 = Card32Array;
848    pValue = (XcmsFloat *) pMatrix->XYZtoRGBmatrix;
849    for (count = 0; count < 9; count++) {
850        *pCard32++ = (unsigned long) (*pValue++ * (XcmsFloat) XDCCC_NUMBER);
851    }
852    pValue = (XcmsFloat *) pMatrix->RGBtoXYZmatrix;
853    for (count = 0; count < 9; count++) {
854        *pCard32++ = (unsigned long) (*pValue++ * (XcmsFloat) XDCCC_NUMBER);
855    }
856    MatricesAtom = XInternAtom(pDpy, XDCCC_MATRIX_ATOM_NAME, False);
857    XChangeProperty(pDpy, root, MatricesAtom, XA_INTEGER, 32,
858                    PropModeReplace, (unsigned char *) Card32Array, 18);
859}
860
861static int
862LoadCorrections(Display *pDpy, Window root, XDCCC_Correction *pCorrection,
863                int targetFormat)
864{
865    unsigned char *pCard8;
866    unsigned char *pCard8Array = NULL;
867    unsigned short *pCard16;
868    unsigned short *pCard16Array = NULL;
869    unsigned long *pCard32;
870    unsigned long *pCard32Array = NULL;
871    Atom CorrectAtom;
872    int total;
873    int i;
874
875    /*
876     * Store each XDCCC_CORRECTION into XDCCC_LINEAR_RGB_CORRECTION property
877     */
878    CorrectAtom = XInternAtom(pDpy, XDCCC_CORRECT_ATOM_NAME, False);
879
880    for (i = 0; pCorrection; i++, pCorrection = pCorrection->next) {
881        if ((pCorrection->tableType != 0) && (pCorrection->tableType != 1)) {
882            if (pCorrection->visual_info.visualid) {
883                fprintf(stderr,
884                        "RGB Correction for visualid %ld: Invalid intensity table type %d.\n",
885                        pCorrection->visual_info.visualid,
886                        pCorrection->tableType);
887            }
888            else {
889                fprintf(stderr,
890                        "Global RGB Correction: Invalid intensity table type %d.\n",
891                        pCorrection->tableType);
892            }
893            return (0);
894        }
895
896        if (pCorrection->nTables != 1 && pCorrection->nTables != 3) {
897            if (pCorrection->visual_info.visualid) {
898                fprintf(stderr,
899                        "RGB Correction for visualid %ld: %d invalid number of tables.\n",
900                        pCorrection->visual_info.visualid,
901                        pCorrection->nTables);
902            }
903            else {
904                fprintf(stderr,
905                        "Global RGB Correction: %d invalid number of tables.\n",
906                        pCorrection->nTables);
907            }
908            return (0);
909        }
910
911        if (pCorrection->nTables == 1) {
912            if (pCorrection->pRedTbl->nEntries < 2) {
913                if (pCorrection->visual_info.visualid) {
914                    fprintf(stderr,
915                            "RGB Correction for visualid %ld: Illegal number of entries in table\n",
916                            pCorrection->visual_info.visualid);
917                }
918                else {
919                    fprintf(stderr,
920                            "Global RGB Correction: Illegal number of entries in table\n");
921                }
922                return (0);
923            }
924            switch (targetFormat) {
925            case 8:
926                total = 7 + (pCorrection->pRedTbl->nEntries *
927                             (pCorrection->tableType == 0 ? 2 : 1));
928                pCard8 = pCard8Array = calloc(total, sizeof(unsigned char));
929                if (pCard8 == NULL) {
930                    fprintf(stderr, "Unable allocate array of ints\n");
931                    return (0);
932                }
933                *pCard8++ = (pCorrection->visual_info.visualid >> 24) & 0xFF;
934                *pCard8++ = (pCorrection->visual_info.visualid >> 16) & 0xFF;
935                *pCard8++ = (pCorrection->visual_info.visualid >> 8) & 0xFF;
936                *pCard8++ = (pCorrection->visual_info.visualid) & 0xFF;
937                *pCard8++ = pCorrection->tableType;     /* type */
938                *pCard8++ = 1;  /* number of tables = 1 */
939                if (pCorrection->tableType == 0) {
940                    PutTableType0Card8(pCorrection->pRedTbl, &pCard8);
941                }
942                else {
943                    PutTableType1Card8(pCorrection->pRedTbl, &pCard8);
944                }
945                XChangeProperty(pDpy, root, CorrectAtom, XA_INTEGER, 8,
946                                i ? PropModeAppend : PropModeReplace,
947                                (unsigned char *) pCard8Array, total);
948                free(pCard8Array);
949                break;
950            case 16:
951                total = 5 + (pCorrection->pRedTbl->nEntries *
952                             (pCorrection->tableType == 0 ? 2 : 1));
953                pCard16 = pCard16Array = calloc(total, sizeof (unsigned short));
954                if (pCard16 == NULL) {
955                    fprintf(stderr, "Unable allocate array of ints\n");
956                    return (0);
957                }
958                *pCard16++ = (pCorrection->visual_info.visualid >> 16) & 0xFFFF;
959                *pCard16++ = (pCorrection->visual_info.visualid) & 0xFFFF;
960                *pCard16++ = pCorrection->tableType;    /* type */
961                *pCard16++ = 1; /* number of tables = 1 */
962                if (pCorrection->tableType == 0) {
963                    PutTableType0Card16(pCorrection->pRedTbl, &pCard16);
964                }
965                else {
966                    PutTableType1Card16(pCorrection->pRedTbl, &pCard16);
967                }
968                XChangeProperty(pDpy, root, CorrectAtom, XA_INTEGER, 16,
969                                i ? PropModeAppend : PropModeReplace,
970                                (unsigned char *) pCard16Array, total);
971                free(pCard16Array);
972                break;
973            case 32:
974                total = 4 + (pCorrection->pRedTbl->nEntries *
975                             (pCorrection->tableType == 0 ? 2 : 1));
976                pCard32 = pCard32Array = calloc(total, sizeof(unsigned long));
977                if (pCard32 == NULL) {
978                    fprintf(stderr, "Unable allocate array of ints\n");
979                    return (0);
980                }
981                *pCard32++ = pCorrection->visual_info.visualid;
982                *pCard32++ = pCorrection->tableType;    /* type */
983                *pCard32++ = 1; /* number of tables = 1 */
984                if (pCorrection->tableType == 0) {
985                    PutTableType0Card32(pCorrection->pRedTbl, &pCard32);
986                }
987                else {
988                    PutTableType1Card32(pCorrection->pRedTbl, &pCard32);
989                }
990                XChangeProperty(pDpy, root, CorrectAtom, XA_INTEGER, 32,
991                                i ? PropModeAppend : PropModeReplace,
992                                (unsigned char *) pCard32Array, total);
993                free(pCard32Array);
994                break;
995            default:
996                if (pCorrection->visual_info.visualid) {
997                    fprintf(stderr,
998                            "RGB Correction for visualid %ld: Invalid property format\n",
999                            pCorrection->visual_info.visualid);
1000                }
1001                else {
1002                    fprintf(stderr,
1003                            "Global RGB Correction: Invalid property format\n");
1004                }
1005                return (0);
1006            }
1007        }
1008        else {                  /* pCorrection->nTables == 3 */
1009            if ((pCorrection->pRedTbl->nEntries < 2) ||
1010                (pCorrection->pGreenTbl->nEntries < 2) ||
1011                (pCorrection->pBlueTbl->nEntries < 2)) {
1012                if (pCorrection->visual_info.visualid) {
1013                    fprintf(stderr,
1014                            "RGB Correction for visualid %ld: Illegal number of entries in table\n",
1015                            pCorrection->visual_info.visualid);
1016                }
1017                else {
1018                    fprintf(stderr,
1019                            "Global RGB Correction: Illegal number of entries in table\n");
1020                }
1021                return (0);
1022            }
1023            switch (targetFormat) {
1024            case 8:
1025                total = 9 +     /* visualID, type, and 3 lengths */
1026                    (pCorrection->pRedTbl->nEntries *
1027                     (pCorrection->tableType == 0 ? 2 : 1)) +
1028                    (pCorrection->pGreenTbl->nEntries *
1029                     (pCorrection->tableType == 0 ? 2 : 1)) +
1030                    (pCorrection->pBlueTbl->nEntries *
1031                     (pCorrection->tableType == 0 ? 2 : 1));
1032                pCard8 = pCard8Array = calloc(total, sizeof(unsigned char));
1033                if (pCard8 == NULL) {
1034                    fprintf(stderr, "Unable allocate array of ints\n");
1035                    return (0);
1036                }
1037                *pCard8++ = (pCorrection->visual_info.visualid >> 24) & 0xFF;
1038                *pCard8++ = (pCorrection->visual_info.visualid >> 16) & 0xFF;
1039                *pCard8++ = (pCorrection->visual_info.visualid >> 8) & 0xFF;
1040                *pCard8++ = (pCorrection->visual_info.visualid) & 0xFF;
1041                *pCard8++ = pCorrection->tableType;     /* type */
1042                *pCard8++ = 3;  /* number of tables = 3 */
1043                if (pCorrection->tableType == 0) {
1044                    PutTableType0Card8(pCorrection->pRedTbl, &pCard8);
1045                    PutTableType0Card8(pCorrection->pGreenTbl, &pCard8);
1046                    PutTableType0Card8(pCorrection->pBlueTbl, &pCard8);
1047                }
1048                else {
1049                    PutTableType1Card8(pCorrection->pRedTbl, &pCard8);
1050                    PutTableType1Card8(pCorrection->pGreenTbl, &pCard8);
1051                    PutTableType1Card8(pCorrection->pBlueTbl, &pCard8);
1052                }
1053                XChangeProperty(pDpy, root, CorrectAtom, XA_INTEGER, 8,
1054                                i ? PropModeAppend : PropModeReplace,
1055                                (unsigned char *) pCard8Array, total);
1056                free(pCard8Array);
1057                break;
1058            case 16:
1059                total = 7 +     /* visualID, type, and 3 lengths */
1060                    (pCorrection->pRedTbl->nEntries *
1061                     (pCorrection->tableType == 0 ? 2 : 1)) +
1062                    (pCorrection->pGreenTbl->nEntries *
1063                     (pCorrection->tableType == 0 ? 2 : 1)) +
1064                    (pCorrection->pBlueTbl->nEntries *
1065                     (pCorrection->tableType == 0 ? 2 : 1));
1066                pCard16 = pCard16Array = calloc(total, sizeof(unsigned short));
1067                if (pCard16 == NULL) {
1068                    fprintf(stderr, "Unable allocate array of ints\n");
1069                    return (0);
1070                }
1071                *pCard16++ = (pCorrection->visual_info.visualid >> 16) & 0xFFFF;
1072                *pCard16++ = (pCorrection->visual_info.visualid) & 0xFFFF;
1073                *pCard16++ = pCorrection->tableType;    /* type = 0 */
1074                *pCard16++ = 3; /* number of tables = 3 */
1075                if (pCorrection->tableType == 0) {
1076                    PutTableType0Card16(pCorrection->pRedTbl, &pCard16);
1077                    PutTableType0Card16(pCorrection->pGreenTbl, &pCard16);
1078                    PutTableType0Card16(pCorrection->pBlueTbl, &pCard16);
1079                }
1080                else {
1081                    PutTableType1Card16(pCorrection->pRedTbl, &pCard16);
1082                    PutTableType1Card16(pCorrection->pGreenTbl, &pCard16);
1083                    PutTableType1Card16(pCorrection->pBlueTbl, &pCard16);
1084                }
1085                XChangeProperty(pDpy, root, CorrectAtom, XA_INTEGER, 16,
1086                                i ? PropModeAppend : PropModeReplace,
1087                                (unsigned char *) pCard16Array, total);
1088                free(pCard16Array);
1089                break;
1090            case 32:
1091                total = 6 +     /* visualID, type, and 3 lengths */
1092                    (pCorrection->pRedTbl->nEntries *
1093                     (pCorrection->tableType == 0 ? 2 : 1)) +
1094                    (pCorrection->pGreenTbl->nEntries *
1095                     (pCorrection->tableType == 0 ? 2 : 1)) +
1096                    (pCorrection->pBlueTbl->nEntries *
1097                     (pCorrection->tableType == 0 ? 2 : 1));
1098                pCard32 = pCard32Array = calloc(total, sizeof(unsigned long));
1099                if (pCard32 == NULL) {
1100                    fprintf(stderr, "Unable allocate array of ints\n");
1101                    return (0);
1102                }
1103                *pCard32++ = pCorrection->visual_info.visualid;
1104                *pCard32++ = pCorrection->tableType;    /* type */
1105                *pCard32++ = 3; /* number of tables = 3 */
1106                if (pCorrection->tableType == 0) {
1107                    PutTableType0Card32(pCorrection->pRedTbl, &pCard32);
1108                    PutTableType0Card32(pCorrection->pGreenTbl, &pCard32);
1109                    PutTableType0Card32(pCorrection->pBlueTbl, &pCard32);
1110                }
1111                else {
1112                    PutTableType1Card32(pCorrection->pRedTbl, &pCard32);
1113                    PutTableType1Card32(pCorrection->pGreenTbl, &pCard32);
1114                    PutTableType1Card32(pCorrection->pBlueTbl, &pCard32);
1115                }
1116                XChangeProperty(pDpy, root, CorrectAtom, XA_INTEGER, 32,
1117                                i ? PropModeAppend : PropModeReplace,
1118                                (unsigned char *) pCard32Array, total);
1119                free(pCard32Array);
1120                break;
1121            default:
1122                if (pCorrection->visual_info.visualid) {
1123                    fprintf(stderr,
1124                            "RGB Correction for visualid %ld: Invalid property format\n",
1125                            pCorrection->visual_info.visualid);
1126                }
1127                else {
1128                    fprintf(stderr,
1129                            "Global RGB Correction: Invalid property format\n");
1130                }
1131                return (0);
1132            }
1133        }
1134    }
1135
1136    return (1);
1137}
1138
1139#ifdef GRAY
1140
1141static int
1142LoadDataGray(Display *pDpy, window root, int tableType,
1143             LINEAR_RGB_SCCData *pScreenData, int targetFormat)
1144{
1145    int nLevels;
1146    unsigned char *pCard8;
1147    unsigned char *pCard8Array = NULL;
1148    unsigned short *pCard16;
1149    unsigned short *pCard16Array = NULL;
1150    unsigned long *pCard32;
1151    unsigned long *pCard32Array = NULL;
1152    unsigned long Card32Array[18];
1153    Atom MatricesAtom, CorrectAtom;
1154    XcmsFloat *pValue;
1155    int total;
1156
1157    /* Now store the XDCCC_SCREENWHITEPT */
1158    pCard32 = Card32Array;
1159    pValue = (XcmsFloat *) pScreenData->XYZtoRGBmatrix;
1160    for (int count = 0; count < 3; count++) {
1161        *pCard32++ = (unsigned long) (*pValue++ * (XcmsFloat) XDCCC_NUMBER);
1162    }
1163    MatricesAtom = XInternAtom(pDpy, XDCCC_SCREENWHITEPT_ATOM_NAME, False);
1164    XChangeProperty(pDpy, root, MatricesAtom, XA_INTEGER, 32,
1165                    PropModeReplace, (unsigned char *) Card32Array, 3);
1166
1167    /* Now store the XDCCC_GRAY_CORRECTION */
1168    CorrectAtom = XInternAtom(pDpy, XDCCC_GRAY_CORRECT_ATOM_NAME, False);
1169
1170    if (tableType == CORR_TYPE_NONE) {
1171        unsigned char *ret_prop;
1172        Atom ret_atom;
1173        int ret_format;
1174        unsigned long ret_len, ret_after;
1175
1176        XGetWindowProperty(pDpy, root, CorrectAtom,
1177                           0, 5, False, XA_INTEGER,
1178                           &ret_atom, &ret_format, &ret_len, &ret_after,
1179                           &ret_prop);
1180        if (ret_format != 0) {
1181            XDeleteProperty(pDpy, root, CorrectAtom);
1182            XFree(ret_prop);
1183        }
1184        return (1);
1185    }
1186    nLevels = pScreenData->pRedTbl->nEntries;
1187    if (nLevels < 2) {
1188        fprintf(stderr, "Illegal number of entries in table\n");
1189        return (0);
1190    }
1191    switch (targetFormat) {
1192    case 8:
1193        total = 6               /* visualID, type, length */
1194            + (nLevels * (tableType == 0 ? 2 : 1));
1195        pCard8 = pCard8Array = calloc(total, sizeof(unsigned char));
1196        if (pCard8 == NULL) {
1197            fprintf(stderr, "Unable allocate array of Card8\n");
1198            return (0);
1199        }
1200        *pCard8++ = 0;          /* VisualID = 0 */
1201        *pCard8++ = 0;          /* VisualID = 0 */
1202        *pCard8++ = 0;          /* VisualID = 0 */
1203        *pCard8++ = 0;          /* VisualID = 0 */
1204        *pCard8++ = tableType;  /* type */
1205        if (tableType == 0) {
1206            PutTableType0Card8(pScreenData->pRedTbl, &pCard8);
1207        }
1208        else {                  /* tableType == 1 */
1209            PutTableType1Card8(pScreenData->pRedTbl, &pCard8);
1210        }
1211        XChangeProperty(pDpy, root, CorrectAtom, XA_INTEGER, 8,
1212                        PropModeReplace, (unsigned char *) pCard8Array, total);
1213        free(pCard8Array);
1214        break;
1215    case 16:
1216        total = 4               /* visualID, type, length */
1217            + (nLevels * (tableType == 0 ? 2 : 1));
1218        pCard16 = pCard16Array = calloc(total, sizeof(unsigned short));
1219        if (pCard16 == NULL) {
1220            fprintf(stderr, "Unable allocate array of Card16\n");
1221            return (0);
1222        }
1223        *pCard16++ = 0;         /* VisualID = 0 */
1224        *pCard16++ = 0;         /* VisualID = 0 */
1225        *pCard16++ = tableType; /* type */
1226        if (tableType == 0) {
1227            PutTableType0Card16(pScreenData->pRedTbl, &pCard16);
1228        }
1229        else {                  /* tableType == 1 */
1230            PutTableType1Card16(pScreenData->pRedTbl, &pCard16);
1231        }
1232        XChangeProperty(pDpy, root, CorrectAtom, XA_INTEGER, 16,
1233                        PropModeReplace, (unsigned char *) pCard16Array, total);
1234        free(pCard16Array);
1235        break;
1236    case 32:
1237        total = 3               /* visualID, type, length */
1238            + (nLevels * (tableType == 0 ? 2 : 1));
1239        pCard32 = pCard32Array = calloc(total, sizeof(unsigned long));
1240        if ((pCard32 == NULL) {
1241            fprintf(stderr, "Unable allocate array of Card32\n");
1242            return (0);
1243        }
1244        *pCard32++ = 0;         /* VisualID = 0 */
1245        *pCard32++ = tableType; /* type */
1246        if (tableType == 0) {
1247            PutTableType0Card32(pScreenData->pRedTbl, &pCard32);
1248        }
1249        else {                  /* tableType == 1 */
1250            PutTableType1Card32(pScreenData->pRedTbl, &pCard32);
1251        }
1252        XChangeProperty(pDpy, root, CorrectAtom, XA_INTEGER, 32,
1253                        PropModeReplace, (unsigned char *) pCard32Array, total);
1254        free(pCard32Array);
1255        break;
1256    default:
1257        fprintf(stderr, "Invalid property format\n");
1258        return (0);
1259    }
1260    return (1);
1261}
1262#endif                          /* GRAY */
1263
1264static void
1265PrintVisualOptions(XDCCC_Correction * pCorrection)
1266{
1267    if (pCorrection->visual_info_mask & VisualIDMask) {
1268        fprintf(stderr, "\t%s:0x%lx\n",
1269                DefineToStr(VisualOptKeyTbl, KEY_VISUALID),
1270                (unsigned long) pCorrection->visual_info.visualid);
1271    }
1272    if (pCorrection->visual_info_mask & VisualDepthMask) {
1273        fprintf(stderr, "\t%s:%d\n",
1274                DefineToStr(VisualOptKeyTbl, KEY_DEPTH),
1275                pCorrection->visual_info.depth);
1276    }
1277    if (pCorrection->visual_info_mask & VisualClassMask) {
1278        fprintf(stderr, "\t%s:%s\n",
1279                DefineToStr(VisualOptKeyTbl, KEY_CLASS),
1280                DefineToStr(VisualClassTbl, pCorrection->visual_info.class));
1281    }
1282    if (pCorrection->visual_info_mask & VisualRedMaskMask) {
1283        fprintf(stderr, "\t%s:0x%lx\n",
1284                DefineToStr(VisualOptKeyTbl, KEY_RED_MASK),
1285                pCorrection->visual_info.red_mask);
1286    }
1287    if (pCorrection->visual_info_mask & VisualGreenMaskMask) {
1288        fprintf(stderr, "\t%s:0x%lx\n",
1289                DefineToStr(VisualOptKeyTbl, KEY_GREEN_MASK),
1290                pCorrection->visual_info.green_mask);
1291    }
1292    if (pCorrection->visual_info_mask & VisualBlueMaskMask) {
1293        fprintf(stderr, "\t%s:0x%lx\n",
1294                DefineToStr(VisualOptKeyTbl, KEY_BLUE_MASK),
1295                pCorrection->visual_info.blue_mask);
1296    }
1297    if (pCorrection->visual_info_mask & VisualColormapSizeMask) {
1298        fprintf(stderr, "\t%s:0x%x\n",
1299                DefineToStr(VisualOptKeyTbl, KEY_COLORMAP_SIZE),
1300                pCorrection->visual_info.colormap_size);
1301    }
1302    if (pCorrection->visual_info_mask & VisualBitsPerRGBMask) {
1303        fprintf(stderr, "\t%s:%d\n",
1304                DefineToStr(VisualOptKeyTbl, KEY_BITS_PER_RGB),
1305                pCorrection->visual_info.bits_per_rgb);
1306    }
1307}
1308
1309static int
1310ParseVisualOptions(Display *pDpy, XDCCC_Correction *pCorrection, char *pbuf)
1311{
1312    char *key;
1313    XVisualInfo *vinfo;
1314    int n_matches;
1315    const char *delims = DATA_DELIMS ":";
1316
1317    pCorrection->visual_info_mask = VisualNoMask;
1318    key = strtok(pbuf, delims);
1319    do {
1320        long tmp;
1321        char *value = strtok(NULL, delims);
1322
1323        if ((key == NULL) || (value == NULL)) {
1324            return (0);
1325        }
1326        switch (StrToDefine(VisualOptKeyTbl, key)) {
1327        case KEY_VISUALID:
1328            if (sscanf(value, "%li", &tmp) != 1) {
1329                fprintf(stderr,
1330                        "Line %d: invalid VisualID specified, %s\n",
1331                        linenum, value);
1332                return (0);
1333            }
1334            else
1335                pCorrection->visual_info.visualid = tmp;
1336            pCorrection->visual_info_mask |= VisualIDMask;
1337            break;
1338        case KEY_DEPTH:
1339            if (sscanf(value, "%i", &pCorrection->visual_info.depth) != 1) {
1340                fprintf(stderr,
1341                        "Line %d: invalid depth specified, %s\n",
1342                        linenum, value);
1343                return (0);
1344            }
1345            pCorrection->visual_info_mask |= VisualDepthMask;
1346            break;
1347        case KEY_CLASS:
1348            switch (pCorrection->visual_info.class =
1349                    StrToDefine(VisualClassTbl, value)) {
1350            case StaticColor:
1351                break;
1352            case PseudoColor:
1353                break;
1354            case TrueColor:
1355                break;
1356            case DirectColor:
1357                break;
1358            case StaticGray:
1359                /* invalid, fall through */
1360            case GrayScale:
1361                /* invalid, fall through */
1362            default:
1363                fprintf(stderr,
1364                        "Line %d: invalid Visual Class -- %s\n",
1365                        linenum, value);
1366                return (0);
1367            }
1368            pCorrection->visual_info_mask |= VisualClassMask;
1369            break;
1370        case KEY_RED_MASK:
1371            if (sscanf(value, "%li", &tmp) != 1) {
1372                fprintf(stderr,
1373                        "Line %d: invalid red_mask specified -- %s\n",
1374                        linenum, value);
1375                return (0);
1376            }
1377            else
1378                pCorrection->visual_info.red_mask = tmp;
1379            pCorrection->visual_info_mask |= VisualRedMaskMask;
1380            break;
1381        case KEY_GREEN_MASK:
1382            if (sscanf(value, "%li", &tmp) != 1) {
1383                fprintf(stderr,
1384                        "Line %d: invalid green_mask specified -- %s\n",
1385                        linenum, value);
1386                return (0);
1387            }
1388            else
1389                pCorrection->visual_info.green_mask = tmp;
1390            pCorrection->visual_info_mask |= VisualGreenMaskMask;
1391            break;
1392        case KEY_BLUE_MASK:
1393            if (sscanf(value, "%li", &tmp) != 1) {
1394                fprintf(stderr,
1395                        "Line %d: invalid blue_mask specified -- %s\n",
1396                        linenum, value);
1397                return (0);
1398            }
1399            else
1400                pCorrection->visual_info.blue_mask = tmp;
1401            pCorrection->visual_info_mask |= VisualBlueMaskMask;
1402            break;
1403        case KEY_COLORMAP_SIZE:
1404            if (sscanf(value, "%i", &pCorrection->visual_info.colormap_size) !=
1405                1) {
1406                fprintf(stderr,
1407                        "Line %d: invalid colormap_size specified -- %s\n",
1408                        linenum, value);
1409                return (0);
1410            }
1411            pCorrection->visual_info_mask |= VisualColormapSizeMask;
1412            break;
1413        case KEY_BITS_PER_RGB:
1414            if (sscanf(value, "%i", &pCorrection->visual_info.bits_per_rgb) !=
1415                1) {
1416                fprintf(stderr,
1417                        "Line %d: invalid bits_per_rgb specified -- %s\n",
1418                        linenum, value);
1419                return (0);
1420            }
1421            pCorrection->visual_info_mask |= VisualBitsPerRGBMask;
1422            break;
1423        default:
1424            fprintf(stderr, "Line %d: invalid keyword %s\n", linenum, key);
1425            return (0);
1426        }
1427        key = strtok(NULL, delims);
1428    } while (key != NULL);
1429
1430    vinfo = XGetVisualInfo(pDpy,
1431                           pCorrection->visual_info_mask,
1432                           &pCorrection->visual_info, &n_matches);
1433
1434    if (!n_matches) {
1435        fprintf(stderr, "Line %d: Cannot find visual matching ...\n", linenum);
1436        PrintVisualOptions(pCorrection);
1437        fprintf(stderr, "\n");
1438        return (0);
1439    }
1440    if (n_matches > 1) {
1441        fprintf(stderr, "Line %d: Found more than one visual matching ...\n",
1442                linenum);
1443        PrintVisualOptions(pCorrection);
1444        fprintf(stderr, "    Using VisualId 0x%lx\n",
1445                (unsigned long) vinfo->visualid);
1446    }
1447    memcpy(&pCorrection->visual_info, vinfo, sizeof(XVisualInfo));
1448    return (1);
1449}
1450
1451/************************************************************************
1452 *									*
1453 *			 PUBLIC ROUTINES				*
1454 *									*
1455 ************************************************************************/
1456
1457/*
1458 *	NAME
1459 *		LoadSCCData - Read and store the screen data
1460 *
1461 *	SYNOPSIS
1462 */
1463int
1464LoadSCCData(Display *pDpy, int screenNumber, const char *filename,
1465            int targetFormat)
1466
1467/*
1468 *	DESCRIPTION
1469 *		Using the X Device Color Characterization Convention (XDCCC)
1470 *		read the screen data and store it on the root window of the
1471 *		screen.
1472 *
1473 *	RETURNS
1474 *		Returns 0 if failed; otherwise 1.
1475 *
1476 */
1477{
1478    FILE *stream;
1479    char *pStr;
1480    char buf[BUFSIZ];
1481    char *keyword, *token1, *token2, *token3;
1482    int state = 0;
1483    int VisualFlag = -2;
1484    Window root;
1485    XDCCC_Matrix matrix;
1486    XDCCC_Correction *CorrectionTail = NULL;
1487    XDCCC_Correction *CorrectionHead = NULL;
1488    XDCCC_Correction *pCurrent;
1489
1490    if (screenNumber < 0) {
1491        fprintf(stderr, "Invalid Screen Number %d\n", screenNumber);
1492        return (0);
1493    }
1494    root = RootWindow(pDpy, screenNumber);
1495
1496    if (!root) {
1497        /* if no root window is available then return an error */
1498        fprintf(stderr, "Could not open root window supplied.\n ");
1499        return (0);
1500    }
1501    /*
1502     * Open the file, determine its size, then read it into memory.
1503     */
1504    if (filename == NULL) {
1505        stream = stdin;
1506        filename = "stdin";
1507    }
1508    else if ((stream = fopen(filename, "r")) == NULL) {
1509        fprintf(stderr, "Could not open file %s.\n", filename);
1510        return (0);
1511    }
1512
1513    /*
1514     * Advance to starting keyword
1515     * Anything before this keyword is just treated as comments.
1516     */
1517
1518    while ((pStr = nextline(buf, BUFSIZ, stream)) != NULL) {
1519        keyword = strtok(buf, DATA_DELIMS);
1520        if (keyword != NULL &&
1521            (strcmp(keyword, SC_BEGIN_KEYWORD) == 0)) {
1522            break;
1523        }                       /* else ignore the line */
1524    }
1525
1526    if (pStr == NULL) {
1527        fprintf(stderr, "File %s is missing %s\n", filename, SC_BEGIN_KEYWORD);
1528        closeS(stream, CorrectionHead);
1529        return (0);
1530    }
1531
1532    token1 = strtok(NULL, DATA_DELIMS);
1533    if (token1 && (strcmp(token1, TXT_FORMAT_VERSION) != 0) &&
1534        (strcmp(token1, "0.3") != 0)) {
1535        fprintf(stderr,
1536                "Screen data format version mismatch in file %s-- expected %s, found %s\n",
1537                filename, TXT_FORMAT_VERSION, token1);
1538        closeS(stream, CorrectionHead);
1539        return (0);
1540    }
1541
1542    while ((pStr = nextline(buf, BUFSIZ, stream)) != NULL) {
1543        keyword = strtok(buf, DATA_DELIMS);
1544        if (keyword != NULL) {
1545            switch (SCKeyOf(keyword)) {
1546            case COMMENT:
1547            case NAME:
1548            case PART_NUMBER:
1549            case MODEL:
1550            case SERIAL_NUMBER:
1551            case REVISION:
1552                /* Do nothing */
1553                break;
1554            case SCREEN_CLASS:
1555                token1 = strtok(NULL, DATA_DELIMS);
1556                token2 = strtok(NULL, DATA_DELIMS);
1557                if ((token1 == NULL)
1558                    || ((VisualFlag = SCScrnClassOf(token1)) == -1)) {
1559                    closeS(stream, CorrectionHead);
1560                    return (0);
1561                }
1562                /*include code to handle screen number input */
1563                if (token2 != NULL) {
1564                    screenNumber = atoi(token2);
1565
1566                    if (screenNumber < 0) {
1567                        fprintf(stderr, "Invalid Screen Number %d\n",
1568                                screenNumber);
1569                    }
1570                    else {
1571                        root = RootWindow(pDpy, screenNumber);
1572                        if (!root) {
1573                            /* if no root window is available then return an error */
1574                            fprintf(stderr,
1575                                    "Could not open root window supplied.\n ");
1576                            return (0);
1577                        }
1578                    }
1579                }
1580                break;
1581            case COLORIMETRIC_BEGIN:
1582                if (VisualFlag == -2) {
1583                    closeS(stream, CorrectionHead);
1584                    return (0);
1585                }
1586                if (!ProcessColorimetric(stream, &matrix, VisualFlag)) {
1587                    closeS(stream, CorrectionHead);
1588                    return (0);
1589                }
1590                state |= 0x02;
1591                break;
1592            case IPROFILE_BEGIN:
1593                if (VisualFlag == -2) {
1594                    closeS(stream, CorrectionHead);
1595                    return (0);
1596                }
1597                token1 = strtok(NULL, DATA_DELIMS);
1598                token2 = strtok(NULL, DATA_DELIMS);
1599                if ((token1 == NULL) || (token2 == NULL)) {
1600                    fprintf(stderr,
1601                            "Line %d: Intensity profile missing TableType and/or nTables.",
1602                            linenum);
1603                    closeS(stream, CorrectionHead);
1604                    return (0);
1605                }
1606
1607                pCurrent = calloc(1, sizeof(XDCCC_Correction));
1608                if (pCurrent  == NULL) {
1609                    fprintf(stderr,
1610                            "Line %d: Could not allocate memory for intensity profile.",
1611                            linenum);
1612                    closeS(stream, CorrectionHead);
1613                    return (0);
1614                }
1615
1616                if (sscanf(token1, "%d", &pCurrent->tableType) != 1 ||
1617                    (pCurrent->tableType < 0 || pCurrent->tableType > 1)) {
1618                    fprintf(stderr,
1619                            "Line %d: invalid table type specified -- %s\n",
1620                            linenum, buf);
1621                    closeS(stream, CorrectionHead);
1622                    free(pCurrent);
1623                    return (0);
1624                }
1625
1626                if ((VisualFlag == VIDEO_RGB) && (token2 == NULL)) {
1627                    fprintf(stderr,
1628                            "Line %d: invalid number of tables specified -- %s\n",
1629                            linenum, buf);
1630                    closeS(stream, CorrectionHead);
1631                    free(pCurrent);
1632                    return (0);
1633                }
1634
1635                if (VisualFlag == VIDEO_RGB) {
1636                    if (sscanf(token2, "%d", &pCurrent->nTables) != 1 ||
1637                        (pCurrent->nTables != 0 && pCurrent->nTables != 1
1638                         && pCurrent->nTables != 3)) {
1639                        fprintf(stderr,
1640                                "Line %d: invalid number of tables (must be 0, 1, or 3)\n",
1641                                linenum);
1642                        closeS(stream, CorrectionHead);
1643                        free(pCurrent);
1644                        return (0);
1645                    }
1646                }
1647                else {
1648                    pCurrent->nTables = 0;
1649                }
1650
1651                token3 = strtok(NULL, "\n");
1652                if (token3 != NULL) {
1653                    if (!ParseVisualOptions(pDpy, pCurrent, token3)) {
1654                        goto ByPassThisIProfile;
1655                    }
1656                }
1657
1658                switch (pCurrent->nTables) {
1659                case 3:
1660                    pCurrent->pRedTbl = calloc(1, sizeof(IntensityTbl));
1661                    if (pCurrent->pRedTbl == NULL) {
1662                        fprintf(stderr,
1663                                "Line %d: Could not allocate Red Intensity Table\n",
1664                                linenum);
1665                        closeS(stream, CorrectionHead);
1666                        free(pCurrent);
1667                        return (0);
1668                    }
1669                    pCurrent->pGreenTbl = calloc(1, sizeof(IntensityTbl));
1670                    if (pCurrent->pGreenTbl == NULL) {
1671                        fprintf(stderr,
1672                                "Line %d: Could not allocate Green Intensity Table\n",
1673                                linenum);
1674                        closeS(stream, CorrectionHead);
1675                        free(pCurrent->pRedTbl);
1676                        free(pCurrent);
1677                        return (0);
1678                    }
1679                    pCurrent->pBlueTbl = calloc(1, sizeof(IntensityTbl));
1680                    if (pCurrent->pBlueTbl == NULL) {
1681                        fprintf(stderr,
1682                                "Line %d: Could not allocate Blue Intensity Table",
1683                                linenum);
1684                        closeS(stream, CorrectionHead);
1685                        free(pCurrent->pRedTbl);
1686                        free(pCurrent->pGreenTbl);
1687                        free(pCurrent);
1688                        return (0);
1689                    }
1690                    if (!ProcessIProfile(stream, pCurrent)) {
1691                        goto ByPassThisIProfile;
1692                    }
1693                    break;
1694                case 1:
1695                    pCurrent->pRedTbl = calloc(1, sizeof(IntensityTbl));
1696                    if (pCurrent->pRedTbl == NULL) {
1697                        fprintf(stderr,
1698                                "Line %d: Could not allocate Red Intensity Table",
1699                                linenum);
1700                        closeS(stream, CorrectionHead);
1701                        free(pCurrent);
1702                        return (0);
1703                    }
1704                    pCurrent->pGreenTbl = pCurrent->pRedTbl;
1705                    pCurrent->pBlueTbl = pCurrent->pRedTbl;
1706                    if (!ProcessIProfile(stream, pCurrent)) {
1707                        goto ByPassThisIProfile;
1708                    }
1709                    break;
1710                default:
1711                    /* do nothing */
1712                    break;
1713                }
1714
1715                if (CorrectionHead == NULL) {
1716                    CorrectionHead = CorrectionTail = pCurrent;
1717                }
1718                else {
1719                    CorrectionTail->next = pCurrent;
1720                    CorrectionTail = pCurrent;
1721                }
1722                state |= 0x04;
1723                break;
1724 ByPassThisIProfile:
1725                /* read till INTENSITY_PROFILE_END */
1726                while ((pStr = nextline(buf, BUFSIZ, stream)) != NULL) {
1727                    keyword = strtok(buf, DATA_DELIMS);
1728                    if (keyword != NULL) {
1729                        switch (SCKeyOf(keyword)) {
1730                        case ITBL_BEGIN:
1731                        case ITBL_END:
1732                        case COMMENT:
1733                        case DATA:
1734                            break;
1735                        case IPROFILE_END:
1736                            goto IProfileProcessed;
1737                        default:
1738                            closeS(stream, CorrectionHead);
1739                            return (0);
1740                        }
1741                    }
1742                }
1743                free(pCurrent);
1744 IProfileProcessed:
1745                state |= 0x04;
1746                break;
1747            case SC_END:
1748                if (!(state & 0x02)) {
1749                    fprintf(stderr,
1750                            "File %s is missing Colorimetric data.\n",
1751                            filename);
1752                    closeS(stream, CorrectionHead);
1753                    return (0);
1754                }
1755                if (!(state & 0x04)) {
1756                    fprintf(stderr,
1757                            "File %s is missing Intensity Profile Data.\n",
1758                            filename);
1759                }
1760                if (VisualFlag == VIDEO_RGB) {
1761                    LoadMatrix(pDpy, root, &matrix);
1762                    if (!LoadCorrections(pDpy, root, CorrectionHead,
1763                                         targetFormat)) {
1764                        closeS(stream, CorrectionHead);
1765                        return (0);
1766                    }
1767#ifdef GRAY
1768                }
1769                else if (VisualFlag == VIDEO_GRAY) {
1770                    if (!LoadDataGray(pDpy, root,
1771                                      pCurrent->tableType, pScreenData,
1772                                      targetFormat)) {
1773                        closeS(stream, CorrectionHead);
1774                        return (0);
1775                    }
1776#endif                          /* GRAY */
1777                }
1778                else {
1779                    fprintf(stderr, "File %s Visual missing.", filename);
1780                }
1781                closeS(stream, CorrectionHead);
1782                return (1);
1783
1784            default:
1785                fprintf(stderr, "Line %d: extraneous keyword %s\n",
1786                        linenum, keyword);
1787                closeS(stream, CorrectionHead);
1788                return (0);
1789
1790            }
1791        }                       /* else it was just a blank line */
1792    }
1793    closeS(stream, CorrectionHead);
1794    return (1);
1795}
1796