xstdcmap.c revision 04449c54
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 map        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	unsigned 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    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    unsigned int	i;
280    int			screen, nvisuals;
281    Status		status = -1;
282    XVisualInfo		*vinfo = NULL, *v = NULL, template;
283
284    screen = DefaultScreen(dpy);
285    template.screen = screen;
286    vinfo = XGetVisualInfo(dpy, VisualScreenMask, &template, &nvisuals);
287
288    /* check for individual standard colormap requests */
289    for (i=0; i < NPROPERTIES; i++) {
290
291	if (propertyTable[i].delete) {
292	    XmuDeleteStandardColormap(dpy, screen, propertyTable[i].property);
293	    if (verbose)
294		fprintf(stderr, "%s: %s was deleted or did not exist.\n",
295			program_name, propertyTable[i].name);
296	}
297
298	if (! propertyTable[i].create)
299	    continue;
300
301	/* which visual is best for this property? */
302	v = getBestVisual(propertyTable[i].property, vinfo, nvisuals);
303	if (v == NULL) {
304	    if (verbose)
305		(void) fprintf(stderr,
306		       "%s: no visual appropriate for %s on screen %d.\n",
307			program_name, propertyTable[i].name, screen);
308	    continue;
309	}
310
311
312	if (verbose)
313	    (void) fprintf(stderr,
314			   "%s: making %s on a %s visual of depth %u.\n",
315			   program_name, propertyTable[i].name,
316			   visualStringFromClass(v->class), v->depth);
317
318	status = XmuLookupStandardColormap(dpy, screen, v->visualid,
319					   v->depth,
320					   propertyTable[i].property,
321					   DO_NOT_REPLACE, RETAIN);
322	if (verbose)
323	    (void) fprintf(stderr,
324			   "%s: %s standard colormap %s.\n", program_name,
325			   propertyTable[i].name, (status)
326			   ? "was created or already exists"
327			   : "cannot be defined");
328	if (!status)
329	    break;
330    }
331    XFree((char *) vinfo);
332    return status;
333}
334
335/* Bare bones standard colormap generation utility */
336int
337main(int argc, char *argv[])
338{
339    Status	status = 0;
340
341    if ((program_name = strrchr(*argv, '/')))
342	program_name++;
343    else
344	program_name = *argv;
345
346    parse(argc, argv);
347
348    if (help) {
349	usage(0);
350    }
351
352    if (version) {
353        printf("%s\n", PACKAGE_STRING);
354        exit(0);
355    }
356
357    if ((dpy = XOpenDisplay(display_name)) == NULL) {
358	(void) fprintf(stderr, "%s: cannot open display \"%s\".\n",
359		       program_name, XDisplayName(display_name));
360	exit(1);
361    }
362
363    if (all) {
364	if (verbose)
365	    (void) fprintf(stderr,
366			   "%s: making all appropriate standard colormaps...",
367			   program_name);
368	status = XmuAllStandardColormaps(dpy);
369	if (verbose)
370	    (void) fprintf(stderr,
371			   "\n%s!\n", (status) ? "success" : "failure");
372    }
373    else {
374	status = doIndividualColormaps();
375	if (!status && verbose)
376	    (void) fprintf(stderr,
377		    "Not all new colormap definitions will be retained.\n");
378    }
379    Exit((status == 0) ? 1 : 0);
380}
381