CrCmap.c revision 6c321187
16c321187Smrg/* $Xorg: CrCmap.c,v 1.4 2001/02/09 02:03:51 xorgcvs Exp $ */
26c321187Smrg
36c321187Smrg/*
46c321187Smrg
56c321187SmrgCopyright 1989, 1998  The Open Group
66c321187Smrg
76c321187SmrgPermission to use, copy, modify, distribute, and sell this software and its
86c321187Smrgdocumentation for any purpose is hereby granted without fee, provided that
96c321187Smrgthe above copyright notice appear in all copies and that both that
106c321187Smrgcopyright notice and this permission notice appear in supporting
116c321187Smrgdocumentation.
126c321187Smrg
136c321187SmrgThe above copyright notice and this permission notice shall be included in
146c321187Smrgall copies or substantial portions of the Software.
156c321187Smrg
166c321187SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
176c321187SmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
186c321187SmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
196c321187SmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
206c321187SmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
216c321187SmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
226c321187Smrg
236c321187SmrgExcept as contained in this notice, the name of The Open Group shall not be
246c321187Smrgused in advertising or otherwise to promote the sale, use or other dealings
256c321187Smrgin this Software without prior written authorization from The Open Group.
266c321187Smrg
276c321187Smrg*/
286c321187Smrg/* $XFree86: xc/lib/Xmu/CrCmap.c,v 3.6 2001/01/17 19:42:53 dawes Exp $ */
296c321187Smrg
306c321187Smrg/*
316c321187Smrg * Author:  Donna Converse, MIT X Consortium
326c321187Smrg */
336c321187Smrg
346c321187Smrg/*
356c321187Smrg * CreateCmap.c - given a standard colormap description, make the map.
366c321187Smrg */
376c321187Smrg
386c321187Smrg#ifdef HAVE_CONFIG_H
396c321187Smrg#include <config.h>
406c321187Smrg#endif
416c321187Smrg#include <stdio.h>
426c321187Smrg#include <stdlib.h>
436c321187Smrg#include <X11/Xlib.h>
446c321187Smrg#include <X11/Xutil.h>
456c321187Smrg#include <X11/Xmu/StdCmap.h>
466c321187Smrg
476c321187Smrg/*
486c321187Smrg * Prototypes
496c321187Smrg */
506c321187Smrg/* allocate entire map Read Only */
516c321187Smrgstatic int ROmap(Display*, Colormap, unsigned long[], int, int);
526c321187Smrg
536c321187Smrg/* allocate a cell, prefer Read Only */
546c321187Smrgstatic Status ROorRWcell(Display*, Colormap, unsigned long[], int,
556c321187Smrg			 XColor*, unsigned long);
566c321187Smrg
576c321187Smrg/* allocate a cell Read Write */
586c321187Smrgstatic Status RWcell(Display*, Colormap, XColor*, XColor*, unsigned long*);
596c321187Smrg
606c321187Smrg/* for quicksort */
616c321187Smrgstatic int compare(_Xconst void*, _Xconst void*);
626c321187Smrg
636c321187Smrg/* find contiguous sequence of cells */
646c321187Smrgstatic Status contiguous(unsigned long[], int, int, unsigned long, int*, int*);
656c321187Smrg
666c321187Smrg/* frees resources before quitting */
676c321187Smrgstatic void free_cells(Display*, Colormap, unsigned long[], int, int);
686c321187Smrg
696c321187Smrg/* create a map in a RO visual type */
706c321187Smrgstatic Status readonly_map(Display*, XVisualInfo*, XStandardColormap*);
716c321187Smrg
726c321187Smrg/* create a map in a RW visual type */
736c321187Smrgstatic Status readwrite_map(Display*, XVisualInfo*, XStandardColormap*);
746c321187Smrg
756c321187Smrg#define lowbit(x) ((x) & (~(x) + 1))
766c321187Smrg#define TRUEMATCH(mult,max,mask) \
776c321187Smrg    (colormap->max * colormap->mult <= vinfo->mask && \
786c321187Smrg     lowbit(vinfo->mask) == colormap->mult)
796c321187Smrg
806c321187Smrg/*
816c321187Smrg * To create any one colormap which is described by an XStandardColormap
826c321187Smrg * structure, use XmuCreateColormap().
836c321187Smrg *
846c321187Smrg * Return 0 on failure, non-zero on success.
856c321187Smrg * Resources created by this function are not made permanent.
866c321187Smrg * No argument error checking is provided.  Use at your own risk.
876c321187Smrg *
886c321187Smrg * All colormaps are created with read only allocations, with the exception
896c321187Smrg * of read only allocations of colors in the default map or otherwise
906c321187Smrg * which fail to return the expected pixel value, and these are individually
916c321187Smrg * defined as read/write allocations.  This is done so that all the cells
926c321187Smrg * defined in the default map are contiguous, for use in image processing.
936c321187Smrg * This typically happens with White and Black in the default map.
946c321187Smrg *
956c321187Smrg * Colormaps of static visuals are considered to be successfully created if
966c321187Smrg * the map of the static visual matches the definition given in the
976c321187Smrg * standard colormap structure.
986c321187Smrg */
996c321187Smrg
1006c321187SmrgStatus
1016c321187SmrgXmuCreateColormap(Display *dpy, XStandardColormap *colormap)
1026c321187Smrg     /* dpy	 - specifies the connection under which the map is created
1036c321187Smrg      * colormap - specifies the map to be created, and returns, particularly
1046c321187Smrg      *		   if the map is created as a subset of the default colormap
1056c321187Smrg      *		   of the screen, the base_pixel of the map.
1066c321187Smrg					 */
1076c321187Smrg{
1086c321187Smrg    XVisualInfo		vinfo_template;	/* template visual information */
1096c321187Smrg    XVisualInfo		*vinfo;		/* matching visual information */
1106c321187Smrg    XVisualInfo		*vpointer;	/* for freeing the entire list */
1116c321187Smrg    long		vinfo_mask;	/* specifies the visual mask value */
1126c321187Smrg    int 		n;		/* number of matching visuals */
1136c321187Smrg    int			status;
1146c321187Smrg
1156c321187Smrg    vinfo_template.visualid = colormap->visualid;
1166c321187Smrg    vinfo_mask = VisualIDMask;
1176c321187Smrg    if ((vinfo = XGetVisualInfo(dpy, vinfo_mask, &vinfo_template, &n)) == NULL)
1186c321187Smrg	return 0;
1196c321187Smrg
1206c321187Smrg    /* A visual id may be valid on multiple screens.  Also, there may
1216c321187Smrg     * be multiple visuals with identical visual ids at different depths.
1226c321187Smrg     * If the colormap is the Default Colormap, use the Default Visual.
1236c321187Smrg     * Otherwise, arbitrarily, use the deepest visual.
1246c321187Smrg     */
1256c321187Smrg    vpointer = vinfo;
1266c321187Smrg    if (n > 1)
1276c321187Smrg    {
1286c321187Smrg	register int	i;
1296c321187Smrg	register int	screen_number;
1306c321187Smrg	Bool 		def_cmap;
1316c321187Smrg
1326c321187Smrg	def_cmap = False;
1336c321187Smrg	for (screen_number = ScreenCount(dpy); --screen_number >= 0; )
1346c321187Smrg	    if (colormap->colormap == DefaultColormap(dpy, screen_number)) {
1356c321187Smrg		def_cmap = True;
1366c321187Smrg		break;
1376c321187Smrg	    }
1386c321187Smrg
1396c321187Smrg	if (def_cmap) {
1406c321187Smrg	    for (i=0; i < n; i++, vinfo++) {
1416c321187Smrg		if (vinfo->visual == DefaultVisual(dpy, screen_number))
1426c321187Smrg			break;
1436c321187Smrg	    }
1446c321187Smrg	} else {
1456c321187Smrg	    int			maxdepth = 0;
1466c321187Smrg	    XVisualInfo		*v = NULL;
1476c321187Smrg
1486c321187Smrg	    for (i=0; i < n; i++, vinfo++)
1496c321187Smrg		if (vinfo->depth > maxdepth) {
1506c321187Smrg		    maxdepth = vinfo->depth;
1516c321187Smrg		    v = vinfo;
1526c321187Smrg		}
1536c321187Smrg	    vinfo = v;
1546c321187Smrg	}
1556c321187Smrg    }
1566c321187Smrg
1576c321187Smrg    if (vinfo->class == PseudoColor || vinfo->class == DirectColor ||
1586c321187Smrg	vinfo->class == GrayScale)
1596c321187Smrg	status = readwrite_map(dpy, vinfo, colormap);
1606c321187Smrg    else if (vinfo->class == TrueColor)
1616c321187Smrg	status = TRUEMATCH(red_mult, red_max, red_mask) &&
1626c321187Smrg	         TRUEMATCH(green_mult, green_max, green_mask) &&
1636c321187Smrg		 TRUEMATCH(blue_mult, blue_max, blue_mask);
1646c321187Smrg    else
1656c321187Smrg	status = readonly_map(dpy, vinfo, colormap);
1666c321187Smrg
1676c321187Smrg    XFree((char *) vpointer);
1686c321187Smrg    return status;
1696c321187Smrg}
1706c321187Smrg
1716c321187Smrg/****************************************************************************/
1726c321187Smrgstatic Status
1736c321187Smrgreadwrite_map(Display *dpy, XVisualInfo *vinfo, XStandardColormap *colormap)
1746c321187Smrg{
1756c321187Smrg    register unsigned long i, n;	/* index counters */
1766c321187Smrg    unsigned long	ncolors;	/* number of colors to be defined */
1776c321187Smrg    int			npixels;	/* number of pixels allocated R/W */
1786c321187Smrg    int			first_index;	/* first index of pixels to use */
1796c321187Smrg    int			remainder;	/* first index of remainder */
1806c321187Smrg    XColor		color;		/* the definition of a color */
1816c321187Smrg    unsigned long	*pixels;	/* array of colormap pixels */
1826c321187Smrg    unsigned long	delta;
1836c321187Smrg
1846c321187Smrg
1856c321187Smrg    /* Determine ncolors, the number of colors to be defined.
1866c321187Smrg     * Insure that 1 < ncolors <= the colormap size.
1876c321187Smrg     */
1886c321187Smrg    if (vinfo->class == DirectColor) {
1896c321187Smrg	ncolors = colormap->red_max;
1906c321187Smrg	if (colormap->green_max > ncolors)
1916c321187Smrg	    ncolors = colormap->green_max;
1926c321187Smrg	if (colormap->blue_max > ncolors)
1936c321187Smrg	    ncolors = colormap->blue_max;
1946c321187Smrg	ncolors++;
1956c321187Smrg	delta = lowbit(vinfo->red_mask) +
1966c321187Smrg	        lowbit(vinfo->green_mask) +
1976c321187Smrg		lowbit(vinfo->blue_mask);
1986c321187Smrg    } else {
1996c321187Smrg	ncolors = colormap->red_max * colormap->red_mult +
2006c321187Smrg		  colormap->green_max * colormap->green_mult +
2016c321187Smrg		  colormap->blue_max * colormap->blue_mult + 1;
2026c321187Smrg	delta = 1;
2036c321187Smrg    }
2046c321187Smrg    if (ncolors <= 1 || (int) ncolors > vinfo->colormap_size)	return 0;
2056c321187Smrg
2066c321187Smrg    /* Allocate Read/Write as much of the colormap as we can possibly get.
2076c321187Smrg     * Then insure that the pixels we were allocated are given in
2086c321187Smrg     * monotonically increasing order, using a quicksort.  Next, insure
2096c321187Smrg     * that our allocation includes a subset of contiguous pixels at least
2106c321187Smrg     * as long as the number of colors to be defined.  Now we know that
2116c321187Smrg     * these conditions are met:
2126c321187Smrg     *	1) There are no free cells in the colormap.
2136c321187Smrg     *  2) We have a contiguous sequence of pixels, monotonically
2146c321187Smrg     *     increasing, of length >= the number of colors requested.
2156c321187Smrg     *
2166c321187Smrg     * One cell at a time, we will free, compute the next color value,
2176c321187Smrg     * then allocate read only.  This takes a long time.
2186c321187Smrg     * This is done to insure that cells are allocated read only in the
2196c321187Smrg     * contiguous order which we prefer.  If the server has a choice of
2206c321187Smrg     * cells to grant to an allocation request, the server may give us any
2216c321187Smrg     * cell, so that is why we do these slow gymnastics.
2226c321187Smrg     */
2236c321187Smrg
2246c321187Smrg    if ((pixels = (unsigned long *) calloc((unsigned) vinfo->colormap_size,
2256c321187Smrg				      sizeof(unsigned long))) == NULL)
2266c321187Smrg	return 0;
2276c321187Smrg
2286c321187Smrg    if ((npixels = ROmap(dpy, colormap->colormap, pixels,
2296c321187Smrg			   vinfo->colormap_size, ncolors)) == 0) {
2306c321187Smrg	free((char *) pixels);
2316c321187Smrg	return 0;
2326c321187Smrg    }
2336c321187Smrg
2346c321187Smrg    qsort((char *) pixels, npixels, sizeof(unsigned long), compare);
2356c321187Smrg
2366c321187Smrg    if (!contiguous(pixels, npixels, ncolors, delta, &first_index, &remainder))
2376c321187Smrg    {
2386c321187Smrg	/* can't find enough contiguous cells, give up */
2396c321187Smrg	XFreeColors(dpy, colormap->colormap, pixels, npixels,
2406c321187Smrg		    (unsigned long) 0);
2416c321187Smrg	free((char *) pixels);
2426c321187Smrg	return 0;
2436c321187Smrg    }
2446c321187Smrg    colormap->base_pixel = pixels[first_index];
2456c321187Smrg
2466c321187Smrg    /* construct a gray map */
2476c321187Smrg    if (colormap->red_mult == 1 && colormap->green_mult == 1 &&
2486c321187Smrg	colormap->blue_mult == 1)
2496c321187Smrg	for (n=colormap->base_pixel, i=0; i < ncolors; i++, n += delta)
2506c321187Smrg	{
2516c321187Smrg	    color.pixel = n;
2526c321187Smrg	    color.blue = color.green = color.red =
2536c321187Smrg		(unsigned short) ((i * 65535) / (colormap->red_max +
2546c321187Smrg						 colormap->green_max +
2556c321187Smrg						 colormap->blue_max));
2566c321187Smrg
2576c321187Smrg	    if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
2586c321187Smrg			     first_index + i))
2596c321187Smrg		return 0;
2606c321187Smrg	}
2616c321187Smrg
2626c321187Smrg    /* construct a red ramp map */
2636c321187Smrg    else if (colormap->green_max == 0 && colormap->blue_max == 0)
2646c321187Smrg    	for (n=colormap->base_pixel, i=0; i < ncolors; i++, n += delta)
2656c321187Smrg	{
2666c321187Smrg	    color.pixel = n;
2676c321187Smrg	    color.red = (unsigned short) ((i * 65535) / colormap->red_max);
2686c321187Smrg	    color.green = color.blue = 0;
2696c321187Smrg
2706c321187Smrg	    if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
2716c321187Smrg			     first_index + i))
2726c321187Smrg		return 0;
2736c321187Smrg	}
2746c321187Smrg
2756c321187Smrg    /* construct a green ramp map */
2766c321187Smrg    else if (colormap->red_max == 0 && colormap->blue_max == 0)
2776c321187Smrg    	for (n=colormap->base_pixel, i=0; i < ncolors; i++, n += delta)
2786c321187Smrg	{
2796c321187Smrg	    color.pixel = n;
2806c321187Smrg	    color.green = (unsigned short) ((i * 65535) / colormap->green_max);
2816c321187Smrg	    color.red = color.blue = 0;
2826c321187Smrg
2836c321187Smrg	    if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
2846c321187Smrg			     first_index + i))
2856c321187Smrg		return 0;
2866c321187Smrg	}
2876c321187Smrg
2886c321187Smrg    /* construct a blue ramp map */
2896c321187Smrg    else if (colormap->red_max == 0 && colormap->green_max == 0)
2906c321187Smrg    	for (n=colormap->base_pixel, i=0; i < ncolors; i++, n += delta)
2916c321187Smrg	{
2926c321187Smrg	    color.pixel = n;
2936c321187Smrg	    color.blue = (unsigned short) ((i * 65535) / colormap->blue_max);
2946c321187Smrg	    color.red = color.green = 0;
2956c321187Smrg
2966c321187Smrg	    if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
2976c321187Smrg			     first_index + i))
2986c321187Smrg		return 0;
2996c321187Smrg	}
3006c321187Smrg
3016c321187Smrg    /* construct a standard red green blue cube map */
3026c321187Smrg    else
3036c321187Smrg    {
3046c321187Smrg#define calc(max,mult) (((n / colormap->mult) % \
3056c321187Smrg			 (colormap->max + 1)) * 65535) / colormap->max
3066c321187Smrg
3076c321187Smrg    	for (n=0, i=0; i < ncolors; i++, n += delta)
3086c321187Smrg	{
3096c321187Smrg	    color.pixel = n + colormap->base_pixel;
3106c321187Smrg	    color.red = calc(red_max, red_mult);
3116c321187Smrg	    color.green = calc(green_max, green_mult);
3126c321187Smrg	    color.blue = calc(blue_max, blue_mult);
3136c321187Smrg	    if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
3146c321187Smrg			     first_index + i))
3156c321187Smrg		return 0;
3166c321187Smrg	}
3176c321187Smrg#undef calc
3186c321187Smrg    }
3196c321187Smrg    /* We have a read-only map defined.  Now free unused cells,
3206c321187Smrg     * first those occuring before the contiguous sequence begins,
3216c321187Smrg     * then any following the contiguous sequence.
3226c321187Smrg     */
3236c321187Smrg
3246c321187Smrg    if (first_index)
3256c321187Smrg	XFreeColors(dpy, colormap->colormap, pixels, first_index,
3266c321187Smrg		    (unsigned long) 0);
3276c321187Smrg    if (remainder)
3286c321187Smrg	XFreeColors(dpy, colormap->colormap,
3296c321187Smrg		    &(pixels[first_index + ncolors]), remainder,
3306c321187Smrg		    (unsigned long) 0);
3316c321187Smrg
3326c321187Smrg    free((char *) pixels);
3336c321187Smrg    return 1;
3346c321187Smrg}
3356c321187Smrg
3366c321187Smrg
3376c321187Smrg/****************************************************************************/
3386c321187Smrgstatic int
3396c321187SmrgROmap(Display *dpy, Colormap cmap, unsigned long pixels[], int m, int n)
3406c321187Smrg     /*
3416c321187Smrg      * dpy	- the X server connection
3426c321187Smrg      * cmap	- specifies colormap ID
3436c321187Smrg      * pixels	- returns pixel allocations
3446c321187Smrg      * m	- specifies colormap size
3456c321187Smrg      * n	- specifies number of colors
3466c321187Smrg      */
3476c321187Smrg{
3486c321187Smrg    register int	p;
3496c321187Smrg
3506c321187Smrg    /* first try to allocate the entire colormap */
3516c321187Smrg    if (XAllocColorCells(dpy, cmap, 1, (unsigned long *) NULL,
3526c321187Smrg			 (unsigned) 0, pixels, (unsigned) m))
3536c321187Smrg	return m;
3546c321187Smrg
3556c321187Smrg    /* Allocate all available cells in the colormap, using a binary
3566c321187Smrg     * algorithm to discover how many cells we can allocate in the colormap.
3576c321187Smrg     */
3586c321187Smrg    m--;
3596c321187Smrg    while (n <= m) {
3606c321187Smrg	p = n + ((m - n + 1) / 2);
3616c321187Smrg	if (XAllocColorCells(dpy, cmap, 1, (unsigned long *) NULL,
3626c321187Smrg			     (unsigned) 0, pixels, (unsigned) p)) {
3636c321187Smrg	    if (p == m)
3646c321187Smrg		return p;
3656c321187Smrg	    else {
3666c321187Smrg		XFreeColors(dpy, cmap, pixels, p, (unsigned long) 0);
3676c321187Smrg		n = p;
3686c321187Smrg	    }
3696c321187Smrg	}
3706c321187Smrg	else
3716c321187Smrg	    m = p - 1;
3726c321187Smrg    }
3736c321187Smrg    return 0;
3746c321187Smrg}
3756c321187Smrg
3766c321187Smrg
3776c321187Smrg/****************************************************************************/
3786c321187Smrgstatic Status
3796c321187Smrgcontiguous(unsigned long pixels[], int npixels, int ncolors,
3806c321187Smrg	   unsigned long delta, int *first, int *rem)
3816c321187Smrg     /* pixels	- specifies allocated pixels
3826c321187Smrg      * npixels	- specifies count of alloc'd pixels
3836c321187Smrg      * ncolors - specifies needed sequence length
3846c321187Smrg      * delta	- between pixels
3856c321187Smrg      * first	- returns first index of sequence
3866c321187Smrg      * rem	- returns first index after sequence, or 0, if none follow
3876c321187Smrg      */
3886c321187Smrg{
3896c321187Smrg    register int i = 1;		/* walking index into the pixel array */
3906c321187Smrg    register int count = 1;	/* length of sequence discovered so far */
3916c321187Smrg
3926c321187Smrg    *first = 0;
3936c321187Smrg    if (npixels == ncolors) {
3946c321187Smrg	*rem = 0;
3956c321187Smrg	return 1;
3966c321187Smrg    }
3976c321187Smrg    *rem = npixels - 1;
3986c321187Smrg    while (count < ncolors && ncolors - count <= *rem)
3996c321187Smrg    {
4006c321187Smrg	if (pixels[i-1] + delta == pixels[i])
4016c321187Smrg	    count++;
4026c321187Smrg	else {
4036c321187Smrg	    count = 1;
4046c321187Smrg	    *first = i;
4056c321187Smrg	}
4066c321187Smrg	i++;
4076c321187Smrg	(*rem)--;
4086c321187Smrg    }
4096c321187Smrg    if (count != ncolors)
4106c321187Smrg	return 0;
4116c321187Smrg    return 1;
4126c321187Smrg}
4136c321187Smrg
4146c321187Smrg
4156c321187Smrg/****************************************************************************/
4166c321187Smrgstatic Status
4176c321187SmrgROorRWcell(Display *dpy, Colormap cmap, unsigned long pixels[],
4186c321187Smrg	   int npixels, XColor *color, unsigned long p)
4196c321187Smrg{
4206c321187Smrg    unsigned long	pixel;
4216c321187Smrg    XColor		request;
4226c321187Smrg
4236c321187Smrg    /* Free the read/write allocation of one cell in the colormap.
4246c321187Smrg     * Request a read only allocation of one cell in the colormap.
4256c321187Smrg     * If the read only allocation cannot be granted, give up, because
4266c321187Smrg     * there must be no free cells in the colormap.
4276c321187Smrg     * If the read only allocation is granted, but gives us a cell which
4286c321187Smrg     * is not the one that we just freed, it is probably the case that
4296c321187Smrg     * we are trying allocate White or Black or some other color which
4306c321187Smrg     * already has a read-only allocation in the map.  So we try to
4316c321187Smrg     * allocate the previously freed cell with a read/write allocation,
4326c321187Smrg     * because we want contiguous cells for image processing algorithms.
4336c321187Smrg     */
4346c321187Smrg
4356c321187Smrg    pixel = color->pixel;
4366c321187Smrg    request.red = color->red;
4376c321187Smrg    request.green = color->green;
4386c321187Smrg    request.blue = color->blue;
4396c321187Smrg
4406c321187Smrg    XFreeColors(dpy, cmap, &pixel, 1, (unsigned long) 0);
4416c321187Smrg    if (! XAllocColor(dpy, cmap, color)
4426c321187Smrg	|| (color->pixel != pixel &&
4436c321187Smrg	    (!RWcell(dpy, cmap, color, &request, &pixel))))
4446c321187Smrg    {
4456c321187Smrg	free_cells(dpy, cmap, pixels, npixels, (int)p);
4466c321187Smrg	return 0;
4476c321187Smrg    }
4486c321187Smrg    return 1;
4496c321187Smrg}
4506c321187Smrg
4516c321187Smrg
4526c321187Smrg/****************************************************************************/
4536c321187Smrgstatic void
4546c321187Smrgfree_cells(Display *dpy, Colormap cmap, unsigned long pixels[],
4556c321187Smrg	   int npixels, int p)
4566c321187Smrg     /*
4576c321187Smrg      * pixels	- to be freed
4586c321187Smrg      *	npixels	- original number allocated
4596c321187Smrg      */
4606c321187Smrg{
4616c321187Smrg    /* One of the npixels allocated has already been freed.
4626c321187Smrg     * p is the index of the freed pixel.
4636c321187Smrg     * First free the pixels preceeding p, and there are p of them;
4646c321187Smrg     * then free the pixels following p, there are npixels - p - 1 of them.
4656c321187Smrg     */
4666c321187Smrg    XFreeColors(dpy, cmap, pixels, p, (unsigned long) 0);
4676c321187Smrg    XFreeColors(dpy, cmap, &(pixels[p+1]), npixels - p - 1, (unsigned long) 0);
4686c321187Smrg    free((char *) pixels);
4696c321187Smrg}
4706c321187Smrg
4716c321187Smrg
4726c321187Smrg/****************************************************************************/
4736c321187Smrgstatic Status
4746c321187SmrgRWcell(Display *dpy, Colormap cmap, XColor *color, XColor *request,
4756c321187Smrg       unsigned long *pixel)
4766c321187Smrg{
4776c321187Smrg    unsigned long	n = *pixel;
4786c321187Smrg
4796c321187Smrg    XFreeColors(dpy, cmap, &(color->pixel), 1, (unsigned long)0);
4806c321187Smrg    if (! XAllocColorCells(dpy, cmap, (Bool) 0, (unsigned long *) NULL,
4816c321187Smrg			   (unsigned) 0, pixel, (unsigned) 1))
4826c321187Smrg	return 0;
4836c321187Smrg    if (*pixel != n)
4846c321187Smrg    {
4856c321187Smrg	XFreeColors(dpy, cmap, pixel, 1, (unsigned long) 0);
4866c321187Smrg	return 0;
4876c321187Smrg    }
4886c321187Smrg    color->pixel = *pixel;
4896c321187Smrg    color->flags = DoRed | DoGreen | DoBlue;
4906c321187Smrg    color->red = request->red;
4916c321187Smrg    color->green = request->green;
4926c321187Smrg    color->blue = request->blue;
4936c321187Smrg    XStoreColors(dpy, cmap, color, 1);
4946c321187Smrg    return 1;
4956c321187Smrg}
4966c321187Smrg
4976c321187Smrg
4986c321187Smrg/****************************************************************************/
4996c321187Smrgstatic int
5006c321187Smrgcompare(_Xconst void *e1, _Xconst void *e2)
5016c321187Smrg{
5026c321187Smrg  return ((int)(*(long *)e1 - *(long *)e2));
5036c321187Smrg}
5046c321187Smrg
5056c321187Smrg
5066c321187Smrg/****************************************************************************/
5076c321187Smrgstatic Status
5086c321187Smrgreadonly_map(Display *dpy, XVisualInfo *vinfo, XStandardColormap *colormap)
5096c321187Smrg{
5106c321187Smrg    int			i, last_pixel;
5116c321187Smrg    XColor		color;
5126c321187Smrg
5136c321187Smrg    last_pixel = (colormap->red_max + 1) * (colormap->green_max + 1) *
5146c321187Smrg	(colormap->blue_max + 1) + colormap->base_pixel - 1;
5156c321187Smrg
5166c321187Smrg    for(i=colormap->base_pixel; i <= last_pixel; i++) {
5176c321187Smrg
5186c321187Smrg	color.pixel = (unsigned long) i;
5196c321187Smrg	color.red = (unsigned short)
5206c321187Smrg	    (((i/colormap->red_mult) * 65535) / colormap->red_max);
5216c321187Smrg
5226c321187Smrg	if (vinfo->class == StaticColor) {
5236c321187Smrg	    color.green = (unsigned short)
5246c321187Smrg		((((i/colormap->green_mult) % (colormap->green_max + 1)) *
5256c321187Smrg		  65535) / colormap->green_max);
5266c321187Smrg	    color.blue = (unsigned short)
5276c321187Smrg		(((i%colormap->green_mult) * 65535) / colormap->blue_max);
5286c321187Smrg	}
5296c321187Smrg	else	/* vinfo->class == GrayScale, old style allocation XXX */
5306c321187Smrg	    color.green = color.blue = color.red;
5316c321187Smrg
5326c321187Smrg	XAllocColor(dpy, colormap->colormap, &color);
5336c321187Smrg	if (color.pixel != (unsigned long) i)
5346c321187Smrg	    return 0;
5356c321187Smrg    }
5366c321187Smrg    return 1;
5376c321187Smrg}
538