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