Blame src/StdCmap.c

Packit cd2a55
/*
Packit cd2a55
Packit cd2a55
Copyright 1989, 1998  The Open Group
Packit cd2a55
Packit cd2a55
Permission to use, copy, modify, distribute, and sell this software and its
Packit cd2a55
documentation for any purpose is hereby granted without fee, provided that
Packit cd2a55
the above copyright notice appear in all copies and that both that
Packit cd2a55
copyright notice and this permission notice appear in supporting
Packit cd2a55
documentation.
Packit cd2a55
Packit cd2a55
The above copyright notice and this permission notice shall be included in
Packit cd2a55
all copies or substantial portions of the Software.
Packit cd2a55
Packit cd2a55
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
Packit cd2a55
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
Packit cd2a55
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
Packit cd2a55
OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
Packit cd2a55
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
Packit cd2a55
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Packit cd2a55
Packit cd2a55
Except as contained in this notice, the name of The Open Group shall not be
Packit cd2a55
used in advertising or otherwise to promote the sale, use or other dealings
Packit cd2a55
in this Software without prior written authorization from The Open Group.
Packit cd2a55
Packit cd2a55
*/
Packit cd2a55
Packit cd2a55
/*
Packit cd2a55
 * Author:  Donna Converse, MIT X Consortium
Packit cd2a55
 */
Packit cd2a55
Packit cd2a55
#ifdef HAVE_CONFIG_H
Packit cd2a55
#include <config.h>
Packit cd2a55
#endif
Packit cd2a55
#include <stdio.h>
Packit cd2a55
#include <X11/Xlib.h>
Packit cd2a55
#include <X11/Xatom.h>
Packit cd2a55
#include <X11/Xutil.h>
Packit cd2a55
#include <X11/Xmu/StdCmap.h>
Packit cd2a55
Packit cd2a55
#define lowbit(x) ((x) & (~(x) + 1))
Packit cd2a55
Packit cd2a55
/*
Packit cd2a55
 * Prototypes
Packit cd2a55
 */
Packit cd2a55
/* argument restrictions */
Packit cd2a55
static Status valid_args(XVisualInfo*, unsigned long, unsigned long,
Packit cd2a55
			 unsigned long, Atom);
Packit cd2a55
Packit cd2a55
/*
Packit cd2a55
 * To create any one standard colormap, use XmuStandardColormap().
Packit cd2a55
 *
Packit cd2a55
 * Create a standard colormap for the given screen, visualid, and visual
Packit cd2a55
 * depth, with the given red, green, and blue maximum values, with the
Packit cd2a55
 * given standard property name.  Return a pointer to an XStandardColormap
Packit cd2a55
 * structure which describes the newly created colormap, upon success.
Packit cd2a55
 * Upon failure, return NULL.
Packit cd2a55
 *
Packit cd2a55
 * XmuStandardColormap() calls XmuCreateColormap() to create the map.
Packit cd2a55
 *
Packit cd2a55
 * Resources created by this function are not made permanent; that is the
Packit cd2a55
 * caller's responsibility.
Packit cd2a55
 */
Packit cd2a55
Packit cd2a55
XStandardColormap *
Packit cd2a55
XmuStandardColormap(Display *dpy, int screen, VisualID visualid,
Packit cd2a55
		    unsigned int depth, Atom property, Colormap cmap,
Packit cd2a55
		    unsigned long red_max, unsigned long green_max,
Packit cd2a55
		    unsigned long blue_max)
Packit cd2a55
     /*
Packit cd2a55
      * dpy				- specifies X server connection
Packit cd2a55
      * screen				- specifies display screen
Packit cd2a55
      * visualid			- identifies the visual type
Packit cd2a55
      * depth				- identifies the visual type
Packit cd2a55
      * property			- a standard colormap property
Packit cd2a55
      * cmap				- specifies colormap ID or None
Packit cd2a55
      * red_max, green_max, blue_max	- allocations
Packit cd2a55
      */
