Blame src/LookupCmap.c

Packit Service 2b1f13
/*
Packit Service 2b1f13
Packit Service 2b1f13
Copyright 1989, 1998  The Open Group
Packit Service 2b1f13
Packit Service 2b1f13
Permission to use, copy, modify, distribute, and sell this software and its
Packit Service 2b1f13
documentation for any purpose is hereby granted without fee, provided that
Packit Service 2b1f13
the above copyright notice appear in all copies and that both that
Packit Service 2b1f13
copyright notice and this permission notice appear in supporting
Packit Service 2b1f13
documentation.
Packit Service 2b1f13
Packit Service 2b1f13
The above copyright notice and this permission notice shall be included in
Packit Service 2b1f13
all copies or substantial portions of the Software.
Packit Service 2b1f13
Packit Service 2b1f13
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
Packit Service 2b1f13
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
Packit Service 2b1f13
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
Packit Service 2b1f13
OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
Packit Service 2b1f13
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
Packit Service 2b1f13
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Packit Service 2b1f13
Packit Service 2b1f13
Except as contained in this notice, the name of The Open Group shall not be
Packit Service 2b1f13
used in advertising or otherwise to promote the sale, use or other dealings
Packit Service 2b1f13
in this Software without prior written authorization from The Open Group.
Packit Service 2b1f13
Packit Service 2b1f13
*/
Packit Service 2b1f13
Packit Service 2b1f13
/*
Packit Service 2b1f13
 * Author:  Donna Converse, MIT X Consortium
Packit Service 2b1f13
 */
Packit Service 2b1f13
Packit Service 2b1f13
#ifdef HAVE_CONFIG_H
Packit Service 2b1f13
#include <config.h>
Packit Service 2b1f13
#endif
Packit Service 2b1f13
#include <stdio.h>
Packit Service 2b1f13
#include <X11/Xlib.h>
Packit Service 2b1f13
#include <X11/Xatom.h>
Packit Service 2b1f13
#include <X11/Xutil.h>
Packit Service 2b1f13
#include <X11/Xmu/StdCmap.h>
Packit Service 2b1f13
#include <stdlib.h>
Packit Service 2b1f13
Packit Service 2b1f13
/*
Packit Service 2b1f13
 * Prototypes
Packit Service 2b1f13
 */
Packit Service 2b1f13
static Status lookup(Display*, int, VisualID, Atom, XStandardColormap*, Bool);
Packit Service 2b1f13
Packit Service 2b1f13
/*
Packit Service 2b1f13
 * To create a standard colormap if one does not currently exist, or
Packit Service 2b1f13
 * replace the currently existing standard colormap, use
Packit Service 2b1f13
 * XmuLookupStandardColormap().
Packit Service 2b1f13
 *
Packit Service 2b1f13
 * Given a screen, a visual, and a property, XmuLookupStandardColormap()
Packit Service 2b1f13
 * will determine the best allocation for the property under the specified
Packit Service 2b1f13
 * visual, and determine the whether to create a new colormap or to use
Packit Service 2b1f13
 * the default colormap of the screen.  It will call XmuStandardColormap()
Packit Service 2b1f13
 * to create the standard colormap.
Packit Service 2b1f13
 *
Packit Service 2b1f13
 * If replace is true, any previous definition of the property will be
Packit Service 2b1f13
 * replaced.  If retain is true, the property and the colormap will be
Packit Service 2b1f13
 * made permanent for the duration of the server session.  However,
Packit Service 2b1f13
 * pre-existing property definitions which are not replaced cannot be made
Packit Service 2b1f13
 * permanent by a call to XmuLookupStandardColormap(); a request to retain
Packit Service 2b1f13
 * resources pertains to newly created resources.
Packit Service 2b1f13
 *
Packit Service 2b1f13
 * Returns 0 on failure, non-zero on success.  A request to create a
Packit Service 2b1f13
 * standard colormap upon a visual which cannot support such a map is
Packit Service 2b1f13
 * considered a failure.  An example of this would be requesting any
Packit Service 2b1f13
 * standard colormap property on a monochrome visual, or, requesting an
Packit Service 2b1f13
 * RGB_BEST_MAP on a display whose colormap size is 16.
Packit Service 2b1f13
 */
