xstdcmap.c revision 20915927
1/*
2 * $Xorg: xstdcmap.c,v 1.5 2001/02/09 02:06:01 xorgcvs Exp $
3 *
4 *
5Copyright 1989, 1998  The Open Group
6
7Permission to use, copy, modify, distribute, and sell this software and its
8documentation for any purpose is hereby granted without fee, provided that
9the above copyright notice appear in all copies and that both that
10copyright notice and this permission notice appear in supporting
11documentation.
12
13The above copyright notice and this permission notice shall be included in
14all copies or substantial portions of the Software.
15
16THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
19OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
20AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
23Except as contained in this notice, the name of The Open Group shall not be
24used in advertising or otherwise to promote the sale, use or other dealings
25in this Software without prior written authorization from The Open Group.
26 * *
27 * Author:  Donna Converse, MIT X Consortium
28 */
29/* $XFree86: xc/programs/xstdcmap/xstdcmap.c,v 1.8tsi Exp $ */
30
31#ifdef HAVE_CONFIG_H
32# include "config.h"
33#endif
34
35#include <stdio.h>
36#include <stdlib.h>
37#include <X11/Xos.h>
38#include <X11/Xlib.h>
39#include <X11/Xutil.h>
40#include <X11/Xresource.h>
41#include <X11/Xatom.h>
42#include <X11/Xmu/StdCmap.h>
43
44#define REPLACE		1
45#define DO_NOT_REPLACE  0
46#define RETAIN		1
47#define DO_NOT_RETAIN	0
48
49static char		*display_name = NULL;
50static char		*program_name = NULL;
51static Bool		all = 0;
52static Bool		help = 0;
53static Bool 		verbose = 0;
54static Bool 		version = 0;
55static Display		*dpy = NULL;
56
57typedef struct
58{
59    Bool	create;
60    Bool	delete;
61    Atom	property;
62    const char	*name;
63    const char	*nickname;
64} colormap_property;
65
66static colormap_property propertyTable[]=
67{
68{0,	0,	XA_RGB_DEFAULT_MAP,	"RGB_DEFAULT_MAP",	"default"},
69{0,	0,	XA_RGB_BEST_MAP,	"RGB_BEST_MAP",		"best"},
70{0,	0,	XA_RGB_GRAY_MAP,	"RGB_GRAY_MAP",		"gray"},
71{0,	0,	XA_RGB_RED_MAP,		"RGB_RED_MAP",		"red"},
72{0,	0,	XA_RGB_GREEN_MAP,	"RGB_GREEN_MAP",	"green"},
73{0,	0,	XA_RGB_BLUE_MAP,	"RGB_BLUE_MAP",		"blue"},
74};
75#define NPROPERTIES (sizeof propertyTable / sizeof propertyTable[0])
76
77#define DEFAULT	0
78#define BEST	1
79#define GRAY	2
80#define RED	3
81#define GREEN	4
82#define BLUE	5
83
84static const char	*usage_message =
85    "    -all               make all standard colormaps for the display\n"
86    "    -best              make the RGB_BEST_MAP\n"
87    "    -blue              make the RGB_BLUE_MAP\n"
88    "    -default           make the RGB_DEFAULT_MAP\n"
89    "    -delete name       remove a standard colormap\n"
90    "    -display dpy       X server to use\n"
91    "    -gray              make the RGB_GRAY_MAP\n"
92    "    -green             make the RGB_GREEN_MAP\n"
93    "    -red               make the RGB_RED_MAP\n"
94    "    -verbose           turn on logging\n"
95    "    -version           print version info\n";
96
97static XrmOptionDescRec optionTable[]=
98{
99{"-all",	".all",		XrmoptionNoArg,		(caddr_t) "on"},
100{"-best",	".best",	XrmoptionNoArg,		(caddr_t) "on"},
101{"-blue",	".blue",	XrmoptionNoArg,		(caddr_t) "on"},
102{"-default",	".default",	XrmoptionNoArg,		(caddr_t) "on"},
103{"-delete",	".delete",	XrmoptionSepArg,	(caddr_t) NULL},
104{"-display",	".display", 	XrmoptionSepArg,	(caddr_t) NULL},
105{"-gray",	".gray",	XrmoptionNoArg,		(caddr_t) "on"},
106{"-green",	".green",	XrmoptionNoArg,		(caddr_t) "on"},
107{"-help",	".help",        XrmoptionNoArg,		(caddr_t) "on"},
108{"-red",	".red",		XrmoptionNoArg,		(caddr_t) "on"},
109{"-verbose",	".verbose",	XrmoptionNoArg,		(caddr_t) "on"},
110{"-version",	".version",	XrmoptionNoArg,		(caddr_t) "on"},
111};
112#define NOPTIONS (sizeof optionTable / sizeof optionTable[0])
113
114static void usage(Status status);
115
116static void
117parse(int argc, char **argv)
118{
119    XrmDatabase		database = NULL;
120    char		*type;
121    XrmValue		value;
122    char		option[512];
123
124    if (argc == 1)
125	usage(0);
126
127    XrmInitialize();
128    XrmParseCommand(&database, optionTable, NOPTIONS, program_name, &argc,
129		    argv);
130    if (--argc)
131	usage(1);
132
133    snprintf(option, sizeof(option), "%s%s", program_name, ".all");
134    if (XrmGetResource(database, option, (char *) NULL, &type, &value))
135    	all++;
136
137    snprintf(option, sizeof(option), "%s%s", program_name, ".best");
138    if (XrmGetResource(database, option, (char *) NULL, &type, &value))
139    	propertyTable[BEST].create++;
140
141    snprintf(option, sizeof(option), "%s%s", program_name, ".blue");
142    if (XrmGetResource(database, option, (char *) NULL, &type, &value))
143	propertyTable[BLUE].create++;
144
145    snprintf(option, sizeof(option), "%s%s", program_name, ".default");
146    if (XrmGetResource(database, option, (char *) NULL, &type, &value))
147	propertyTable[DEFAULT].create++;
148
149    snprintf(option, sizeof(option), "%s%s", program_name, ".delete");
150    if (XrmGetResource(database, option, (char *) NULL, &type, &value)) {
151	register int i;
152	for (i=0; i < NPROPERTIES; i++) {
153	    if (strcmp((char *) value.addr, propertyTable[i].nickname) == 0) {
154		propertyTable[i].delete++;
155		break;
156	    }
157	    if (strcmp((char *) value.addr, "all") == 0)
158		propertyTable[i].delete++;
159	}
160    }
161
162    snprintf(option, sizeof(option), "%s%s", program_name, ".display");
163    if (XrmGetResource(database, option, (char *) NULL, &type, &value))
164	display_name = value.addr;
165
166    snprintf(option, sizeof(option), "%s%s", program_name, ".gray");
167    if (XrmGetResource(database, option, (char *) NULL, &type, &value))
168	propertyTable[GRAY].create++;
169
170    snprintf(option, sizeof(option), "%s%s", program_name, ".green");
171    if (XrmGetResource(database, option, (char *) NULL, &type, &value))
172	propertyTable[GREEN].create++;
173
174    snprintf(option, sizeof(option), "%s%s", program_name, ".help");
175    if (XrmGetResource(database, option, (char *) NULL, &type, &value))
176	help++;
177
178    snprintf(option, sizeof(option), "%s%s", program_name, ".red");
179    if (XrmGetResource(database, option, (char *) NULL, &type, &value))
180	propertyTable[RED].create++;
181
182    snprintf(option, sizeof(option), "%s%s", program_name, ".verbose");
183    if (XrmGetResource(database, option, (char *) NULL, &type, &value))
184	verbose++;
185
186    snprintf(option, sizeof(option), "%s%s", program_name, ".version");
187    if (XrmGetResource(database, option, (char *) NULL, &type, &value))
188	version++;
189}
190
191static void _X_NORETURN
192Exit(Status status)
193{
194    if (dpy)
195	XCloseDisplay(dpy);
196    exit(status);
197}
198
199static void  _X_NORETURN
200usage(Status status)
201{
202    (void) fprintf(stderr, "usage:  %s [-options]\n\n", program_name);
203    (void) fprintf(stderr, "where options include:\n%s\n", usage_message);
204    Exit(status);
205}
206
207/* Determine the visual of greatest depth in a given visual class.
208 * If no such visual exists, return NULL.
209 */
210static XVisualInfo *
211getDeepestVisual(int visual_class,   /* specifies the desired visual class */
212		 XVisualInfo *vinfo, /* specifies all visuals for a screen */
213		 int nvisuals)	/* specifies number of visuals in the list */
214{
215    register int	i;
216    unsigned int	maxdepth = 0;
217    XVisualInfo		*v = NULL;
218
219    for (i=0; i < nvisuals; i++, vinfo++)
220	if (vinfo->class == visual_class && vinfo->depth > maxdepth)
221	{
222	    maxdepth = vinfo->depth;
223	    v = vinfo;
224	}
225    return(v);
226}
227
228/* Determine the ``best'' visual of the screen for a standard colormap
229 * property.  Return NULL if no visual is appropriate.
230 */
231static XVisualInfo *
232getBestVisual(Atom property,	/* specifies the standard colormap */
233	      XVisualInfo *vinfo, /* specifies all visuals of the screen */
234	      int nvisuals)	/* specifies number of visuals of screen */
235{
236    XVisualInfo	*v1 = NULL, *v2 = NULL;
237
238    if (vinfo == NULL)		 /* unexpected: a screen with no visuals */
239	return v1;
240    v1 = getDeepestVisual(DirectColor, vinfo, nvisuals);
241    v2 = getDeepestVisual(PseudoColor, vinfo, nvisuals);
242    if (v2 && (!v1 || (v2->colormap_size >=
243		       ((v1->red_mask | v1->green_mask | v1->blue_mask) + 1))))
244	return v2;
245    else if (v1)
246	return v1;
247    if (property == XA_RGB_BEST_MAP)
248	if (((v1 = getDeepestVisual(TrueColor, vinfo, nvisuals)) != NULL) ||
249	    ((v1 = getDeepestVisual(StaticColor, vinfo, nvisuals)) != NULL))
250	    return v1;
251    if (property == XA_RGB_GRAY_MAP)
252	if (((v1 = getDeepestVisual(GrayScale, vinfo, nvisuals)) != NULL) ||
253	    ((v1 = getDeepestVisual(StaticGray, vinfo, nvisuals)) != NULL))
254	    return v1;
255    if (property == XA_RGB_DEFAULT_MAP)
256	for (v1 = vinfo; v1->visual != DefaultVisual(dpy, v1->screen); v1++)
257	    ;
258    return v1;
259
260}
261
262static const char *
263visualStringFromClass(int class)
264{
265    switch (class) {
266      case PseudoColor: return "PseudoColor";
267      case DirectColor: return "DirectColor";
268      case GrayScale: return "GrayScale";
269      case StaticColor: return "StaticColor";
270      case TrueColor: return "TrueColor";
271      case StaticGray: return "StaticGray";
272    }
273    return "unknown visual class";
274}
275
276static int
277doIndividualColormaps(void)
278{
279    int			i, screen, nvisuals;
280    Status		status = -1;
281    XVisualInfo		*vinfo = NULL, *v = NULL, template;
282
283    screen = DefaultScreen(dpy);
284    template.screen = screen;
285    vinfo = XGetVisualInfo(dpy, VisualScreenMask, &template, &nvisuals);
286
287    /* check for individual standard colormap requests */
288    for (i=0; i < NPROPERTIES; i++) {
289
290	if (propertyTable[i].delete) {
291	    XmuDeleteStandardColormap(dpy, screen, propertyTable[i].property);
292	    if (verbose)
293		fprintf(stderr, "%s: %s was deleted or did not exist.\n",
294			program_name, propertyTable[i].name);
295	}
296
297	if (! propertyTable[i].create)
298	    continue;
299
300	/* which visual is best for this property? */
301	v = getBestVisual(propertyTable[i].property, vinfo, nvisuals);
302	if (v == NULL) {
303	    if (verbose)
304		(void) fprintf(stderr,
305		       "%s: no visual appropriate for %s on screen %d.\n",
306			program_name, propertyTable[i].name, screen);
307	    continue;
308	}
309
310
311	if (verbose)
312	    (void) fprintf(stderr,
313			   "%s: making %s on a %s visual of depth %u.\n",
314			   program_name, propertyTable[i].name,
315			   visualStringFromClass(v->class), v->depth);
316
317	status = XmuLookupStandardColormap(dpy, screen, v->visualid,
318					   v->depth,
319					   propertyTable[i].property,
320					   DO_NOT_REPLACE, RETAIN);
321	if (verbose)
322	    (void) fprintf(stderr,
323			   "%s: %s standard colormap %s.\n", program_name,
324			   propertyTable[i].name, (status)
325			   ? "was created or already exists"
326			   : "cannot be defined");
327	if (!status)
328	    break;
329    }
330    XFree((char *) vinfo);
331    return status;
332}
333
334/* Bare bones standard colormap generation utility */
335int
336main(int argc, char *argv[])
337{
338    Status	status = 0;
339
340    if ((program_name = strrchr(*argv, '/')))
341	program_name++;
342    else
343	program_name = *argv;
344
345    parse(argc, argv);
346
347    if (help) {
348	usage(0);
349    }
350
351    if (version) {
352        printf("%s\n", PACKAGE_STRING);
353        exit(0);
354    }
355
356    if ((dpy = XOpenDisplay(display_name)) == NULL) {
357	(void) fprintf(stderr, "%s: cannot open display \"%s\".\n",
358		       program_name, XDisplayName(display_name));
359	exit(1);
360    }
361
362    if (all) {
363	if (verbose)
364	    (void) fprintf(stderr,
365			   "%s: making all appropriate standard colormaps...",
366			   program_name);
367	status = XmuAllStandardColormaps(dpy);
368	if (verbose)
369	    (void) fprintf(stderr,
370			   "\n%s!\n", (status) ? "success" : "failure");
371    }
372    else {
373	status = doIndividualColormaps();
374	if (!status && verbose)
375	    (void) fprintf(stderr,
376		    "Not all new colormap definitions will be retained.\n");
377    }
378    Exit((status == 0) ? 1 : 0);
379}
380