Packit cd2a55
{
Packit cd2a55
    XStandardColormap	*stdcmap;
Packit cd2a55
    Status		status;
Packit cd2a55
    XVisualInfo		vinfo_template, *vinfo;
Packit cd2a55
    long		vinfo_mask;
Packit cd2a55
    int			n;
Packit cd2a55
Packit cd2a55
    /* Match the required visual information to an actual visual */
Packit cd2a55
    vinfo_template.visualid = visualid;
Packit cd2a55
    vinfo_template.screen = screen;
Packit cd2a55
    vinfo_template.depth = depth;
Packit cd2a55
    vinfo_mask = VisualIDMask | VisualScreenMask | VisualDepthMask;
Packit cd2a55
    if ((vinfo = XGetVisualInfo(dpy, vinfo_mask, &vinfo_template, &n)) == NULL)
Packit cd2a55
	return NULL;
Packit cd2a55
Packit cd2a55
    /* Check the validity of the combination of visual characteristics,
Packit cd2a55
     * allocation, and colormap property.  Create an XStandardColormap
Packit cd2a55
     * structure.
Packit cd2a55
     */
Packit cd2a55
Packit cd2a55
    if (! valid_args(vinfo, red_max, green_max, blue_max, property)
Packit cd2a55
	|| ((stdcmap = XAllocStandardColormap()) == NULL)) {
Packit cd2a55
	XFree((char *) vinfo);
Packit cd2a55
	return NULL;
Packit cd2a55
    }
Packit cd2a55
Packit cd2a55
    /* Fill in the XStandardColormap structure */
Packit cd2a55
Packit cd2a55
    if (cmap == DefaultColormap(dpy, screen)) {
Packit cd2a55
	/* Allocating out of the default map, cannot use XFreeColormap() */
Packit cd2a55
	Window win = XCreateWindow(dpy, RootWindow(dpy, screen), 1, 1, 1, 1,
Packit cd2a55
				   0, 0, InputOnly, vinfo->visual,
Packit cd2a55
				   (unsigned long) 0,
Packit cd2a55
				   (XSetWindowAttributes *)NULL);
Packit cd2a55
	stdcmap->killid  = (XID) XCreatePixmap(dpy, win, 1, 1, depth);
Packit cd2a55
	XDestroyWindow(dpy, win);
Packit cd2a55
	stdcmap->colormap = cmap;
Packit cd2a55
    } else {
Packit cd2a55
	stdcmap->killid = ReleaseByFreeingColormap;
Packit cd2a55
	stdcmap->colormap = XCreateColormap(dpy, RootWindow(dpy, screen),
Packit cd2a55
					    vinfo->visual, AllocNone);
Packit cd2a55
    }
Packit cd2a55
    stdcmap->red_max = red_max;
Packit cd2a55
    stdcmap->green_max = green_max;
Packit cd2a55
    stdcmap->blue_max = blue_max;
Packit cd2a55
    if (property == XA_RGB_GRAY_MAP)
Packit cd2a55
	stdcmap->red_mult = stdcmap->green_mult = stdcmap->blue_mult = 1;
Packit cd2a55
    else if (vinfo->class == TrueColor || vinfo->class == DirectColor) {
Packit cd2a55
	stdcmap->red_mult = lowbit(vinfo->red_mask);
Packit cd2a55
	stdcmap->green_mult = lowbit(vinfo->green_mask);
Packit cd2a55
	stdcmap->blue_mult = lowbit(vinfo->blue_mask);
Packit cd2a55
    } else {
Packit cd2a55
	stdcmap->red_mult = (red_max > 0)
Packit cd2a55
	    ? (green_max + 1) * (blue_max + 1) : 0;
Packit cd2a55
	stdcmap->green_mult = (green_max > 0) ? blue_max + 1 : 0;
Packit cd2a55
	stdcmap->blue_mult = (blue_max > 0) ? 1 : 0;
Packit cd2a55
    }
Packit cd2a55
    stdcmap->base_pixel = 0;			/* base pixel may change */
Packit cd2a55
    stdcmap->visualid = vinfo->visualid;
Packit cd2a55
Packit cd2a55
    /* Make the colormap */
Packit cd2a55
Packit cd2a55
    status = XmuCreateColormap(dpy, stdcmap);
Packit cd2a55
Packit cd2a55
    /* Clean up */
Packit cd2a55
Packit cd2a55
    XFree((char *) vinfo);
Packit cd2a55
    if (!status) {
Packit cd2a55
Packit cd2a55
	/* Free the colormap or the pixmap, if we created one */
Packit cd2a55
	if (stdcmap->killid == ReleaseByFreeingColormap)
Packit cd2a55
	    XFreeColormap(dpy, stdcmap->colormap);
Packit cd2a55
	else if (stdcmap->killid != None)
Packit cd2a55
	    XFreePixmap(dpy, stdcmap->killid);
Packit cd2a55
Packit cd2a55
	XFree((char *) stdcmap);
Packit cd2a55
	return (XStandardColormap *) NULL;
Packit cd2a55
    }
Packit cd2a55
    return stdcmap;
Packit cd2a55
}
Packit cd2a55
Packit cd2a55
/****************************************************************************/
Packit cd2a55
static Status
Packit cd2a55
valid_args(XVisualInfo *vinfo, unsigned long red_max, unsigned long green_max,
Packit cd2a55
	   unsigned long blue_max, Atom property)
