/* $Xorg: xcmsdb.c,v 1.3 2000/08/17 19:54:13 cpqbld Exp $ */ /* * (c) Copyright 1990 Tektronix Inc. * All Rights Reserved * * Permission to use, copy, modify, and distribute this software and its * documentation for any purpose and without fee is hereby granted, * provided that the above copyright notice appear in all copies and that * both that copyright notice and this permission notice appear in * supporting documentation, and that the name of Tektronix not be used * in advertising or publicity pertaining to distribution of the software * without specific, written prior permission. * * Tektronix disclaims all warranties with regard to this software, including * all implied warranties of merchantability and fitness, in no event shall * Tektronix be liable for any special, indirect or consequential damages or * any damages whatsoever resulting from loss of use, data or profits, * whether in an action of contract, negligence or other tortious action, * arising out of or in connection with the use or performance of this * software. * * * NAME * xcmsdb.c * * DESCRIPTION * Program to load, query or remove the Screen Color * Characterization Data from the root window of the screen. * */ /* $XFree86: xc/programs/xcmsdb/xcmsdb.c,v 1.5 2001/01/17 23:45:19 dawes Exp $ */ /* * INCLUDES */ #ifdef HAVE_CONFIG_H # include "config.h" #endif #include #include #include #include #include #include #include "SCCDFile.h" static void QuerySCCDataRGB(Display *dpy, Window root); static void RemoveSCCData(Display *dpy, Window root, int colorFlag); static unsigned long _XcmsGetElement(int format, char **pValue, unsigned long *pCount); static int _XcmsGetProperty(Display *pDpy, Window w, Atom property, int *pFormat, unsigned long *pNItems, unsigned long *pNBytes, char **pValue); static char *ProgramName; static void Syntax (int exitcode) { fprintf (stderr, "usage: %s [-options ...] [filename]\n\n%s", ProgramName, "where options include:\n" " -display host:dpy[.scrn] display to use\n" " -format [ 32 | 16 | 8 ] property format\n" " -query query Screen Color Characterization Data\n" " -remove remove Screen Color Characterization Data\n" #ifdef GRAY " -color use color as default\n"); " -gray use gray-scale as default\n"); #endif /* GRAY */ " -version print program version\n" "\n"); exit (exitcode); } static void MissingArg (const char *option) { fprintf (stderr, "%s: %s requires an argument\n", ProgramName, option); Syntax (1); } static Bool optionmatch(const char *opt, const char *arg, int minlen) { int arglen; if (strcmp(opt, arg) == 0) { return(True); } if ((arglen = strlen(arg)) >= (int)strlen(opt) || arglen < minlen) { return(False); } if (strncmp (opt, arg, arglen) == 0) { return(True); } return(False); } int main(int argc, char *argv[]) { Display *dpy; int i; char *displayname = NULL; char *filename = NULL; int query = 0; int remove = 0; int load = 0; int color = -1; int targetFormat = 32; ProgramName = argv[0]; for (i = 1; i < argc; i++) { char *arg = argv[i]; if (arg[0] == '-') { if (arg[1] == '\0') { filename = NULL; continue; } else if (optionmatch ("-help", arg, 1)) { Syntax (0); /* doesn't return */ } else if (optionmatch ("-display", arg, 1)) { if (++i >= argc) MissingArg ("-display"); displayname = argv[i]; continue; } else if (optionmatch ("-format", arg, 1)) { if (++i >= argc) MissingArg ("-format"); targetFormat = atoi(argv[i]); if (targetFormat != 32 && targetFormat != 16 && targetFormat != 8) { fprintf (stderr, "%s: invalid value for -format: %d\n", ProgramName, targetFormat); Syntax (1); } continue; } else if (optionmatch ("-query", arg, 1)) { query = 1; continue; } else if (optionmatch ("-remove", arg, 1)) { remove = 1; continue; #ifdef GRAY } else if (optionmatch ("-color", arg, 1)) { color = 1; continue; } else if (optionmatch ("-gray", arg, 1)) { color = 0; continue; #endif /* GRAY */ } else if (optionmatch ("-version", arg, 1)) { puts (PACKAGE_STRING); exit (0); } fprintf (stderr, "%s: unrecognized option '%s'\n", ProgramName, arg); Syntax (1); } else { load = 1; filename = arg; } } /* Open display */ if (!(dpy = XOpenDisplay (displayname))) { fprintf (stderr, "%s: Can't open display '%s'\n", ProgramName, XDisplayName(displayname)); exit (1); } if (query || remove) { load = 0; } if (load) { LoadSCCData(dpy, DefaultScreen(dpy), filename, targetFormat); } if (query) { if (color != 0) QuerySCCDataRGB(dpy, RootWindow(dpy, DefaultScreen(dpy))); #ifdef GRAY if (color != 1) QuerySCCDataGray(dpy, RootWindow(dpy, DefaultScreen(dpy))); #endif /* GRAY */ } if (remove) { RemoveSCCData(dpy, RootWindow(dpy, DefaultScreen(dpy)), color); } XCloseDisplay(dpy); exit (0); /*NOTREACHED*/ } static Atom ParseAtom(Display *dpy, const char *name, int only_flag) { return(XInternAtom(dpy, name, only_flag)); } /* * NAME * PrintTableType0 * * SYNOPSIS */ static void PrintTableType0(int format, char **pChar, unsigned long *pCount) /* * DESCRIPTION * * RETURNS * XcmsFailure if failed. * XcmsSuccess if succeeded. * */ { unsigned int nElements; unsigned short hValue; XcmsFloat fValue; nElements = _XcmsGetElement(format, pChar, pCount) + 1; printf ("\t length:%d\n", nElements); switch (format) { case 8: while (nElements--) { /* 0xFFFF/0xFF = 0x101 */ hValue = _XcmsGetElement (format, pChar, pCount) * 0x101; fValue = _XcmsGetElement (format, pChar, pCount) / (XcmsFloat)255.0; printf ("\t\t0x%x\t%8.5f\n", hValue, fValue); } break; case 16: while (nElements--) { hValue = _XcmsGetElement (format, pChar, pCount); fValue = _XcmsGetElement (format, pChar, pCount) / (XcmsFloat)65535.0; printf ("\t\t0x%x\t%8.5f\n", hValue, fValue); } break; case 32: while (nElements--) { hValue = _XcmsGetElement (format, pChar, pCount); fValue = _XcmsGetElement (format, pChar, pCount) / (XcmsFloat)4294967295.0; printf ("\t\t0x%x\t%8.5f\n", hValue, fValue); } break; default: return; } } /* * NAME * PrintTableType1 * * SYNOPSIS */ static void PrintTableType1(int format, char **pChar, unsigned long *pCount) /* * DESCRIPTION * * RETURNS * XcmsFailure if failed. * XcmsSuccess if succeeded. * */ { int count; unsigned int max_index; unsigned short hValue; XcmsFloat fValue; max_index = _XcmsGetElement(format, pChar, pCount); printf ("\t length:%d\n", max_index + 1); switch (format) { case 8: for (count = 0; count < max_index+1; count++) { hValue = (count * 65535) / max_index; fValue = _XcmsGetElement (format, pChar, pCount) / (XcmsFloat)255.0; printf ("\t\t0x%x\t%8.5f\n", hValue, fValue); } break; case 16: for (count = 0; count < max_index+1; count++) { hValue = (count * 65535) / max_index; fValue = _XcmsGetElement (format, pChar, pCount) / (XcmsFloat)65535.0; printf ("\t\t0x%x\t%8.5f\n", hValue, fValue); } break; case 32: for (count = 0; count < max_index+1; count++) { hValue = (count * 65535) / max_index; fValue = _XcmsGetElement (format, pChar, pCount) / (XcmsFloat)4294967295.0; printf ("\t\t0x%x\t%8.5f\n", hValue, fValue); } break; default: return; } } /* * NAME * QuerySCCData - Query for the SCC data on the root window * * SYNOPSIS */ static void QuerySCCDataRGB(Display *dpy, Window root) /* * DESCRIPTION * * RETURNS * None */ { char *property_return, *pChar; int i, j; int count, format, cType, nTables; unsigned long nitems, nbytes_return; Atom MatricesAtom, CorrectAtom; VisualID visualID; XVisualInfo vinfo_template, *vinfo_ret; int nvis; static const char *visual_strings[] = { "StaticGray", "GrayScale", "StaticColor", "PseudoColor", "TrueColor", "DirectColor" }; /* * Get Matrices */ MatricesAtom = ParseAtom (dpy, XDCCC_MATRIX_ATOM_NAME, True); if (MatricesAtom != None) { if (_XcmsGetProperty (dpy, root, MatricesAtom, &format, &nitems, &nbytes_return, &property_return) == XcmsFailure) { format = 0; } else if (nitems != 18) { printf ("Property %s had invalid length of %ld\n", XDCCC_MATRIX_ATOM_NAME, nitems); if (property_return) { XFree (property_return); } return; } } if (MatricesAtom == None || !format) { printf ("Could not find property %s\n", XDCCC_MATRIX_ATOM_NAME); } else if (format != 32) { printf ("Data in property %s not in 32 bit format\n", XDCCC_MATRIX_ATOM_NAME); } else { pChar = property_return; printf ("Screen: %d\n", DefaultScreen(dpy)); printf ("Querying property %s\n", XDCCC_MATRIX_ATOM_NAME); printf ("\tXYZtoRGB matrix :\n"); for (i = 0; i < 3; i++) { printf ("\t"); for (j = 0; j < 3; j++) { printf ("\t%8.5f", (long)_XcmsGetElement(format, &pChar, &nitems) / (XcmsFloat) XDCCC_NUMBER); } printf ("\n"); } printf ("\tRGBtoXYZ matrix :\n"); for (i = 0; i < 3; i++) { printf ("\t"); for (j = 0; j < 3; j++) { printf ("\t%8.5f", (long) _XcmsGetElement(format, &pChar, &nitems) / (XcmsFloat) XDCCC_NUMBER); } printf ("\n"); } XFree (property_return); } /* * Get Intensity Tables */ CorrectAtom = XInternAtom (dpy, XDCCC_CORRECT_ATOM_NAME, True); if (CorrectAtom != None) { if (_XcmsGetProperty (dpy, root, CorrectAtom, &format, &nitems, &nbytes_return, &property_return) == XcmsFailure) { format = 0; } else if (nitems <= 0) { printf ("Property %s had invalid length of %ld\n", XDCCC_CORRECT_ATOM_NAME, nitems); if (property_return) { XFree (property_return); } return; } } if (CorrectAtom == None || !format) { printf ("Could not find property %s\n", XDCCC_CORRECT_ATOM_NAME); } else { printf ("\nQuerying property %s\n", XDCCC_CORRECT_ATOM_NAME); pChar = property_return; while (nitems) { switch (format) { case 8: /* * Must have at least: * VisualID0 * VisualID1 * VisualID2 * VisualID3 * type * count * length * intensity1 * intensity2 */ if (nitems < 9) { goto IntensityTblError; } count = 3; break; case 16: /* * Must have at least: * VisualID0 * VisualID3 * type * count * length * intensity1 * intensity2 */ if (nitems < 7) { goto IntensityTblError; } count = 1; break; case 32: /* * Must have at least: * VisualID0 * type * count * length * intensity1 * intensity2 */ if (nitems < 6) { goto IntensityTblError; } count = 0; break; default: goto IntensityTblError; } /* * Get VisualID */ visualID = _XcmsGetElement(format, &pChar, &nitems); /* add the depth, class, and bits info in output */ vinfo_template.visualid = visualID; vinfo_ret = XGetVisualInfo(dpy, VisualIDMask, &vinfo_template, &nvis); while (count--) { visualID = visualID << format; visualID |= _XcmsGetElement(format, &pChar, &nitems); } if (vinfo_ret != NULL) { printf ("\n\tVisualID: 0x%lx class: %s depth: %d bits_per_rgb: %d\n", visualID, visual_strings[vinfo_ret->class], vinfo_ret->depth, vinfo_ret->bits_per_rgb); } else printf ("\n\tVisualID: 0x%lx\n", visualID); XFree(vinfo_ret); cType = _XcmsGetElement(format, &pChar, &nitems); printf ("\ttype: %d\n", cType); nTables = _XcmsGetElement(format, &pChar, &nitems); printf ("\tcount: %d\n", nTables); switch (cType) { case 0: /* Red Table should always exist */ printf ("\tRed Conversion Table:\n"); PrintTableType0(format, &pChar, &nitems); if (nTables > 1) { printf ("\tGreen Conversion Table:\n"); PrintTableType0(format, &pChar, &nitems); printf ("\tBlue Conversion Table:\n"); PrintTableType0(format, &pChar, &nitems); } break; case 1: /* Red Table should always exist */ printf ("\tRed Conversion Table:\n"); PrintTableType1(format, &pChar, &nitems); if (nTables > 1) { printf ("\tGreen Conversion Table:\n"); PrintTableType1(format, &pChar, &nitems); printf ("\tBlue Conversion Table:\n"); PrintTableType1(format, &pChar, &nitems); } break; default: goto IntensityTblError; } } XFree (property_return); } return; IntensityTblError: XFree (property_return); printf("Fatal error in %s property\n", XDCCC_CORRECT_ATOM_NAME); } #ifdef GRAY /* * NAME * QuerySCCDataGray - Query for the SCC data on the root window * * SYNOPSIS */ int QuerySCCDataGray(Display *dpy, Window root) /* * DESCRIPTION * * RETURNS * None */ { char *property_return, *pChar; int j; int count, format, cType; unsigned long nitems, nbytes_return; Atom MatricesAtom, CorrectAtom; VisualID visualID; MatricesAtom = ParseAtom (dpy, XDCCC_SCREENWHITEPT_ATOM_NAME, True); if (MatricesAtom != None) { if (_XcmsGetProperty (dpy, root, MatricesAtom, &format, &nitems, &nbytes_return, &property_return) == XcmsFailure) { format = 0; } else if (nitems != 3) { printf ("Property %s had invalid length of %d\n", XDCCC_SCREENWHITEPT_ATOM_NAME, nitems); if (property_return) { XFree (property_return); } return; } } if (MatricesAtom == None || !format) { printf ("Could not find property %s\n", XDCCC_SCREENWHITEPT_ATOM_NAME); } else { pChar = property_return; printf ("\nQuerying property %s\n", XDCCC_SCREENWHITEPT_ATOM_NAME); printf ("\tWhite Point XYZ :\n"); printf ("\t"); for (j = 0; j < 3; j++) { printf ("\t%8.5lf", (long) _XcmsGetElement(format, &pChar, &nitems) / (XcmsFloat) XDCCC_NUMBER); } printf ("\n"); XFree (property_return); } CorrectAtom = XInternAtom (dpy, XDCCC_GRAY_CORRECT_ATOM_NAME, True); if (CorrectAtom != None) { if (_XcmsGetProperty (dpy, root, CorrectAtom, &format, &nitems, &nbytes_return, &property_return) == XcmsFailure) { format = 0; } else if (nitems <= 0) { printf ("Property %s had invalid length of %d\n", XDCCC_GRAY_CORRECT_ATOM_NAME, nitems); if (property_return) { XFree (property_return); } return; } } if (CorrectAtom == None || !format) { printf ("Could not find property %s\n", XDCCC_GRAY_CORRECT_ATOM_NAME); } else { printf ("\nQuerying property %s\n\n", XDCCC_GRAY_CORRECT_ATOM_NAME); pChar = property_return; while (nitems) { switch (format) { case 8: /* * Must have at least: * VisualID0 * VisualID1 * VisualID2 * VisualID3 * type * count * length * intensity1 * intensity2 */ if (nitems < 9) { goto IntensityTblError; } count = 3; break; case 16: /* * Must have at least: * VisualID0 * VisualID3 * type * count * length * intensity1 * intensity2 */ if (nitems < 7) { goto IntensityTblError; } count = 1; break; case 32: /* * Must have at least: * VisualID0 * type * count * length * intensity1 * intensity2 */ if (nitems < 6) { goto IntensityTblError; } count = 0; break; default: goto IntensityTblError; break; } /* * Get VisualID */ visualID = _XcmsGetElement(format, &pChar, &nitems); while (count--) { visualID = visualID << format; visualID |= _XcmsGetElement(format, &pChar, &nitems); } printf ("\n\tVisualID: 0x%lx\n", visualID); cType = _XcmsGetElement(format, &pChar, &nitems); printf ("\ttype: %d\n", cType); printf ("\tGray Conversion Table:\n"); switch (cType) { case 0: PrintTableType0(format, &pChar, &nitems); break; case 1: PrintTableType1(format, &pChar, &nitems); break; default: goto IntensityTblError; } } XFree (property_return); } return; IntensityTblError: XFree (property_return); printf("Fatal error in %s property\n", XDCCC_CORRECT_ATOM_NAME); } #endif /* GRAY */ /* * NAME * RemoveSCCData - Remove for the SCC data on the root window * * SYNOPSIS */ static void RemoveSCCData(Display *dpy, Window root, int colorFlag) /* * DESCRIPTION * * RETURNS * None */ { unsigned char *ret_prop; unsigned long ret_len, ret_after; int ret_format, status = -1; Atom MatricesAtom, CorrectAtom, ret_atom; if (colorFlag != 0) { MatricesAtom = ParseAtom (dpy, XDCCC_MATRIX_ATOM_NAME, True); if (MatricesAtom != None) { status = XGetWindowProperty (dpy, root, MatricesAtom, 0, 8192, False, XA_INTEGER, &ret_atom, &ret_format, &ret_len, &ret_after, &ret_prop); } if (MatricesAtom == None || status != Success || !ret_format) { printf ("Could not find property %s\n", XDCCC_MATRIX_ATOM_NAME); } else { printf ("Deleting property %s\n", XDCCC_MATRIX_ATOM_NAME); XDeleteProperty (dpy, root, MatricesAtom); XFree ((char *)ret_prop); } CorrectAtom = XInternAtom (dpy, XDCCC_CORRECT_ATOM_NAME, True); if (CorrectAtom != None) { status = XGetWindowProperty (dpy, root, CorrectAtom, 0, 8192, False, XA_INTEGER, &ret_atom, &ret_format, &ret_len, &ret_after, &ret_prop); } if (CorrectAtom == None || status != Success || !ret_format) { printf ("Could not find property %s\n", XDCCC_CORRECT_ATOM_NAME); } else { printf ("Deleting property %s\n", XDCCC_CORRECT_ATOM_NAME); XDeleteProperty (dpy, root, CorrectAtom); XFree ((char *)ret_prop); } } #ifdef GRAY if (colorFlag != 1) { MatricesAtom = ParseAtom (dpy, XDCCC_SCREENWHITEPT_ATOM_NAME, True); if (MatricesAtom != None) { status = XGetWindowProperty (dpy, root, MatricesAtom, 0, 8192, False, XA_INTEGER, &ret_atom, &ret_format, &ret_len, &ret_after, &ret_prop); } if (MatricesAtom == None || status != Success || !ret_format) { printf ("Could not find property %s\n", XDCCC_SCREENWHITEPT_ATOM_NAME); } else { printf ("Deleting property %s\n", XDCCC_SCREENWHITEPT_ATOM_NAME); XDeleteProperty (dpy, root, MatricesAtom); XFree ((char *)ret_prop); } CorrectAtom = XInternAtom (dpy, XDCCC_GRAY_CORRECT_ATOM_NAME, True); if (CorrectAtom != None) { status = XGetWindowProperty (dpy, root, CorrectAtom, 0, 8192, False, XA_INTEGER, &ret_atom, &ret_format, &ret_len, &ret_after, &ret_prop); } if (CorrectAtom == None || status != Success || !ret_format) { printf ("Could not find property %s\n", XDCCC_GRAY_CORRECT_ATOM_NAME); } else { printf ("Deleting property %s\n", XDCCC_GRAY_CORRECT_ATOM_NAME); XDeleteProperty (dpy, root, CorrectAtom); XFree ((char *)ret_prop); } } #endif /* GRAY */ } static unsigned long _XcmsGetElement(int format, char **pValue, unsigned long *pCount) /* * DESCRIPTION * Get the next element from the property and return it. * Also increment the pointer the amount needed. * * Returns * unsigned long */ { unsigned long value; switch (format) { case 32: value = *((unsigned long *)(*pValue)) & 0xFFFFFFFF; *pValue += sizeof(unsigned long); *pCount -= 1; break; case 16: value = *((unsigned short *)(*pValue)); *pValue += sizeof(unsigned short); *pCount -= 1; break; case 8: value = *((unsigned char *) (*pValue)); *pValue += 1; *pCount -= 1; break; default: value = 0; break; } return(value); } /* * NAME * _XcmsGetProperty -- Determine the existance of a property * * SYNOPSIS */ static int _XcmsGetProperty(Display *pDpy, Window w, Atom property, int *pFormat, unsigned long *pNItems, unsigned long *pNBytes, char **pValue) /* * DESCRIPTION * * Returns * 0 if property does not exist. * 1 if property exists. */ { char *prop_ret; int format_ret; long len = 6516; unsigned long nitems_ret, after_ret; Atom atom_ret; int xgwp_ret; while (True) { xgwp_ret = XGetWindowProperty (pDpy, w, property, 0, len, False, XA_INTEGER, &atom_ret, &format_ret, &nitems_ret, &after_ret, (unsigned char **)&prop_ret); if (xgwp_ret == Success && after_ret > 0) { len += nitems_ret * (format_ret >> 3); XFree (prop_ret); } else { break; } } if (xgwp_ret != Success || format_ret == 0 || nitems_ret == 0) { /* the property does not exist or is of an unexpected type or getting window property failed */ return(XcmsFailure); } *pFormat = format_ret; *pNItems = nitems_ret; *pNBytes = nitems_ret * (format_ret >> 3); *pValue = prop_ret; return(XcmsSuccess); }