550N/A/*
550N/A*
550N/A* cmap_alloc.c 1.x
550N/A*
943N/A* Copyright (c) 1991, 2000, Oracle and/or its affiliates. All rights reserved.
550N/A*
550N/A* Permission is hereby granted, free of charge, to any person obtaining a
919N/A* copy of this software and associated documentation files (the "Software"),
919N/A* to deal in the Software without restriction, including without limitation
919N/A* the rights to use, copy, modify, merge, publish, distribute, sublicense,
919N/A* and/or sell copies of the Software, and to permit persons to whom the
919N/A* Software is furnished to do so, subject to the following conditions:
550N/A*
919N/A* The above copyright notice and this permission notice (including the next
919N/A* paragraph) shall be included in all copies or substantial portions of the
919N/A* Software.
550N/A*
919N/A* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
919N/A* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
919N/A* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
919N/A* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
919N/A* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
919N/A* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
919N/A* DEALINGS IN THE SOFTWARE.
550N/A*/
550N/A
550N/A
550N/A#include <X11/Xlib.h>
550N/A#include <X11/Xutil.h>
550N/A#include <X11/Xos.h>
550N/A#include <X11/Xatom.h>
550N/A#include <stdio.h>
550N/A#include <stdlib.h>
550N/A
550N/A#define All -1
550N/A#define DYNAMIC_VISUAL(class) (((class) % 2) ? True : False)
550N/A
550N/Achar *prog_name;
550N/Achar *display_name = NULL;
550N/Aint force = False;
550N/Aint all_screens = False;
550N/Aint depth = All;
550N/Aint visual_class = All;
550N/Aint verbose = False;
550N/A
550N/Aint created_colormap = False;
550N/AXStandardColormap *allocated_cmaps;
550N/Aint num_cmaps;
550N/AXVisualInfo *available_visuals;
550N/Aint num_visuals;
550N/A
550N/Astatic void alloc_cmaps_for_screen();
550N/Astatic void alloc_cmap_for_visual();
550N/Astatic void create_colormap();
550N/Astatic char *visual_class_name();
550N/Astatic void parse_cmdline();
550N/Astatic int string_to_depth();
550N/Astatic int string_to_visual();
550N/Astatic void usage();
550N/A
550N/A
550N/Aint
550N/Amain(argc, argv)
550N/A int argc;
550N/A char **argv;
550N/A{
550N/A Display *display;
550N/A int screen;
550N/A
550N/A /* Take care of command line options */
550N/A parse_cmdline(argc, argv);
550N/A
550N/A /* Try to open the display */
550N/A if ((display = XOpenDisplay(display_name)) == NULL) {
550N/A (void)fprintf(stderr, "Error %s: can't open display \"%s\".\n",
550N/A argv[0], XDisplayName(display_name));
550N/A exit(0);
550N/A }
550N/A
550N/A /* Handle all necessary screens */
550N/A if (all_screens)
550N/A for (screen = 0; screen < ScreenCount(display); screen++)
550N/A alloc_cmaps_for_screen(display, screen);
550N/A else
550N/A alloc_cmaps_for_screen(display, DefaultScreen(display));
550N/A
550N/A /* If we created any colormaps, we need to ensure
550N/A * that they live after the program exits.
550N/A */
550N/A if (created_colormap)
550N/A XSetCloseDownMode(display, RetainPermanent);
550N/A
550N/A XCloseDisplay(display);
550N/A return (1);
550N/A}
550N/A
550N/A
550N/Astatic void
550N/Aalloc_cmaps_for_screen(display, screen)
550N/A Display *display;
550N/A int screen;
550N/A{
550N/A XVisualInfo vinfo_template;
550N/A XVisualInfo *vinfo;
550N/A VisualID default_visualid;
550N/A int v;
550N/A
550N/A if (verbose)
550N/A (void)printf("Creating colormaps for screen #%d:\n", screen);
550N/A
550N/A /* Find out if any colormaps already exist in the property */
550N/A if (!XGetRGBColormaps(display, RootWindow(display, screen),
550N/A &allocated_cmaps, &num_cmaps, XA_RGB_DEFAULT_MAP))
550N/A num_cmaps = 0;
550N/A
550N/A /* Find the available visuals on the screen */
550N/A vinfo_template.screen = screen;
550N/A available_visuals = XGetVisualInfo(display, VisualScreenMask, &vinfo_template, &num_visuals);
550N/A
550N/A default_visualid = XVisualIDFromVisual(DefaultVisual(display, screen));
550N/A
550N/A /* Only try the specified visual */
550N/A if ((visual_class != All) && (depth != All)) {
550N/A v = 0;
550N/A vinfo = NULL;
550N/A while (!vinfo && (v < num_visuals))
550N/A if ((available_visuals[v].class == visual_class) &&
550N/A (available_visuals[v].depth == depth))
550N/A vinfo = &available_visuals[v];
550N/A else
550N/A v++;
550N/A if (vinfo)
550N/A if (vinfo->visualid == default_visualid) {
550N/A fprintf(stderr, "%s: no need to create a colormap for the default visual\n",
550N/A prog_name);
550N/A exit(0);
550N/A } else
550N/A alloc_cmap_for_visual(display, screen, vinfo);
550N/A }
550N/A
550N/A /* Try all visuals of visual_class with any depth */
550N/A else if (visual_class != All) {
550N/A for (v = 0; v < num_visuals; v++)
550N/A if ((visual_class == available_visuals[v].class) &&
550N/A (available_visuals[v].visualid != default_visualid))
550N/A alloc_cmap_for_visual(display, screen, &available_visuals[v]);
550N/A }
550N/A
550N/A /* Try all visuals of depth and any dynamic class */
550N/A else if (depth != All) {
550N/A for (v = 0; v < num_visuals; v++)
550N/A if ((depth == available_visuals[v].depth) &&
550N/A DYNAMIC_VISUAL(available_visuals[v].class) &&
550N/A (available_visuals[v].visualid != default_visualid))
550N/A alloc_cmap_for_visual(display, screen, &available_visuals[v]);
550N/A }
550N/A
550N/A /* Try all visuals */
550N/A else
550N/A for (v = 0; v < num_visuals; v++)
550N/A if (DYNAMIC_VISUAL(available_visuals[v].class) &&
550N/A (available_visuals[v].visualid != default_visualid))
550N/A alloc_cmap_for_visual(display, screen, &available_visuals[v]);
550N/A}
550N/A
550N/A
550N/Astatic void
550N/Aalloc_cmap_for_visual(display, screen, vinfo)
550N/A Display *display;
550N/A int screen;
550N/A XVisualInfo *vinfo;
550N/A{
550N/A int c = 0;
550N/A XStandardColormap *std_cmap = NULL;
550N/A XStandardColormap new_cmap;
550N/A
550N/A if (verbose)
550N/A (void)printf(" Creating a colormap for the %s %d bit visual...",
550N/A visual_class_name(vinfo->class), vinfo->depth);
550N/A
550N/A /* Check to see if one already exists */
550N/A while (!std_cmap && (c < num_cmaps))
550N/A if ((allocated_cmaps[c].visualid == vinfo->visualid) &&
550N/A (allocated_cmaps[c].red_max == 0) &&
550N/A (allocated_cmaps[c].red_mult == 0) &&
550N/A (allocated_cmaps[c].green_max == 0) &&
550N/A (allocated_cmaps[c].green_mult == 0) &&
550N/A (allocated_cmaps[c].blue_max == 0) &&
550N/A (allocated_cmaps[c].blue_mult == 0))
550N/A std_cmap = &allocated_cmaps[c];
550N/A else
550N/A c++;
550N/A
550N/A if (std_cmap && !force && verbose)
550N/A (void)printf("one already exists\n");
550N/A else if (!std_cmap || force) {
550N/A /* Create the colormap */
550N/A create_colormap(display, vinfo, &new_cmap);
550N/A
550N/A /* append it to the property on the root window */
550N/A XChangeProperty(display, RootWindow(display, screen),
550N/A XA_RGB_DEFAULT_MAP, XA_RGB_COLOR_MAP,
550N/A 32, PropModeAppend, (unsigned char *)(&new_cmap),
550N/A 10);
550N/A if (verbose)
550N/A (void)printf("done\n new colormap id = 0x%x\n", new_cmap.colormap);
550N/A }
550N/A}
550N/A
550N/A
550N/Astatic void
550N/Acreate_colormap(display, vinfo, std_colormap)
550N/A Display *display;
550N/A XVisualInfo *vinfo;
550N/A XStandardColormap *std_colormap; /* RETURN */
550N/A{
550N/A Colormap colormap;
550N/A XColor color;
550N/A
550N/A colormap = XCreateColormap(display, RootWindow(display, vinfo->screen),
550N/A vinfo->visual, AllocNone);
550N/A
550N/A /* Allocate black from the colormap */
550N/A color.red = color.green = color.blue = 0;
550N/A XAllocColor(display, colormap, &color);
550N/A
550N/A /* Fill out the standard colormap information */
550N/A std_colormap->colormap = colormap;
550N/A std_colormap->red_max = 0;
550N/A std_colormap->red_mult = 0;
550N/A std_colormap->green_max = 0;
550N/A std_colormap->green_mult = 0;
550N/A std_colormap->blue_max = 0;
550N/A std_colormap->blue_mult = 0;
550N/A std_colormap->base_pixel = color.pixel;
550N/A std_colormap->visualid = vinfo->visualid;
550N/A
550N/A /* We don't want anybody pulling the colormap out from
550N/A * under running clients, so set the killid to 0.
550N/A */
550N/A std_colormap->killid = 0;
550N/A
550N/A created_colormap = True;
550N/A}
550N/A
550N/A
550N/Astatic char *
550N/Avisual_class_name(class)
550N/A int class;
550N/A{
550N/A char *name;
550N/A
550N/A switch (class) {
550N/A case StaticGray:
550N/A name = "StaticGray";
550N/A break;
550N/A case GrayScale:
550N/A name = "GrayScale";
550N/A break;
550N/A case StaticColor:
550N/A name = "StaticColor";
550N/A break;
550N/A case PseudoColor:
550N/A name = "PseudoColor";
550N/A break;
550N/A case TrueColor:
550N/A name = "TrueColor";
550N/A break;
550N/A case DirectColor:
550N/A name = "DirectColor";
550N/A break;
550N/A default:
550N/A name = "";
550N/A break;
550N/A }
550N/A return name;
550N/A}
550N/A
550N/A
550N/Astatic void
550N/Aparse_cmdline(argc, argv)
550N/A int argc;
550N/A char **argv;
550N/A{
550N/A int option = 1;
550N/A
550N/A if (argc)
550N/A prog_name = argv[0];
550N/A
550N/A while (option < argc) {
550N/A if (!strcmp(argv[option], "-display"))
550N/A if (++option < argc)
550N/A display_name = argv[option];
550N/A else
550N/A usage();
550N/A
550N/A else if (!strcmp(argv[option], "-force"))
550N/A force = True;
550N/A
550N/A else if (!strcmp(argv[option], "-allscreens"))
550N/A all_screens = True;
550N/A
550N/A else if (!strcmp(argv[option], "-depth"))
550N/A if (++option < argc) {
550N/A depth = string_to_depth(argv[option]);
550N/A if (depth == All) {
550N/A fprintf(stderr, "%s: unknown depth %s\n", prog_name, argv[option]);
550N/A usage();
550N/A }
550N/A } else
550N/A usage();
550N/A
550N/A else if (!strcmp(argv[option], "-visual"))
550N/A if (++option < argc) {
550N/A visual_class = string_to_visual(argv[option]);
550N/A if (visual_class == All) {
550N/A fprintf(stderr, "%s: unknown visual class %s\n", prog_name, argv[option]);
550N/A usage();
550N/A } else if (!DYNAMIC_VISUAL(visual_class)) {
550N/A fprintf(stderr, "%s: no need to create a colormap for a static visual\n", prog_name);
550N/A exit(0);
550N/A }
550N/A } else
550N/A usage();
550N/A
550N/A else if (!strcmp(argv[option], "-verbose"))
550N/A verbose = True;
550N/A
550N/A else if (!strcmp(argv[option], "-help"))
550N/A usage();
550N/A
550N/A else {
550N/A (void)fprintf(stderr, "%s: unknown command line option \"%s\"\n",
550N/A prog_name, argv[option]);
550N/A usage();
550N/A }
550N/A option++;
550N/A }
550N/A}
550N/A
550N/A
550N/Astatic int
550N/Astring_to_depth(str)
550N/A char *str;
550N/A{
550N/A int depth;
550N/A
550N/A if ((sscanf(str, "%d", &depth) != 1) || (depth < 1))
550N/A depth = All;
550N/A
550N/A return depth;
550N/A}
550N/A
550N/A
550N/Astatic int
550N/Astring_to_visual(str)
550N/A char *str;
550N/A{
550N/A int visual_class;
550N/A
550N/A if (!strcmp(str, "StaticGray"))
550N/A visual_class = StaticGray;
550N/A else if (!strcmp(str, "GrayScale"))
550N/A visual_class = GrayScale;
550N/A else if (!strcmp(str, "StaticColor"))
550N/A visual_class = StaticColor;
550N/A else if (!strcmp(str, "PseudoColor"))
550N/A visual_class = PseudoColor;
550N/A else if (!strcmp(str, "TrueColor"))
550N/A visual_class = TrueColor;
550N/A else if (!strcmp(str, "DirectColor"))
550N/A visual_class = DirectColor;
550N/A else
550N/A visual_class = All;
550N/A
550N/A return visual_class;
550N/A}
550N/A
550N/A
550N/Astatic void
550N/Ausage()
550N/A{
550N/A (void)fprintf(stderr, "Usage: %s [-display <display:n.screen>]\n", prog_name);
550N/A (void)fprintf(stderr, "\t\t[-force] [-allscreens]\n");
550N/A (void)fprintf(stderr, "\t\t[-depth <n>] [-visual <class>]\n");
550N/A (void)fprintf(stderr, "\t\t[-verbose] [-help]\n");
550N/A exit(0);
550N/A}
550N/A