xenocara/app/xcmsdb/xcmsdb.c

903 lines
27 KiB
C

/* $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 <stdio.h>
#include <stdlib.h>
#include <X11/Xlib.h>
#include <X11/Xatom.h>
#include <X11/Xos.h>
#include <ctype.h>
#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.
*
*/
{
unsigned 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(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(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(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(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 existence 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);
}