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