Packit cd2a55
     /*
Packit cd2a55
      * vinfo				- specifies visual
Packit cd2a55
      * red_max, green_max, blue_max	- specifies alloc
Packit cd2a55
      * property			- specifies property name
Packit cd2a55
      */
Packit cd2a55
{
Packit cd2a55
    unsigned long	ncolors;	/* number of colors requested */
Packit cd2a55
Packit cd2a55
    /* Determine that the number of colors requested is <= map size */
Packit cd2a55
Packit cd2a55
    if ((vinfo->class == DirectColor) || (vinfo->class == TrueColor)) {
Packit cd2a55
	unsigned long mask;
Packit cd2a55
Packit cd2a55
	mask = vinfo->red_mask;
Packit cd2a55
	while (!(mask & 1))
Packit cd2a55
	    mask >>= 1;
Packit cd2a55
	if (red_max > mask)
Packit cd2a55
	    return 0;
Packit cd2a55
	mask = vinfo->green_mask;
Packit cd2a55
	while (!(mask & 1))
Packit cd2a55
	    mask >>= 1;
Packit cd2a55
	if (green_max > mask)
Packit cd2a55
	    return 0;
Packit cd2a55
	mask = vinfo->blue_mask;
Packit cd2a55
	while (!(mask & 1))
Packit cd2a55
	    mask >>= 1;
Packit cd2a55
	if (blue_max > mask)
Packit cd2a55
	    return 0;
Packit cd2a55
    } else if (property == XA_RGB_GRAY_MAP) {
Packit cd2a55
	ncolors = red_max + green_max + blue_max + 1;
Packit cd2a55
	if (ncolors > vinfo->colormap_size)
Packit cd2a55
	    return 0;
Packit cd2a55
    } else {
Packit cd2a55
	ncolors = (red_max + 1) * (green_max + 1) * (blue_max + 1);
Packit cd2a55
	if (ncolors > vinfo->colormap_size)
Packit cd2a55
	    return 0;
Packit cd2a55
    }
Packit cd2a55
Packit cd2a55
    /* Determine that the allocation and visual make sense for the property */
Packit cd2a55
Packit cd2a55
    switch (property)
Packit cd2a55
    {
Packit cd2a55
      case XA_RGB_DEFAULT_MAP:
Packit cd2a55
	if (red_max == 0 || green_max == 0 || blue_max == 0)
Packit cd2a55
	    return 0;
Packit cd2a55
	break;
Packit cd2a55
      case XA_RGB_RED_MAP:
Packit cd2a55
	if (red_max == 0)
Packit cd2a55
	    return 0;
Packit cd2a55
	break;
Packit cd2a55
      case XA_RGB_GREEN_MAP:
Packit cd2a55
	if (green_max == 0)
Packit cd2a55
	    return 0;
Packit cd2a55
	break;
Packit cd2a55
      case XA_RGB_BLUE_MAP:
Packit cd2a55
	if (blue_max == 0)
Packit cd2a55
	    return 0;
Packit cd2a55
	break;
Packit cd2a55
      case XA_RGB_BEST_MAP:
Packit cd2a55
	if (red_max == 0 || green_max == 0 || blue_max == 0)
Packit cd2a55
	    return 0;
Packit cd2a55
	break;
Packit cd2a55
      case XA_RGB_GRAY_MAP:
Packit cd2a55
	if (red_max == 0 || blue_max == 0 || green_max == 0)
Packit cd2a55
	    return 0;
Packit cd2a55
	break;
Packit cd2a55
      default:
Packit cd2a55
	return 0;
Packit cd2a55
    }
Packit cd2a55
    return 1;
Packit cd2a55
}