xcmsdb.c revision 16d7e2f1
1/* $Xorg: xcmsdb.c,v 1.3 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 *		xcmsdb.c
26 *
27 *	DESCRIPTION
28 *		Program to load, query or remove the Screen Color
29 *		Characterization Data from the root window of the screen.
30 *
31 */
32/* $XFree86: xc/programs/xcmsdb/xcmsdb.c,v 1.5 2001/01/17 23:45:19 dawes Exp $ */
33
34/*
35 *      INCLUDES
36 */
37
38#include <stdio.h>
39#include <stdlib.h>
40#include <X11/Xlib.h>
41#include <X11/Xatom.h>
42#include <X11/Xos.h>
43#include <ctype.h>
44
45#include "SCCDFile.h"
46
47static void QuerySCCDataRGB(Display *dpy, Window root);
48static void RemoveSCCData(Display *dpy, Window root, int colorFlag);
49static unsigned long _XcmsGetElement(int format, char **pValue,
50				     unsigned long *pCount);
51static int _XcmsGetProperty(Display *pDpy, Window w, Atom property,
52			    int *pFormat, unsigned long *pNItems,
53			    unsigned long *pNBytes, char **pValue);
54
55
56static char *ProgramName;
57
58static void
59Syntax (void)
60{
61    fprintf (stderr,
62	     "usage:  %s [-options ...] [filename]\n\n",
63	     ProgramName);
64    fprintf (stderr,
65	     "where options include:\n");
66    fprintf (stderr,
67	     "    -display host:dpy[.scrn]     display to use\n");
68    fprintf (stderr,
69	     "    -format [ 32 | 16 | 8 ]      property format\n");
70    fprintf (stderr,
71	     "    -query                       query Screen Color Characterization Data\n");
72    fprintf (stderr,
73	     "    -remove                      remove Screen Color Characterization Data\n");
74#ifdef GRAY
75    fprintf (stderr,
76	     "    -color                       use color as default\n");
77    fprintf (stderr,
78	     "    -gray                        use gray-scale as default\n");
79#endif /* GRAY */
80    fprintf (stderr,
81	     "\n");
82    exit (1);
83}
84
85static Bool
86optionmatch(char *opt, char *arg, int minlen)
87{
88    int arglen;
89
90    if (strcmp(opt, arg) == 0) {
91	return(True);
92    }
93
94    if ((arglen = strlen(arg)) >= (int)strlen(opt) || arglen < minlen) {
95	return(False);
96    }
97
98    if (strncmp (opt, arg, arglen) == 0) {
99	return(True);
100    }
101
102    return(False);
103}
104
105int
106main(int argc, char *argv[])
107{
108    Display *dpy;
109    int i;
110    char *displayname = NULL;
111    char *filename = NULL;
112    int query = 0;
113    int remove = 0;
114    int load = 0;
115    int color = -1;
116    int targetFormat = 32;
117
118    ProgramName = argv[0];
119
120    for (i = 1; i < argc; i++) {
121	char *arg = argv[i];
122
123	if (arg[0] == '-') {
124	    if (arg[1] == '\0') {
125		filename = NULL;
126		continue;
127	    } else if (optionmatch ("-help", arg, 1)) {
128		Syntax ();
129		/* doesn't return */
130	    } else if (optionmatch ("-display", arg, 1)) {
131		if (++i >= argc) Syntax ();
132		displayname = argv[i];
133		continue;
134	    } else if (optionmatch ("-format", arg, 1)) {
135		if (++i >= argc) Syntax ();
136		targetFormat = atoi(argv[i]);
137		if (targetFormat != 32 && targetFormat != 16 &&
138			targetFormat != 8) Syntax();
139		continue;
140	    } else if (optionmatch ("-query", arg, 1)) {
141		query = 1;
142		continue;
143	    } else if (optionmatch ("-remove", arg, 1)) {
144		remove = 1;
145		continue;
146#ifdef GRAY
147	    } else if (optionmatch ("-color", arg, 1)) {
148		color = 1;
149		continue;
150	    } else if (optionmatch ("-gray", arg, 1)) {
151		color = 0;
152		continue;
153#endif /* GRAY */
154	    }
155	    Syntax ();
156	} else {
157	    load = 1;
158	    filename = arg;
159	}
160    }
161
162    /* Open display  */
163    if (!(dpy = XOpenDisplay (displayname))) {
164      fprintf (stderr, "%s:  Can't open display '%s'\n",
165	       ProgramName, XDisplayName(displayname));
166      exit (1);
167    }
168
169    if (query || remove) {
170	load = 0;
171    }
172
173    if (load) {
174	LoadSCCData(dpy, DefaultScreen(dpy), filename, targetFormat);
175    }
176
177    if (query) {
178	if (color != 0)
179	    QuerySCCDataRGB(dpy, RootWindow(dpy, DefaultScreen(dpy)));
180#ifdef GRAY
181	if (color != 1)
182	    QuerySCCDataGray(dpy, RootWindow(dpy, DefaultScreen(dpy)));
183#endif /* GRAY */
184    }
185
186    if (remove) {
187	RemoveSCCData(dpy, RootWindow(dpy, DefaultScreen(dpy)), color);
188    }
189
190    XCloseDisplay(dpy);
191    exit (0);
192    /*NOTREACHED*/
193}
194
195
196static Atom
197ParseAtom(Display *dpy, char *name, int only_flag)
198{
199    return(XInternAtom(dpy, name, only_flag));
200}
201
202
203/*
204 *	NAME
205 *		PrintTableType0
206 *
207 *	SYNOPSIS
208 */
209static void
210PrintTableType0(int format, char **pChar, unsigned long *pCount)
211/*
212 *	DESCRIPTION
213 *
214 *	RETURNS
215 *		XcmsFailure if failed.
216 *		XcmsSuccess if succeeded.
217 *
218 */
219{
220    unsigned int nElements;
221    unsigned short hValue;
222    XcmsFloat fValue;
223
224    nElements = _XcmsGetElement(format, pChar, pCount) + 1;
225    printf ("\t    length:%d\n", nElements);
226
227    switch (format) {
228      case 8:
229	while (nElements--) {
230	    /* 0xFFFF/0xFF = 0x101 */
231	    hValue = _XcmsGetElement (format, pChar, pCount) * 0x101;
232	    fValue = _XcmsGetElement (format, pChar, pCount)
233		    / (XcmsFloat)255.0;
234	    printf ("\t\t0x%x\t%8.5f\n", hValue, fValue);
235	}
236	break;
237      case 16:
238	while (nElements--) {
239	    hValue = _XcmsGetElement (format, pChar, pCount);
240	    fValue = _XcmsGetElement (format, pChar, pCount)
241		    / (XcmsFloat)65535.0;
242	    printf ("\t\t0x%x\t%8.5f\n", hValue, fValue);
243	}
244	break;
245      case 32:
246	while (nElements--) {
247	    hValue = _XcmsGetElement (format, pChar, pCount);
248	    fValue = _XcmsGetElement (format, pChar, pCount)
249		    / (XcmsFloat)4294967295.0;
250	    printf ("\t\t0x%x\t%8.5f\n", hValue, fValue);
251	}
252	break;
253      default:
254	return;
255    }
256}
257
258
259/*
260 *	NAME
261 *		PrintTableType1
262 *
263 *	SYNOPSIS
264 */
265static void
266PrintTableType1(int format, char **pChar, unsigned long *pCount)
267/*
268 *	DESCRIPTION
269 *
270 *	RETURNS
271 *		XcmsFailure if failed.
272 *		XcmsSuccess if succeeded.
273 *
274 */
275{
276    int count;
277    unsigned int max_index;
278    unsigned short hValue;
279    XcmsFloat fValue;
280
281    max_index = _XcmsGetElement(format, pChar, pCount);
282    printf ("\t    length:%d\n", max_index + 1);
283
284    switch (format) {
285      case 8:
286	for (count = 0; count < max_index+1; count++) {
287	    hValue = (count * 65535) / max_index;
288	    fValue = _XcmsGetElement (format, pChar, pCount)
289		    / (XcmsFloat)255.0;
290	    printf ("\t\t0x%x\t%8.5f\n", hValue, fValue);
291	}
292	break;
293      case 16:
294	for (count = 0; count < max_index+1; count++) {
295	    hValue = (count * 65535) / max_index;
296	    fValue = _XcmsGetElement (format, pChar, pCount)
297		    / (XcmsFloat)65535.0;
298	    printf ("\t\t0x%x\t%8.5f\n", hValue, fValue);
299	}
300	break;
301      case 32:
302	for (count = 0; count < max_index+1; count++) {
303	    hValue = (count * 65535) / max_index;
304	    fValue = _XcmsGetElement (format, pChar, pCount)
305		    / (XcmsFloat)4294967295.0;
306	    printf ("\t\t0x%x\t%8.5f\n", hValue, fValue);
307	}
308	break;
309      default:
310	return;
311    }
312}
313
314
315/*
316 *      NAME
317 *		QuerySCCData - Query for the SCC data on the root window
318 *
319 *      SYNOPSIS
320 */
321static void
322QuerySCCDataRGB(Display *dpy, Window root)
323/*
324 *      DESCRIPTION
325 *
326 *      RETURNS
327 *		None
328 */
329{
330    char *property_return, *pChar;
331    int  i, j;
332    int  count, format, cType, nTables;
333    unsigned long nitems, nbytes_return;
334    Atom MatricesAtom, CorrectAtom;
335    VisualID visualID;
336    XVisualInfo vinfo_template, *vinfo_ret;
337    int nvis;
338    static char *visual_strings[] = {
339	"StaticGray",
340	"GrayScale",
341	"StaticColor",
342	"PseudoColor",
343	"TrueColor",
344	"DirectColor"
345	};
346
347    /*
348     * Get Matrices
349     */
350    MatricesAtom = ParseAtom (dpy, XDCCC_MATRIX_ATOM_NAME, True);
351    if (MatricesAtom != None) {
352	if (_XcmsGetProperty (dpy, root, MatricesAtom, &format, &nitems,
353			  &nbytes_return, &property_return) == XcmsFailure) {
354	    format = 0;
355	} else if (nitems != 18) {
356	    printf ("Property %s had invalid length of %ld\n",
357		    XDCCC_MATRIX_ATOM_NAME, nitems);
358	    if (property_return) {
359		XFree (property_return);
360	    }
361	    return;
362	}
363    }
364    if (MatricesAtom == None || !format) {
365	printf ("Could not find property %s\n", XDCCC_MATRIX_ATOM_NAME);
366    } else if (format != 32) {
367	printf ("Data in property %s not in 32 bit format\n",
368		XDCCC_MATRIX_ATOM_NAME);
369    } else {
370	pChar = property_return;
371	printf ("Screen: %d\n", DefaultScreen(dpy));
372	printf ("Querying property %s\n", XDCCC_MATRIX_ATOM_NAME);
373	printf ("\tXYZtoRGB matrix :\n");
374	for (i = 0; i < 3; i++) {
375	    printf ("\t");
376	    for (j = 0; j < 3; j++) {
377		printf ("\t%8.5f",
378			(long)_XcmsGetElement(format, &pChar, &nitems)
379			/ (XcmsFloat) XDCCC_NUMBER);
380	    }
381	    printf ("\n");
382	}
383	printf ("\tRGBtoXYZ matrix :\n");
384	for (i = 0; i < 3; i++) {
385	    printf ("\t");
386	    for (j = 0; j < 3; j++) {
387		printf ("\t%8.5f",
388			(long) _XcmsGetElement(format, &pChar, &nitems)
389			/ (XcmsFloat) XDCCC_NUMBER);
390	    }
391	    printf ("\n");
392	}
393	XFree (property_return);
394    }
395
396
397    /*
398     * Get Intensity Tables
399     */
400    CorrectAtom = XInternAtom (dpy, XDCCC_CORRECT_ATOM_NAME, True);
401    if (CorrectAtom != None) {
402	if (_XcmsGetProperty (dpy, root, CorrectAtom, &format, &nitems,
403			  &nbytes_return, &property_return) == XcmsFailure) {
404	    format = 0;
405	} else if (nitems <= 0) {
406            printf ("Property %s had invalid length of %ld\n",
407		    XDCCC_CORRECT_ATOM_NAME, nitems);
408	    if (property_return) {
409		XFree (property_return);
410	    }
411	    return;
412	}
413    }
414    if (CorrectAtom == None || !format) {
415	printf ("Could not find property %s\n", XDCCC_CORRECT_ATOM_NAME);
416    } else {
417	printf ("\nQuerying property %s\n", XDCCC_CORRECT_ATOM_NAME);
418	pChar = property_return;
419
420	while (nitems) {
421	    switch (format) {
422	      case 8:
423		/*
424		 * Must have at least:
425		 *		VisualID0
426		 *		VisualID1
427		 *		VisualID2
428		 *		VisualID3
429		 *		type
430		 *		count
431		 *		length
432		 *		intensity1
433		 *		intensity2
434		 */
435		if (nitems < 9) {
436		    goto IntensityTblError;
437		}
438		count = 3;
439		break;
440	      case 16:
441		/*
442		 * Must have at least:
443		 *		VisualID0
444		 *		VisualID3
445		 *		type
446		 *		count
447		 *		length
448		 *		intensity1
449		 *		intensity2
450		 */
451		if (nitems < 7) {
452		    goto IntensityTblError;
453		}
454		count = 1;
455		break;
456	      case 32:
457		/*
458		 * Must have at least:
459		 *		VisualID0
460		 *		type
461		 *		count
462		 *		length
463		 *		intensity1
464		 *		intensity2
465		 */
466		if (nitems < 6) {
467		    goto IntensityTblError;
468		}
469		count = 0;
470		break;
471	      default:
472		goto IntensityTblError;
473	    }
474
475	    /*
476	     * Get VisualID
477	     */
478	    visualID = _XcmsGetElement(format, &pChar, &nitems);
479	    /* add the depth, class, and bits info in output */
480	    vinfo_template.visualid = visualID;
481	    vinfo_ret = XGetVisualInfo(dpy, VisualIDMask, &vinfo_template,
482				       &nvis);
483	    while (count--) {
484		visualID = visualID << format;
485		visualID |= _XcmsGetElement(format, &pChar, &nitems);
486	    }
487
488	    if (vinfo_ret != NULL) {
489		printf
490		 ("\n\tVisualID: 0x%lx class: %s depth: %d bits_per_rgb: %d\n",
491		  visualID, visual_strings[vinfo_ret->class],
492		  vinfo_ret->depth, vinfo_ret->bits_per_rgb);
493	    }
494	    else
495	    printf ("\n\tVisualID: 0x%lx\n", visualID);
496	    XFree(vinfo_ret);
497	    cType = _XcmsGetElement(format, &pChar, &nitems);
498	    printf ("\ttype: %d\n", cType);
499	    nTables = _XcmsGetElement(format, &pChar, &nitems);
500	    printf ("\tcount: %d\n", nTables);
501
502	    switch (cType) {
503	      case 0:
504		/* Red Table should always exist */
505		printf ("\tRed Conversion Table:\n");
506		PrintTableType0(format, &pChar, &nitems);
507		if (nTables > 1) {
508		    printf ("\tGreen Conversion Table:\n");
509		    PrintTableType0(format, &pChar, &nitems);
510		    printf ("\tBlue Conversion Table:\n");
511		    PrintTableType0(format, &pChar, &nitems);
512		}
513		break;
514	      case 1:
515		/* Red Table should always exist */
516		printf ("\tRed Conversion Table:\n");
517		PrintTableType1(format, &pChar, &nitems);
518		if (nTables > 1) {
519		    printf ("\tGreen Conversion Table:\n");
520		    PrintTableType1(format, &pChar, &nitems);
521		    printf ("\tBlue Conversion Table:\n");
522		    PrintTableType1(format, &pChar, &nitems);
523		}
524	        break;
525	      default:
526		goto IntensityTblError;
527	    }
528	}
529	XFree (property_return);
530    }
531    return;
532
533IntensityTblError:
534    XFree (property_return);
535    printf("Fatal error in %s property\n", XDCCC_CORRECT_ATOM_NAME);
536}
537
538
539#ifdef GRAY
540
541/*
542 *      NAME
543 *		QuerySCCDataGray - Query for the SCC data on the root window
544 *
545 *      SYNOPSIS
546 */
547int
548QuerySCCDataGray(Display *dpy, Window root)
549/*
550 *      DESCRIPTION
551 *
552 *      RETURNS
553 *		None
554 */
555{
556    char *property_return, *pChar;
557    int  j;
558    int  count, format, cType;
559    unsigned long  nitems, nbytes_return;
560    Atom MatricesAtom, CorrectAtom;
561    VisualID visualID;
562
563    MatricesAtom = ParseAtom (dpy, XDCCC_SCREENWHITEPT_ATOM_NAME, True);
564    if (MatricesAtom != None) {
565	if (_XcmsGetProperty (dpy, root, MatricesAtom, &format, &nitems,
566			  &nbytes_return, &property_return)  == XcmsFailure) {
567	    format = 0;
568	} else if (nitems != 3) {
569	    printf ("Property %s had invalid length of %d\n",
570		    XDCCC_SCREENWHITEPT_ATOM_NAME, nitems);
571	    if (property_return) {
572		XFree (property_return);
573	    }
574	    return;
575	}
576    }
577    if (MatricesAtom == None || !format) {
578	printf ("Could not find property %s\n", XDCCC_SCREENWHITEPT_ATOM_NAME);
579    } else {
580	pChar = property_return;
581	printf ("\nQuerying property %s\n", XDCCC_SCREENWHITEPT_ATOM_NAME);
582	printf ("\tWhite Point XYZ :\n");
583	printf ("\t");
584	for (j = 0; j < 3; j++) {
585	    printf ("\t%8.5lf",
586			(long) _XcmsGetElement(format, &pChar, &nitems) /
587			(XcmsFloat) XDCCC_NUMBER);
588	}
589	printf ("\n");
590	XFree (property_return);
591    }
592
593    CorrectAtom = XInternAtom (dpy, XDCCC_GRAY_CORRECT_ATOM_NAME, True);
594    if (CorrectAtom != None) {
595	if (_XcmsGetProperty (dpy, root, CorrectAtom, &format, &nitems,
596			  &nbytes_return, &property_return) == XcmsFailure) {
597	    format = 0;
598	} else if (nitems <= 0) {
599            printf ("Property %s had invalid length of %d\n",
600		    XDCCC_GRAY_CORRECT_ATOM_NAME, nitems);
601	    if (property_return) {
602		XFree (property_return);
603	    }
604	    return;
605	}
606    }
607    if (CorrectAtom == None || !format) {
608	printf ("Could not find property %s\n", XDCCC_GRAY_CORRECT_ATOM_NAME);
609    } else {
610	printf ("\nQuerying property %s\n\n", XDCCC_GRAY_CORRECT_ATOM_NAME);
611	pChar = property_return;
612
613	while (nitems) {
614	    switch (format) {
615	      case 8:
616		/*
617		 * Must have at least:
618		 *		VisualID0
619		 *		VisualID1
620		 *		VisualID2
621		 *		VisualID3
622		 *		type
623		 *		count
624		 *		length
625		 *		intensity1
626		 *		intensity2
627		 */
628		if (nitems < 9) {
629		    goto IntensityTblError;
630		}
631		count = 3;
632		break;
633	      case 16:
634		/*
635		 * Must have at least:
636		 *		VisualID0
637		 *		VisualID3
638		 *		type
639		 *		count
640		 *		length
641		 *		intensity1
642		 *		intensity2
643		 */
644		if (nitems < 7) {
645		    goto IntensityTblError;
646		}
647		count = 1;
648		break;
649	      case 32:
650		/*
651		 * Must have at least:
652		 *		VisualID0
653		 *		type
654		 *		count
655		 *		length
656		 *		intensity1
657		 *		intensity2
658		 */
659		if (nitems < 6) {
660		    goto IntensityTblError;
661		}
662		count = 0;
663		break;
664	      default:
665		goto IntensityTblError;
666		break;
667	    }
668
669	    /*
670	     * Get VisualID
671	     */
672	    visualID = _XcmsGetElement(format, &pChar, &nitems);
673	    while (count--) {
674		visualID = visualID << format;
675		visualID |= _XcmsGetElement(format, &pChar, &nitems);
676	    }
677
678	    printf ("\n\tVisualID: 0x%lx\n", visualID);
679	    cType = _XcmsGetElement(format, &pChar, &nitems);
680	    printf ("\ttype: %d\n", cType);
681	    printf ("\tGray Conversion Table:\n");
682	    switch (cType) {
683	      case 0:
684		PrintTableType0(format, &pChar, &nitems);
685		break;
686	      case 1:
687		PrintTableType1(format, &pChar, &nitems);
688		break;
689	      default:
690		goto IntensityTblError;
691	    }
692	}
693	XFree (property_return);
694    }
695    return;
696IntensityTblError:
697    XFree (property_return);
698    printf("Fatal error in %s property\n", XDCCC_CORRECT_ATOM_NAME);
699}
700#endif /* GRAY */
701
702
703/*
704 *      NAME
705 *		RemoveSCCData - Remove for the SCC data on the root window
706 *
707 *      SYNOPSIS
708 */
709static void
710RemoveSCCData(Display *dpy, Window root, int colorFlag)
711/*
712 *      DESCRIPTION
713 *
714 *      RETURNS
715 *		None
716 */
717{
718    unsigned char *ret_prop;
719    unsigned long ret_len, ret_after;
720    int  ret_format;
721    Atom MatricesAtom, CorrectAtom, ret_atom;
722
723    if (colorFlag != 0) {
724	MatricesAtom = ParseAtom (dpy, XDCCC_MATRIX_ATOM_NAME, True);
725	if (MatricesAtom != None) {
726	    XGetWindowProperty (dpy, root, MatricesAtom, 0, 8192, False,
727			XA_INTEGER, &ret_atom, &ret_format, &ret_len,
728			&ret_after, &ret_prop);
729	}
730	if (MatricesAtom == None || !ret_format) {
731	    printf ("Could not find property %s\n", XDCCC_MATRIX_ATOM_NAME);
732	} else {
733	    printf ("Deleting property %s\n", XDCCC_MATRIX_ATOM_NAME);
734	    XDeleteProperty (dpy, root, MatricesAtom);
735	    XFree ((char *)ret_prop);
736	}
737
738	CorrectAtom = XInternAtom (dpy, XDCCC_CORRECT_ATOM_NAME, True);
739	if (CorrectAtom != None) {
740	    XGetWindowProperty (dpy, root, CorrectAtom, 0, 8192, False,
741			XA_INTEGER, &ret_atom, &ret_format, &ret_len,
742			&ret_after, &ret_prop);
743	}
744	if (CorrectAtom == None || !ret_format) {
745	    printf ("Could not find property %s\n", XDCCC_CORRECT_ATOM_NAME);
746	} else {
747	    printf ("Deleting property %s\n", XDCCC_CORRECT_ATOM_NAME);
748	    XDeleteProperty (dpy, root, CorrectAtom);
749	    XFree ((char *)ret_prop);
750	}
751    }
752#ifdef GRAY
753    if (colorFlag != 1) {
754	MatricesAtom = ParseAtom (dpy, XDCCC_SCREENWHITEPT_ATOM_NAME, True);
755	if (MatricesAtom != None) {
756	    XGetWindowProperty (dpy, root, MatricesAtom, 0, 8192, False,
757			XA_INTEGER, &ret_atom, &ret_format, &ret_len,
758			&ret_after, &ret_prop);
759	}
760	if (MatricesAtom == None || !ret_format) {
761	    printf ("Could not find property %s\n", XDCCC_SCREENWHITEPT_ATOM_NAME);
762	} else {
763	    printf ("Deleting property %s\n", XDCCC_SCREENWHITEPT_ATOM_NAME);
764	    XDeleteProperty (dpy, root, MatricesAtom);
765	    XFree ((char *)ret_prop);
766	}
767
768	CorrectAtom = XInternAtom (dpy, XDCCC_GRAY_CORRECT_ATOM_NAME, True);
769	if (CorrectAtom != None) {
770	    XGetWindowProperty (dpy, root, CorrectAtom, 0, 8192, False,
771			XA_INTEGER, &ret_atom, &ret_format, &ret_len,
772			&ret_after, &ret_prop);
773	}
774	if (CorrectAtom == None || !ret_format) {
775	    printf ("Could not find property %s\n", XDCCC_GRAY_CORRECT_ATOM_NAME);
776	} else {
777	    printf ("Deleting property %s\n", XDCCC_GRAY_CORRECT_ATOM_NAME);
778	    XDeleteProperty (dpy, root, CorrectAtom);
779	    XFree ((char *)ret_prop);
780	}
781    }
782#endif /* GRAY */
783}
784
785static unsigned long
786_XcmsGetElement(int format, char **pValue, unsigned long *pCount)
787/*
788 *	DESCRIPTION
789 *	    Get the next element from the property and return it.
790 *	    Also increment the pointer the amount needed.
791 *
792 *	Returns
793 *	    unsigned long
794 */
795{
796    unsigned long value;
797
798    switch (format) {
799      case 32:
800	value = *((unsigned long *)(*pValue)) & 0xFFFFFFFF;
801	*pValue += sizeof(unsigned long);
802	*pCount -= 1;
803	break;
804      case 16:
805	value = *((unsigned short *)(*pValue));
806	*pValue += sizeof(unsigned short);
807	*pCount -= 1;
808	break;
809      case 8:
810	value = *((unsigned char *) (*pValue));
811	*pValue += 1;
812	*pCount -= 1;
813	break;
814      default:
815	value = 0;
816	break;
817    }
818    return(value);
819}
820
821
822/*
823 *	NAME
824 *		_XcmsGetProperty -- Determine the existance of a property
825 *
826 *	SYNOPSIS
827 */
828static int
829_XcmsGetProperty(Display *pDpy, Window w, Atom property, int *pFormat,
830		 unsigned long *pNItems, unsigned long *pNBytes,
831		 char **pValue)
832/*
833 *	DESCRIPTION
834 *
835 *	Returns
836 *	    0 if property does not exist.
837 *	    1 if property exists.
838 */
839{
840    char *prop_ret;
841    int format_ret;
842    long len = 6516;
843    unsigned long nitems_ret, after_ret;
844    Atom atom_ret;
845
846    while (XGetWindowProperty (pDpy, w, property, 0, len, False,
847			       XA_INTEGER, &atom_ret, &format_ret,
848			       &nitems_ret, &after_ret,
849			       (unsigned char **)&prop_ret)) {
850	if (after_ret > 0) {
851	    len += nitems_ret * (format_ret >> 3);
852	    XFree (prop_ret);
853	} else {
854	    break;
855	}
856    }
857    if (format_ret == 0 || nitems_ret == 0) {
858	/* the property does not exist or is of an unexpected type */
859	return(XcmsFailure);
860    }
861
862    *pFormat = format_ret;
863    *pNItems = nitems_ret;
864    *pNBytes = nitems_ret * (format_ret >> 3);
865    *pValue = prop_ret;
866    return(XcmsSuccess);
867}
868