Packit Service 2b1f13
Packit Service 2b1f13
Status
Packit Service 2b1f13
XmuLookupStandardColormap(Display *dpy, int screen, VisualID visualid,
Packit Service 2b1f13
			  unsigned int depth, Atom property,
Packit Service 2b1f13
			  Bool replace, Bool retain)
Packit Service 2b1f13
     /*
Packit Service 2b1f13
      * dpy		- specifies X server connection
Packit Service 2b1f13
      * screen 		- specifies screen of display
Packit Service 2b1f13
      * visualid	- specifies the visual type
Packit Service 2b1f13
      * depth		- specifies  the visual type
Packit Service 2b1f13
      * property	- a standard colormap property
Packit Service 2b1f13
      * replace		- specifies whether to replace
Packit Service 2b1f13
      * retain		- specifies whether to retain
Packit Service 2b1f13
      */
Packit Service 2b1f13
{
Packit Service 2b1f13
    Display		*odpy;		/* original display connection */
Packit Service 2b1f13
    XStandardColormap	*colormap;
Packit Service 2b1f13
    XVisualInfo		vinfo_template, *vinfo;	/* visual */
Packit Service 2b1f13
    long		vinfo_mask;
Packit Service 2b1f13
    unsigned long	r_max, g_max, b_max;	/* allocation */
Packit Service 2b1f13
    int			count;
Packit Service 2b1f13
    Colormap		cmap;			/* colormap ID */
Packit Service 2b1f13
    Status		status = 0;
Packit Service 2b1f13
Packit Service 2b1f13
Packit Service 2b1f13
    /* Match the requested visual */
Packit Service 2b1f13
Packit Service 2b1f13
    vinfo_template.visualid = visualid;
Packit Service 2b1f13
    vinfo_template.screen = screen;
Packit Service 2b1f13
    vinfo_template.depth = depth;
Packit Service 2b1f13
    vinfo_mask = VisualIDMask | VisualScreenMask | VisualDepthMask;
Packit Service 2b1f13
    if ((vinfo = XGetVisualInfo(dpy, vinfo_mask, &vinfo_template, &count)) ==
Packit Service 2b1f13
	NULL)
Packit Service 2b1f13
	return 0;
Packit Service 2b1f13
Packit Service 2b1f13
    /* Monochrome visuals have no standard maps */
Packit Service 2b1f13
Packit Service 2b1f13
    if (vinfo->colormap_size <= 2) {
Packit Service 2b1f13
	XFree((char *) vinfo);
Packit Service 2b1f13
	return 0;
Packit Service 2b1f13
    }
Packit Service 2b1f13
Packit Service 2b1f13
    /* If the requested property already exists on this screen, and,
Packit Service 2b1f13
     * if the replace flag has not been set to true, return success.
Packit Service 2b1f13
     * lookup() will remove a pre-existing map if replace is true.
Packit Service 2b1f13
     */
Packit Service 2b1f13
Packit Service 2b1f13
    if (lookup(dpy, screen, visualid, property, (XStandardColormap *) NULL,
Packit Service 2b1f13
	       replace) && !replace) {
Packit Service 2b1f13
	XFree((char *) vinfo);
Packit Service 2b1f13
	return 1;
Packit Service 2b1f13
    }
Packit Service 2b1f13
Packit Service 2b1f13
    /* Determine the best allocation for this property under the requested
Packit Service 2b1f13
     * visualid and depth, and determine whether or not to use the default
Packit Service 2b1f13
     * colormap of the screen.
Packit Service 2b1f13
     */
Packit Service 2b1f13
Packit Service 2b1f13
    if (!XmuGetColormapAllocation(vinfo, property, &r_max, &g_max, &b_max)) {
Packit Service 2b1f13
	XFree((char *) vinfo);
Packit Service 2b1f13
	return 0;
Packit Service 2b1f13
    }
Packit Service 2b1f13
Packit Service 2b1f13
    cmap = (property == XA_RGB_DEFAULT_MAP &&
Packit Service 2b1f13
	    visualid == XVisualIDFromVisual(DefaultVisual(dpy, screen)))
Packit Service 2b1f13
	? DefaultColormap(dpy, screen) : None;
Packit Service 2b1f13
Packit Service 2b1f13
    /* If retaining resources, open a new connection to the same server */
Packit Service 2b1f13
Packit Service 2b1f13
    if (retain) {
Packit Service 2b1f13
	odpy = dpy;
Packit Service 2b1f13
	if ((dpy = XOpenDisplay(XDisplayString(odpy))) == NULL) {
Packit Service 2b1f13
	    XFree((char *) vinfo);
Packit Service 2b1f13
	    return 0;
Packit Service 2b1f13
	}
Packit Service 2b1f13
    }
Packit Service 2b1f13
Packit Service 2b1f13
    /* Create the standard colormap */
Packit Service 2b1f13
Packit Service 2b1f13
    colormap = XmuStandardColormap(dpy, screen, visualid, depth, property,
Packit Service 2b1f13
				   cmap, r_max, g_max, b_max);
Packit Service 2b1f13
Packit Service 2b1f13
    /* Set the standard colormap property */
Packit Service 2b1f13
Packit Service 2b1f13
    if (colormap) {
Packit Service 2b1f13
	XGrabServer(dpy);
Packit Service 2b1f13
Packit Service 2b1f13
	if (lookup(dpy, screen, visualid, property, colormap, replace) &&
Packit Service 2b1f13
	    !replace) {
Packit Service 2b1f13
	    /* Someone has defined the property since we last looked.
Packit Service 2b1f13
	     * Since we will not replace it, release our own resources.
Packit Service 2b1f13
	     * If this is the default map, our allocations will be freed
Packit Service 2b1f13
	     * when this connection closes.
Packit Service 2b1f13
	     */
Packit Service 2b1f13
	    if (colormap->killid == ReleaseByFreeingColormap)
Packit Service 2b1f13
		XFreeColormap(dpy, colormap->colormap);
Packit Service 2b1f13
	}
Packit Service 2b1f13
	else if (retain) {
Packit Service 2b1f13
		XSetCloseDownMode(dpy, RetainPermanent);
Packit Service 2b1f13
	}
Packit Service 2b1f13
	XUngrabServer(dpy);
Packit Service 2b1f13
	XFree((char *) colormap);
Packit Service 2b1f13
	status = 1;
Packit Service 2b1f13
    }
Packit Service 2b1f13
Packit Service 2b1f13
    if (retain)
Packit Service 2b1f13
	XCloseDisplay(dpy);
Packit Service 2b1f13
    XFree((char *) vinfo);
Packit Service 2b1f13
    return status;
Packit Service 2b1f13
}
Packit Service 2b1f13
Packit Service 2b1f13
/***************************************************************************/
Packit Service 2b1f13
Packit Service 2b1f13
/* Lookup a standard colormap property.  If the property is RGB_DEFAULT_MAP,
Packit Service 2b1f13
 * the visualid is used to determine whether the indicated standard colormap
Packit Service 2b1f13
 * exists.  If the map exists and replace is true, delete the resources used
Packit Service 2b1f13
 * by the map and remove the property.  Return true if the map exists,
Packit Service 2b1f13
 * or did exist and was deleted; return false if the map was not found.
Packit Service 2b1f13
 *
Packit Service 2b1f13
 * Note that this is not the way that a Status return is normally used.
Packit Service 2b1f13
 *
Packit Service 2b1f13
 * If new is not NULL, new points to an XStandardColormap structure which
Packit Service 2b1f13
 * describes a standard colormap of the specified property.  It will be made
Packit Service 2b1f13
 * a standard colormap of the screen if none already exists, or if replace
Packit Service 2b1f13
 * is true.
Packit Service 2b1f13
 */
