xstdcmap.c revision 8440cca4
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#include <stdio.h>
32#include <stdlib.h>
33#include <X11/Xos.h>
34#include <X11/Xlib.h>
35#include <X11/Xutil.h>
36#include <X11/Xresource.h>
37#include <X11/Xatom.h>
38#include <X11/Xmu/StdCmap.h>
39
40#define REPLACE		1
41#define DO_NOT_REPLACE  0
42#define RETAIN		1
43#define DO_NOT_RETAIN	0
44
45static char		*display_name = NULL;
46static char		*program_name = NULL;
47static Bool		all = 0;
48static Bool		help = 0;
49static Bool 		verbose = 0;
50static Display		*dpy = NULL;
51
52typedef struct
53{
54    Bool	create;
55    Bool	delete;
56    Atom	property;
57    char	*name;
58    char	*nickname;
59} colormap_property;
60
61static colormap_property propertyTable[]=
62{
63{0,	0,	XA_RGB_DEFAULT_MAP,	"RGB_DEFAULT_MAP",	"default"},
64{0,	0,	XA_RGB_BEST_MAP,	"RGB_BEST_MAP",		"best"},
65{0,	0,	XA_RGB_GRAY_MAP,	"RGB_GRAY_MAP",		"gray"},
66{0,	0,	XA_RGB_RED_MAP,		"RGB_RED_MAP",		"red"},
67{0,	0,	XA_RGB_GREEN_MAP,	"RGB_GREEN_MAP",	"green"},
68{0,	0,	XA_RGB_BLUE_MAP,	"RGB_BLUE_MAP",		"blue"},
69};
70#define NPROPERTIES (sizeof propertyTable / sizeof propertyTable[0])
71
72#define DEFAULT	0
73#define BEST	1
74#define GRAY	2
75#define RED	3
76#define GREEN	4
77#define BLUE	5
78
79static char	*usage_message[]=
80{
81"    -all               make all standard colormaps for the display",
82"    -best              make the RGB_BEST_MAP",
83"    -blue              make the RGB_BLUE_MAP",
84"    -default           make the RGB_DEFAULT_MAP",
85"    -delete name       remove a standard colormap",
86"    -display dpy       X server to use",
87"    -gray              make the RGB_GRAY_MAP",
88"    -green             make the RGB_GREEN_MAP",
89"    -red               make the RGB_RED_MAP",
90"    -verbose           turn on logging",
91"",
92NULL };
93
94static XrmOptionDescRec optionTable[]=
95{
96{"-all",	".all",		XrmoptionNoArg,		(caddr_t) "on"},
97{"-best",	".best",	XrmoptionNoArg,		(caddr_t) "on"},
98{"-blue",	".blue",	XrmoptionNoArg,		(caddr_t) "on"},
99{"-default",	".default",	XrmoptionNoArg,		(caddr_t) "on"},
100{"-delete",	".delete",	XrmoptionSepArg,	(caddr_t) NULL},
101{"-display",	".display", 	XrmoptionSepArg,	(caddr_t) NULL},
102{"-gray",	".gray",	XrmoptionNoArg,		(caddr_t) "on"},
103{"-green",	".green",	XrmoptionNoArg,		(caddr_t) "on"},
104{"-help",	".help",        XrmoptionNoArg,		(caddr_t) "on"},
105{"-red",	".red",		XrmoptionNoArg,		(caddr_t) "on"},
106{"-verbose",	".verbose",	XrmoptionNoArg,		(caddr_t) "on"},
107};
108#define NOPTIONS (sizeof optionTable / sizeof optionTable[0])
109
110static void usage(Status status);
111
112static void
113parse(int argc, char **argv)
114{
115    XrmDatabase		database = NULL;
116    char		*type;
117    XrmValue		value;
118    char		option[512];
119
120    if (argc == 1)
121	usage(0);
122
123    XrmInitialize();
124    XrmParseCommand(&database, optionTable, NOPTIONS, program_name, &argc,
125		    argv);
126    if (--argc)
127	usage(1);
128
129    (void) sprintf(option, "%s%s", program_name, ".all");
130    if (XrmGetResource(database, option, (char *) NULL, &type, &value))
131    	all++;
132
133    (void) sprintf(option, "%s%s", program_name, ".best");
134    if (XrmGetResource(database, option, (char *) NULL, &type, &value))
135    	propertyTable[BEST].create++;
136
137    (void) sprintf(option, "%s%s", program_name, ".blue");
138    if (XrmGetResource(database, option, (char *) NULL, &type, &value))
139	propertyTable[BLUE].create++;
140
141    (void) sprintf(option, "%s%s", program_name, ".default");
142    if (XrmGetResource(database, option, (char *) NULL, &type, &value))
143	propertyTable[DEFAULT].create++;
144
145    (void) sprintf(option, "%s%s", program_name, ".delete");
146    if (XrmGetResource(database, option, (char *) NULL, &type, &value)) {
147	register int i;
148	for (i=0; i < NPROPERTIES; i++) {
149	    if (strcmp((char *) value.addr, propertyTable[i].nickname) == 0) {
150		propertyTable[i].delete++;
151		break;
152	    }
153	    if (strcmp((char *) value.addr, "all") == 0)
154		propertyTable[i].delete++;
155	}
156    }
157
158    (void) sprintf(option, "%s%s", program_name, ".display");
159    if (XrmGetResource(database, option, (char *) NULL, &type, &value))
160	display_name = value.addr;
161
162    (void) sprintf(option, "%s%s", program_name, ".gray");
163    if (XrmGetResource(database, option, (char *) NULL, &type, &value))
164	propertyTable[GRAY].create++;
165
166    (void) sprintf(option, "%s%s", program_name, ".green");
167    if (XrmGetResource(database, option, (char *) NULL, &type, &value))
168	propertyTable[GREEN].create++;
169
170    (void) sprintf(option, "%s%s", program_name, ".help");
171    if (XrmGetResource(database, option, (char *) NULL, &type, &value))
172	help++;
173
174    (void) sprintf(option, "%s%s", program_name, ".red");
175    if (XrmGetResource(database, option, (char *) NULL, &type, &value))
176	propertyTable[RED].create++;
177
178    (void) sprintf(option, "%s%s", program_name, ".verbose");
179    if (XrmGetResource(database, option, (char *) NULL, &type, &value))
180	verbose++;
181}
182
183static void
184Exit(Status status)
185{
186    if (dpy)
187	XCloseDisplay(dpy);
188    exit(status);
189}
190
191static void
192usage(Status status)
193{
194    register char	**i;
195    (void) fprintf(stderr, "usage:  %s [-options]\n\n", program_name);
196    (void) fprintf(stderr, "where options include:\n");
197    for (i = usage_message; *i != NULL; i++)
198	(void) fprintf(stderr, "%s\n", *i);
199    Exit(status);
200}
201
202/* Determine the visual of greatest depth in a given visual class.
203 * If no such visual exists, return NULL.
204 */
205static XVisualInfo *
206getDeepestVisual(int visual_class,   /* specifies the desired visual class */
207		 XVisualInfo *vinfo, /* specifies all visuals for a screen */
208		 int nvisuals)	/* specifies number of visuals in the list */
209{
210    register int	i;
211    unsigned int	maxdepth = 0;
212    XVisualInfo		*v = NULL;
213
214    for (i=0; i < nvisuals; i++, vinfo++)
215	if (vinfo->class == visual_class && vinfo->depth > maxdepth)
216	{
217	    maxdepth = vinfo->depth;
218	    v = vinfo;
219	}
220    return(v);
221}
222
223/* Determine the ``best'' visual of the screen for a standard colormap
224 * property.  Return NULL if no visual is appropriate.
225 */
226static XVisualInfo *
227getBestVisual(Atom property,	/* specifies the standard colormap */
228	      XVisualInfo *vinfo, /* specifies all visuals of the screen */
229	      int nvisuals)	/* specifies number of visuals of screen */
230{
231    XVisualInfo	*v1 = NULL, *v2 = NULL;
232
233    if (vinfo == NULL)		 /* unexpected: a screen with no visuals */
234	return v1;
235    v1 = getDeepestVisual(DirectColor, vinfo, nvisuals);
236    v2 = getDeepestVisual(PseudoColor, vinfo, nvisuals);
237    if (v2 && (!v1 || (v2->colormap_size >=
238		       ((v1->red_mask | v1->green_mask | v1->blue_mask) + 1))))
239	return v2;
240    else if (v1)
241	return v1;
242    if (property == XA_RGB_BEST_MAP)
243	if (((v1 = getDeepestVisual(TrueColor, vinfo, nvisuals)) != NULL) ||
244	    ((v1 = getDeepestVisual(StaticColor, vinfo, nvisuals)) != NULL))
245	    return v1;
246    if (property == XA_RGB_GRAY_MAP)
247	if (((v1 = getDeepestVisual(GrayScale, vinfo, nvisuals)) != NULL) ||
248	    ((v1 = getDeepestVisual(StaticGray, vinfo, nvisuals)) != NULL))
249	    return v1;
250    if (property == XA_RGB_DEFAULT_MAP)
251	for (v1 = vinfo; v1->visual != DefaultVisual(dpy, v1->screen); v1++)
252	    ;
253    return v1;
254
255}
256
257static char *
258visualStringFromClass(int class)
259{
260    switch (class) {
261      case PseudoColor: return "PseudoColor";
262      case DirectColor: return "DirectColor";
263      case GrayScale: return "GrayScale";
264      case StaticColor: return "StaticColor";
265      case TrueColor: return "TrueColor";
266      case StaticGray: return "StaticGray";
267    }
268    return "unknown visual class";
269}
270
271static int
272doIndividualColormaps(void)
273{
274    int			i, screen, nvisuals;
275    Status		status = -1;
276    XVisualInfo		*vinfo = NULL, *v = NULL, template;
277
278    screen = DefaultScreen(dpy);
279    template.screen = screen;
280    vinfo = XGetVisualInfo(dpy, VisualScreenMask, &template, &nvisuals);
281
282    /* check for individual standard colormap requests */
283    for (i=0; i < NPROPERTIES; i++) {
284
285	if (propertyTable[i].delete) {
286	    XmuDeleteStandardColormap(dpy, screen, propertyTable[i].property);
287	    if (verbose)
288		fprintf(stderr, "%s: %s was deleted or did not exist.\n",
289			program_name, propertyTable[i].name);
290	}
291
292	if (! propertyTable[i].create)
293	    continue;
294
295	/* which visual is best for this property? */
296	v = getBestVisual(propertyTable[i].property, vinfo, nvisuals);
297	if (v == NULL) {
298	    if (verbose)
299		(void) fprintf(stderr,
300		       "%s: no visual appropriate for %s on screen %d.\n",
301			program_name, propertyTable[i].name, screen);
302	    continue;
303	}
304
305
306	if (verbose)
307	    (void) fprintf(stderr,
308			   "%s: making %s on a %s visual of depth %u.\n",
309			   program_name, propertyTable[i].name,
310			   visualStringFromClass(v->class), v->depth);
311
312	status = XmuLookupStandardColormap(dpy, screen, v->visualid,
313					   v->depth,
314					   propertyTable[i].property,
315					   DO_NOT_REPLACE, RETAIN);
316	if (verbose)
317	    (void) fprintf(stderr,
318			   "%s: %s standard colormap %s.\n", program_name,
319			   propertyTable[i].name, (status)
320			   ? "was created or already exists"
321			   : "cannot be defined");
322	if (!status)
323	    break;
324    }
325    XFree((char *) vinfo);
326    return status;
327}
328
329/* Bare bones standard colormap generation utility */
330int
331main(int argc, char *argv[])
332{
333    Status	status = 0;
334
335    if ((program_name = strrchr(*argv, '/')))
336	program_name++;
337    else
338	program_name = *argv;
339
340    parse(argc, argv);
341
342    if ((dpy = XOpenDisplay(display_name)) == NULL) {
343	(void) fprintf(stderr, "%s: cannot open display \"%s\".\n",
344		       program_name, XDisplayName(display_name));
345	exit(1);
346    }
347
348    if (help) {
349	usage(0);
350	Exit(0);
351
352	/* Muffle gcc */
353	return 0;
354    }
355
356    if (all) {
357	if (verbose)
358	    (void) fprintf(stderr,
359			   "%s: making all appropriate standard colormaps...",
360			   program_name);
361	status = XmuAllStandardColormaps(dpy);
362	if (verbose)
363	    (void) fprintf(stderr,
364			   "\n%s!\n", (status) ? "success" : "failure");
365    }
366    else {
367	status = doIndividualColormaps();
368	if (!status && verbose)
369	    (void) fprintf(stderr,
370		    "Not all new colormap definitions will be retained.\n");
371    }
372    Exit((status == 0) ? 1 : 0);
373    /* Muffle compiler */
374    return 0;
375}
376