Packit Service 2b1f13
Packit Service 2b1f13
static Status
Packit Service 2b1f13
lookup(Display *dpy, int screen, VisualID visualid, Atom property,
Packit Service 2b1f13
       XStandardColormap *cnew, Bool replace)
Packit Service 2b1f13
     /*
Packit Service 2b1f13
      * dpy		- specifies display connection
Packit Service 2b1f13
      * screen		- specifies screen number
Packit Service 2b1f13
      * visualid	- specifies visualid for std map
Packit Service 2b1f13
      * property	- specifies colormap property name
Packit Service 2b1f13
      * cnew		- specifies a standard colormap
Packit Service 2b1f13
      * replace		- specifies whether to replace
Packit Service 2b1f13
      */
Packit Service 2b1f13
{
Packit Service 2b1f13
    register int	i;
Packit Service 2b1f13
    int			count;
Packit Service 2b1f13
    XStandardColormap	*stdcmaps, *s;
Packit Service 2b1f13
    Window		win = RootWindow(dpy, screen);
Packit Service 2b1f13
Packit Service 2b1f13
    /* The property does not already exist */
Packit Service 2b1f13
Packit Service 2b1f13
    if (! XGetRGBColormaps(dpy, win, &stdcmaps, &count, property)) {
Packit Service 2b1f13
	if (cnew)
Packit Service 2b1f13
	    XSetRGBColormaps(dpy, win, cnew, 1, property);
Packit Service 2b1f13
	return 0;
Packit Service 2b1f13
    }
Packit Service 2b1f13
Packit Service 2b1f13
    /* The property exists and is not describing the RGB_DEFAULT_MAP */
Packit Service 2b1f13
Packit Service 2b1f13
    if (property != XA_RGB_DEFAULT_MAP) {
Packit Service 2b1f13
	if (replace) {
Packit Service 2b1f13
	    XmuDeleteStandardColormap(dpy, screen, property);
Packit Service 2b1f13
	    if (cnew)
Packit Service 2b1f13
		XSetRGBColormaps(dpy, win, cnew, 1, property);
Packit Service 2b1f13
	}
Packit Service 2b1f13
	XFree((char *)stdcmaps);
Packit Service 2b1f13
	return 1;
Packit Service 2b1f13
    }
Packit Service 2b1f13
Packit Service 2b1f13
    /* The property exists and is RGB_DEFAULT_MAP */
Packit Service 2b1f13
Packit Service 2b1f13
    for (i=0, s=stdcmaps; (i < count) && (s->visualid != visualid); i++, s++)
Packit Service 2b1f13
	;
Packit Service 2b1f13
Packit Service 2b1f13
    /* No RGB_DEFAULT_MAP property matches the given visualid */
Packit Service 2b1f13
Packit Service 2b1f13
    if (i == count) {
Packit Service 2b1f13
	if (cnew) {
Packit Service 2b1f13
	    XStandardColormap	*m, *maps;
Packit Service 2b1f13
Packit Service 2b1f13
	    s = (XStandardColormap *) malloc((unsigned) ((count+1) * sizeof
Packit Service 2b1f13
					      (XStandardColormap)));
Packit Service 2b1f13
Packit Service 2b1f13
	    for (i = 0, m = s, maps = stdcmaps; i < count; i++, m++, maps++) {
Packit Service 2b1f13
		m->colormap   = maps->colormap;
Packit Service 2b1f13
		m->red_max    = maps->red_max;
Packit Service 2b1f13
		m->red_mult   = maps->red_mult;
Packit Service 2b1f13
		m->green_max  = maps->green_max;
Packit Service 2b1f13
		m->green_mult = maps->green_mult;
Packit Service 2b1f13
		m->blue_max   = maps->blue_max;
Packit Service 2b1f13
		m->blue_mult  = maps->blue_mult;
Packit Service 2b1f13
		m->base_pixel = maps->base_pixel;
Packit Service 2b1f13
		m->visualid   = maps->visualid;
Packit Service 2b1f13
		m->killid     = maps->killid;
Packit Service 2b1f13
	    }
Packit Service 2b1f13
	    m->colormap   = cnew->colormap;
Packit Service 2b1f13
	    m->red_max    = cnew->red_max;
Packit Service 2b1f13
	    m->red_mult   = cnew->red_mult;
Packit Service 2b1f13
	    m->green_max  = cnew->green_max;
Packit Service 2b1f13
	    m->green_mult = cnew->green_mult;
Packit Service 2b1f13
	    m->blue_max   = cnew->blue_max;
Packit Service 2b1f13
	    m->blue_mult  = cnew->blue_mult;
Packit Service 2b1f13
	    m->base_pixel = cnew->base_pixel;
Packit Service 2b1f13
	    m->visualid   = cnew->visualid;
Packit Service 2b1f13
	    m->killid     = cnew->killid;
Packit Service 2b1f13
Packit Service 2b1f13
	    XSetRGBColormaps(dpy, win, s, ++count, property);
Packit Service 2b1f13
	    free((char *) s);
Packit Service 2b1f13
	}
Packit Service 2b1f13
	XFree((char *) stdcmaps);
Packit Service 2b1f13
	return 0;
Packit Service 2b1f13
    }
Packit Service 2b1f13
Packit Service 2b1f13
    /* Found an RGB_DEFAULT_MAP property with a matching visualid */
Packit Service 2b1f13
Packit Service 2b1f13
    if (replace) {
Packit Service 2b1f13
	/* Free old resources first - we may need them, particularly in
Packit Service 2b1f13
	 * the default colormap of the screen.  However, because of this,
Packit Service 2b1f13
	 * it is possible that we will destroy the old resource and fail
Packit Service 2b1f13
	 * to create a new one if XmuStandardColormap() fails.
Packit Service 2b1f13
	 */
Packit Service 2b1f13
Packit Service 2b1f13
	if (count == 1) {
Packit Service 2b1f13
	    XmuDeleteStandardColormap(dpy, screen, property);
Packit Service 2b1f13
	    if (cnew)
Packit Service 2b1f13
		XSetRGBColormaps(dpy, win, cnew, 1, property);
Packit Service 2b1f13
	}
Packit Service 2b1f13
	else {
Packit Service 2b1f13
	    XStandardColormap	*map;
Packit Service 2b1f13
Packit Service 2b1f13
	    /* s still points to the matching standard colormap */
Packit Service 2b1f13
Packit Service 2b1f13
	    if (s->killid == ReleaseByFreeingColormap) {
Packit Service 2b1f13
		if ((s->colormap != None) &&
Packit Service 2b1f13
		    (s->colormap != DefaultColormap(dpy, screen)))
Packit Service 2b1f13
		    XFreeColormap(dpy, s->colormap);
Packit Service 2b1f13
	    }
Packit Service 2b1f13
	    else if (s->killid != None)
Packit Service 2b1f13
		XKillClient(dpy, s->killid);
Packit Service 2b1f13
Packit Service 2b1f13
	    map = (cnew) ? cnew : stdcmaps + --count;
Packit Service 2b1f13
Packit Service 2b1f13
	    s->colormap   = map->colormap;
Packit Service 2b1f13
	    s->red_max    = map->red_max;
Packit Service 2b1f13
	    s->red_mult   = map->red_mult;
Packit Service 2b1f13
	    s->green_max  = map->green_max;
Packit Service 2b1f13
	    s->green_mult = map->green_mult;
Packit Service 2b1f13
	    s->blue_max   = map->blue_max;
Packit Service 2b1f13
	    s->blue_mult  = map->blue_mult;
Packit Service 2b1f13
	    s->visualid   = map->visualid;
Packit Service 2b1f13
	    s->killid     = map->killid;
Packit Service 2b1f13
Packit Service 2b1f13
	    XSetRGBColormaps(dpy, win, stdcmaps, count, property);
Packit Service 2b1f13
	}
Packit Service 2b1f13
    }
Packit Service 2b1f13
    XFree((char *) stdcmaps);
Packit Service 2b1f13
    return 1;
Packit Service 2b1f13
}