X-Git-Url: https://repo.or.cz/w/wmaker-crm.git/blobdiff_plain/59fc927dc9f183802621138534fa6eaafe5593ba..688a56e8ab67b56550e2874d9d7423f0d435bfd9:/wrlib/CrCmap.c diff --git a/wrlib/CrCmap.c b/wrlib/CrCmap.c dissimilarity index 79% index 9ac102f2..fca9d34e 100644 --- a/wrlib/CrCmap.c +++ b/wrlib/CrCmap.c @@ -1,525 +1,484 @@ -/* $XConsortium: CrCmap.c,v 1.6 94/04/17 20:15:53 rws Exp $ */ - -/* - -Copyright (c) 1989 X Consortium - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN -AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -Except as contained in this notice, the name of the X Consortium shall not be -used in advertising or otherwise to promote the sale, use or other dealings -in this Software without prior written authorization from the X Consortium. - -*/ - -/* - * Author: Donna Converse, MIT X Consortium - */ - -/* - * CreateCmap.c - given a standard colormap description, make the map. - */ - -#include -#include -#include -#include - - -static int ROmap(); /* allocate entire map Read Only */ -static Status ROorRWcell(); /* allocate a cell, prefer Read Only */ -static Status RWcell(); /* allocate a cell Read Write */ -static int compare(); /* for quicksort */ -static Status contiguous(); /* find contiguous sequence of cells */ -static void free_cells(); /* frees resources before quitting */ -static Status readonly_map(); /* create a map in a RO visual type */ -static Status readwrite_map(); /* create a map in a RW visual type */ - -#define lowbit(x) ((x) & (~(x) + 1)) -#define TRUEMATCH(mult,max,mask) \ - (colormap->max * colormap->mult <= vinfo->mask && \ - lowbit(vinfo->mask) == colormap->mult) - -/* - * To create any one colormap which is described by an XStandardColormap - * structure, use XmuCreateColormap(). - * - * Return 0 on failure, non-zero on success. - * Resources created by this function are not made permanent. - * No argument error checking is provided. Use at your own risk. - * - * All colormaps are created with read only allocations, with the exception - * of read only allocations of colors in the default map or otherwise - * which fail to return the expected pixel value, and these are individually - * defined as read/write allocations. This is done so that all the cells - * defined in the default map are contiguous, for use in image processing. - * This typically happens with White and Black in the default map. - * - * Colormaps of static visuals are considered to be successfully created if - * the map of the static visual matches the definition given in the - * standard colormap structure. - */ - -Status XmuCreateColormap(dpy, colormap) - Display *dpy; /* specifies the connection under - * which the map is created */ - XStandardColormap *colormap; /* specifies the map to be created, - * and returns, particularly if the - * map is created as a subset of the - * default colormap of the screen, - * the base_pixel of the map. - */ -{ - XVisualInfo vinfo_template; /* template visual information */ - XVisualInfo *vinfo; /* matching visual information */ - XVisualInfo *vpointer; /* for freeing the entire list */ - long vinfo_mask; /* specifies the visual mask value */ - int n; /* number of matching visuals */ - int status; - - vinfo_template.visualid = colormap->visualid; - vinfo_mask = VisualIDMask; - if ((vinfo = XGetVisualInfo(dpy, vinfo_mask, &vinfo_template, &n)) == NULL) - return 0; - - /* A visual id may be valid on multiple screens. Also, there may - * be multiple visuals with identical visual ids at different depths. - * If the colormap is the Default Colormap, use the Default Visual. - * Otherwise, arbitrarily, use the deepest visual. - */ - vpointer = vinfo; - if (n > 1) - { - register int i; - register int screen_number; - Bool def_cmap; - - def_cmap = False; - for (screen_number = ScreenCount(dpy); --screen_number >= 0; ) - if (colormap->colormap == DefaultColormap(dpy, screen_number)) { - def_cmap = True; - break; - } - - if (def_cmap) { - for (i=0; i < n; i++, vinfo++) { - if (vinfo->visual == DefaultVisual(dpy, screen_number)) - break; - } - } else { - unsigned int maxdepth = 0; - XVisualInfo *v = vinfo; - - for (i=0; i < n; i++, vinfo++) - if (vinfo->depth > maxdepth) { - maxdepth = vinfo->depth; - v = vinfo; - } - vinfo = v; - } - } - - if (vinfo->class == PseudoColor || vinfo->class == DirectColor || - vinfo->class == GrayScale) - status = readwrite_map(dpy, vinfo, colormap); - else if (vinfo->class == TrueColor) - status = TRUEMATCH(red_mult, red_max, red_mask) && - TRUEMATCH(green_mult, green_max, green_mask) && - TRUEMATCH(blue_mult, blue_max, blue_mask); - else - status = readonly_map(dpy, vinfo, colormap); - - XFree((char *) vpointer); - return status; -} - -/****************************************************************************/ -static Status readwrite_map(dpy, vinfo, colormap) - Display *dpy; - XVisualInfo *vinfo; - XStandardColormap *colormap; -{ - register unsigned long i, n; /* index counters */ - int ncolors; /* number of colors to be defined */ - int npixels; /* number of pixels allocated R/W */ - int first_index; /* first index of pixels to use */ - int remainder; /* first index of remainder */ - XColor color; /* the definition of a color */ - unsigned long *pixels; /* array of colormap pixels */ - unsigned long delta; - - - /* Determine ncolors, the number of colors to be defined. - * Insure that 1 < ncolors <= the colormap size. - */ - if (vinfo->class == DirectColor) { - ncolors = colormap->red_max; - if (colormap->green_max > ncolors) - ncolors = colormap->green_max; - if (colormap->blue_max > ncolors) - ncolors = colormap->blue_max; - ncolors++; - delta = lowbit(vinfo->red_mask) + - lowbit(vinfo->green_mask) + - lowbit(vinfo->blue_mask); - } else { - ncolors = colormap->red_max * colormap->red_mult + - colormap->green_max * colormap->green_mult + - colormap->blue_max * colormap->blue_mult + 1; - delta = 1; - } - if (ncolors <= 1 || ncolors > vinfo->colormap_size) return 0; - - /* Allocate Read/Write as much of the colormap as we can possibly get. - * Then insure that the pixels we were allocated are given in - * monotonically increasing order, using a quicksort. Next, insure - * that our allocation includes a subset of contiguous pixels at least - * as long as the number of colors to be defined. Now we know that - * these conditions are met: - * 1) There are no free cells in the colormap. - * 2) We have a contiguous sequence of pixels, monotonically - * increasing, of length >= the number of colors requested. - * - * One cell at a time, we will free, compute the next color value, - * then allocate read only. This takes a long time. - * This is done to insure that cells are allocated read only in the - * contiguous order which we prefer. If the server has a choice of - * cells to grant to an allocation request, the server may give us any - * cell, so that is why we do these slow gymnastics. - */ - - if ((pixels = (unsigned long *) calloc((unsigned) vinfo->colormap_size, - sizeof(unsigned long))) == NULL) - return 0; - - if ((npixels = ROmap(dpy, colormap->colormap, pixels, - vinfo->colormap_size, ncolors)) == 0) { - free((char *) pixels); - return 0; - } - - qsort((char *) pixels, npixels, sizeof(unsigned long), compare); - - if (!contiguous(pixels, npixels, ncolors, delta, &first_index, &remainder)) - { - /* can't find enough contiguous cells, give up */ - XFreeColors(dpy, colormap->colormap, pixels, npixels, - (unsigned long) 0); - free((char *) pixels); - return 0; - } - colormap->base_pixel = pixels[first_index]; - - /* construct a gray map */ - if (colormap->red_mult == 1 && colormap->green_mult == 1 && - colormap->blue_mult == 1) - for (n=colormap->base_pixel, i=0; i < ncolors; i++, n += delta) - { - color.pixel = n; - color.blue = color.green = color.red = - (unsigned short) ((i * 65535) / (colormap->red_max + - colormap->green_max + - colormap->blue_max)); - - if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color, - first_index + i)) - return 0; - } - - /* construct a red ramp map */ - else if (colormap->green_max == 0 && colormap->blue_max == 0) - for (n=colormap->base_pixel, i=0; i < ncolors; i++, n += delta) - { - color.pixel = n; - color.red = (unsigned short) ((i * 65535) / colormap->red_max); - color.green = color.blue = 0; - - if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color, - first_index + i)) - return 0; - } - - /* construct a green ramp map */ - else if (colormap->red_max == 0 && colormap->blue_max == 0) - for (n=colormap->base_pixel, i=0; i < ncolors; i++, n += delta) - { - color.pixel = n; - color.green = (unsigned short) ((i * 65535) / colormap->green_max); - color.red = color.blue = 0; - - if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color, - first_index + i)) - return 0; - } - - /* construct a blue ramp map */ - else if (colormap->red_max == 0 && colormap->green_max == 0) - for (n=colormap->base_pixel, i=0; i < ncolors; i++, n += delta) - { - color.pixel = n; - color.blue = (unsigned short) ((i * 65535) / colormap->blue_max); - color.red = color.green = 0; - - if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color, - first_index + i)) - return 0; - } - - /* construct a standard red green blue cube map */ - else - { -#define calc(max,mult) (((n / colormap->mult) % \ - (colormap->max + 1)) * 65535) / colormap->max - - for (n=0, i=0; i < ncolors; i++, n += delta) - { - color.pixel = n + colormap->base_pixel; - color.red = calc(red_max, red_mult); - color.green = calc(green_max, green_mult); - color.blue = calc(blue_max, blue_mult); - if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color, - first_index + i)) - return 0; - } -#undef calc - } - /* We have a read-only map defined. Now free unused cells, - * first those occuring before the contiguous sequence begins, - * then any following the contiguous sequence. - */ - - if (first_index) - XFreeColors(dpy, colormap->colormap, pixels, first_index, - (unsigned long) 0); - if (remainder) - XFreeColors(dpy, colormap->colormap, - &(pixels[first_index + ncolors]), remainder, - (unsigned long) 0); - - free((char *) pixels); - return 1; -} - - -/****************************************************************************/ -static int ROmap(dpy, cmap, pixels, m, n) - Display *dpy; /* the X server connection */ - Colormap cmap; /* specifies colormap ID */ - unsigned long pixels[]; /* returns pixel allocations */ - int m; /* specifies colormap size */ - int n; /* specifies number of colors */ -{ - register int p; - - /* first try to allocate the entire colormap */ - if (XAllocColorCells(dpy, cmap, 1, (unsigned long *) NULL, - (unsigned) 0, pixels, (unsigned) m)) - return m; - - /* Allocate all available cells in the colormap, using a binary - * algorithm to discover how many cells we can allocate in the colormap. - */ - m--; - while (n <= m) { - p = n + ((m - n + 1) / 2); - if (XAllocColorCells(dpy, cmap, 1, (unsigned long *) NULL, - (unsigned) 0, pixels, (unsigned) p)) { - if (p == m) - return p; - else { - XFreeColors(dpy, cmap, pixels, p, (unsigned long) 0); - n = p; - } - } - else - m = p - 1; - } - return 0; -} - - -/****************************************************************************/ -static Status contiguous(pixels, npixels, ncolors, delta, first, rem) - unsigned long pixels[]; /* specifies allocated pixels */ - int npixels; /* specifies count of alloc'd pixels */ - int ncolors; /* specifies needed sequence length */ - unsigned long delta; /* between pixels */ - int *first; /* returns first index of sequence */ - int *rem; /* returns first index after sequence, - * or 0, if none follow */ -{ - register int i = 1; /* walking index into the pixel array */ - register int count = 1; /* length of sequence discovered so far */ - - *first = 0; - if (npixels == ncolors) { - *rem = 0; - return 1; - } - *rem = npixels - 1; - while (count < ncolors && ncolors - count <= *rem) - { - if (pixels[i-1] + delta == pixels[i]) - count++; - else { - count = 1; - *first = i; - } - i++; - (*rem)--; - } - if (count != ncolors) - return 0; - return 1; -} - - -/****************************************************************************/ -static Status ROorRWcell(dpy, cmap, pixels, npixels, color, p) - Display *dpy; - Colormap cmap; - unsigned long pixels[]; - int npixels; - XColor *color; - unsigned long p; -{ - unsigned long pixel; - XColor request; - - /* Free the read/write allocation of one cell in the colormap. - * Request a read only allocation of one cell in the colormap. - * If the read only allocation cannot be granted, give up, because - * there must be no free cells in the colormap. - * If the read only allocation is granted, but gives us a cell which - * is not the one that we just freed, it is probably the case that - * we are trying allocate White or Black or some other color which - * already has a read-only allocation in the map. So we try to - * allocate the previously freed cell with a read/write allocation, - * because we want contiguous cells for image processing algorithms. - */ - - pixel = color->pixel; - request.red = color->red; - request.green = color->green; - request.blue = color->blue; - - XFreeColors(dpy, cmap, &pixel, 1, (unsigned long) 0); - if (! XAllocColor(dpy, cmap, color) - || (color->pixel != pixel && - (!RWcell(dpy, cmap, color, &request, &pixel)))) - { - free_cells(dpy, cmap, pixels, npixels, (int)p); - return 0; - } - return 1; -} - - -/****************************************************************************/ -static void free_cells(dpy, cmap, pixels, npixels, p) - Display *dpy; - Colormap cmap; - unsigned long pixels[]; /* to be freed */ - int npixels; /* original number allocated */ - int p; -{ - /* One of the npixels allocated has already been freed. - * p is the index of the freed pixel. - * First free the pixels preceeding p, and there are p of them; - * then free the pixels following p, there are npixels - p - 1 of them. - */ - XFreeColors(dpy, cmap, pixels, p, (unsigned long) 0); - XFreeColors(dpy, cmap, &(pixels[p+1]), npixels - p - 1, (unsigned long) 0); - free((char *) pixels); -} - - -/****************************************************************************/ -static Status RWcell(dpy, cmap, color, request, pixel) - Display *dpy; - Colormap cmap; - XColor *color; - XColor *request; - unsigned long *pixel; -{ - unsigned long n = *pixel; - - XFreeColors(dpy, cmap, &(color->pixel), 1, (unsigned long)0); - if (! XAllocColorCells(dpy, cmap, (Bool) 0, (unsigned long *) NULL, - (unsigned) 0, pixel, (unsigned) 1)) - return 0; - if (*pixel != n) - { - XFreeColors(dpy, cmap, pixel, 1, (unsigned long) 0); - return 0; - } - color->pixel = *pixel; - color->flags = DoRed | DoGreen | DoBlue; - color->red = request->red; - color->green = request->green; - color->blue = request->blue; - XStoreColors(dpy, cmap, color, 1); - return 1; -} - - -/****************************************************************************/ -static int compare(e1, e2) - unsigned long *e1, *e2; -{ - if (*e1 < *e2) return -1; - if (*e1 > *e2) return 1; - return 0; -} - - -/****************************************************************************/ -static Status readonly_map(dpy, vinfo, colormap) - Display *dpy; - XVisualInfo *vinfo; - XStandardColormap *colormap; -{ - int i, last_pixel; - XColor color; - - last_pixel = (colormap->red_max + 1) * (colormap->green_max + 1) * - (colormap->blue_max + 1) + colormap->base_pixel - 1; - - for(i=colormap->base_pixel; i <= last_pixel; i++) { - - color.pixel = (unsigned long) i; - color.red = (unsigned short) - (((i/colormap->red_mult) * 65535) / colormap->red_max); - - if (vinfo->class == StaticColor) { - color.green = (unsigned short) - ((((i/colormap->green_mult) % (colormap->green_max + 1)) * - 65535) / colormap->green_max); - color.blue = (unsigned short) - (((i%colormap->green_mult) * 65535) / colormap->blue_max); - } - else /* vinfo->class == GrayScale, old style allocation XXX */ - color.green = color.blue = color.red; - - XAllocColor(dpy, colormap->colormap, &color); - if (color.pixel != (unsigned long) i) - return 0; - } - return 1; -} - +/* $XConsortium: CrCmap.c,v 1.6 94/04/17 20:15:53 rws Exp $ */ + +/* + +Copyright (c) 1989 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + +*/ + +/* + * Author: Donna Converse, MIT X Consortium + */ + +/* + * CreateCmap.c - given a standard colormap description, make the map. + */ + +#include +#include +#include +#include + +static int ROmap(); /* allocate entire map Read Only */ +static Status ROorRWcell(); /* allocate a cell, prefer Read Only */ +static Status RWcell(); /* allocate a cell Read Write */ +static int compare(); /* for quicksort */ +static Status contiguous(); /* find contiguous sequence of cells */ +static void free_cells(); /* frees resources before quitting */ +static Status readonly_map(); /* create a map in a RO visual type */ +static Status readwrite_map(); /* create a map in a RW visual type */ + +#define lowbit(x) ((x) & (~(x) + 1)) +#define TRUEMATCH(mult,max,mask) \ + (colormap->max * colormap->mult <= vinfo->mask && \ + lowbit(vinfo->mask) == colormap->mult) + +/* + * To create any one colormap which is described by an XStandardColormap + * structure, use XmuCreateColormap(). + * + * Return 0 on failure, non-zero on success. + * Resources created by this function are not made permanent. + * No argument error checking is provided. Use at your own risk. + * + * All colormaps are created with read only allocations, with the exception + * of read only allocations of colors in the default map or otherwise + * which fail to return the expected pixel value, and these are individually + * defined as read/write allocations. This is done so that all the cells + * defined in the default map are contiguous, for use in image processing. + * This typically happens with White and Black in the default map. + * + * Colormaps of static visuals are considered to be successfully created if + * the map of the static visual matches the definition given in the + * standard colormap structure. + */ + +Status XmuCreateColormap(dpy, colormap) +Display *dpy; /* specifies the connection under + * which the map is created */ +XStandardColormap *colormap; /* specifies the map to be created, + * and returns, particularly if the + * map is created as a subset of the + * default colormap of the screen, + * the base_pixel of the map. + */ +{ + XVisualInfo vinfo_template; /* template visual information */ + XVisualInfo *vinfo; /* matching visual information */ + XVisualInfo *vpointer; /* for freeing the entire list */ + long vinfo_mask; /* specifies the visual mask value */ + int n; /* number of matching visuals */ + int status; + + vinfo_template.visualid = colormap->visualid; + vinfo_mask = VisualIDMask; + if ((vinfo = XGetVisualInfo(dpy, vinfo_mask, &vinfo_template, &n)) == NULL) + return 0; + + /* A visual id may be valid on multiple screens. Also, there may + * be multiple visuals with identical visual ids at different depths. + * If the colormap is the Default Colormap, use the Default Visual. + * Otherwise, arbitrarily, use the deepest visual. + */ + vpointer = vinfo; + if (n > 1) { + register int i; + register int screen_number; + Bool def_cmap; + + def_cmap = False; + for (screen_number = ScreenCount(dpy); --screen_number >= 0;) + if (colormap->colormap == DefaultColormap(dpy, screen_number)) { + def_cmap = True; + break; + } + + if (def_cmap) { + for (i = 0; i < n; i++, vinfo++) { + if (vinfo->visual == DefaultVisual(dpy, screen_number)) + break; + } + } else { + unsigned int maxdepth = 0; + XVisualInfo *v = vinfo; + + for (i = 0; i < n; i++, vinfo++) + if (vinfo->depth > maxdepth) { + maxdepth = vinfo->depth; + v = vinfo; + } + vinfo = v; + } + } + + if (vinfo->class == PseudoColor || vinfo->class == DirectColor || vinfo->class == GrayScale) + status = readwrite_map(dpy, vinfo, colormap); + else if (vinfo->class == TrueColor) + status = TRUEMATCH(red_mult, red_max, red_mask) && + TRUEMATCH(green_mult, green_max, green_mask) && TRUEMATCH(blue_mult, blue_max, blue_mask); + else + status = readonly_map(dpy, vinfo, colormap); + + XFree((char *)vpointer); + return status; +} + +/****************************************************************************/ +static Status readwrite_map(dpy, vinfo, colormap) +Display *dpy; +XVisualInfo *vinfo; +XStandardColormap *colormap; +{ + register unsigned long i, n; /* index counters */ + int ncolors; /* number of colors to be defined */ + int npixels; /* number of pixels allocated R/W */ + int first_index; /* first index of pixels to use */ + int remainder; /* first index of remainder */ + XColor color; /* the definition of a color */ + unsigned long *pixels; /* array of colormap pixels */ + unsigned long delta; + + /* Determine ncolors, the number of colors to be defined. + * Insure that 1 < ncolors <= the colormap size. + */ + if (vinfo->class == DirectColor) { + ncolors = colormap->red_max; + if (colormap->green_max > ncolors) + ncolors = colormap->green_max; + if (colormap->blue_max > ncolors) + ncolors = colormap->blue_max; + ncolors++; + delta = lowbit(vinfo->red_mask) + lowbit(vinfo->green_mask) + lowbit(vinfo->blue_mask); + } else { + ncolors = colormap->red_max * colormap->red_mult + + colormap->green_max * colormap->green_mult + colormap->blue_max * colormap->blue_mult + 1; + delta = 1; + } + if (ncolors <= 1 || ncolors > vinfo->colormap_size) + return 0; + + /* Allocate Read/Write as much of the colormap as we can possibly get. + * Then insure that the pixels we were allocated are given in + * monotonically increasing order, using a quicksort. Next, insure + * that our allocation includes a subset of contiguous pixels at least + * as long as the number of colors to be defined. Now we know that + * these conditions are met: + * 1) There are no free cells in the colormap. + * 2) We have a contiguous sequence of pixels, monotonically + * increasing, of length >= the number of colors requested. + * + * One cell at a time, we will free, compute the next color value, + * then allocate read only. This takes a long time. + * This is done to insure that cells are allocated read only in the + * contiguous order which we prefer. If the server has a choice of + * cells to grant to an allocation request, the server may give us any + * cell, so that is why we do these slow gymnastics. + */ + + if ((pixels = (unsigned long *)calloc((unsigned)vinfo->colormap_size, sizeof(unsigned long))) == NULL) + return 0; + + if ((npixels = ROmap(dpy, colormap->colormap, pixels, vinfo->colormap_size, ncolors)) == 0) { + free((char *)pixels); + return 0; + } + + qsort((char *)pixels, npixels, sizeof(unsigned long), compare); + + if (!contiguous(pixels, npixels, ncolors, delta, &first_index, &remainder)) { + /* can't find enough contiguous cells, give up */ + XFreeColors(dpy, colormap->colormap, pixels, npixels, (unsigned long)0); + free((char *)pixels); + return 0; + } + colormap->base_pixel = pixels[first_index]; + + /* construct a gray map */ + if (colormap->red_mult == 1 && colormap->green_mult == 1 && colormap->blue_mult == 1) + for (n = colormap->base_pixel, i = 0; i < ncolors; i++, n += delta) { + color.pixel = n; + color.blue = color.green = color.red = + (unsigned short)((i * 65535) / (colormap->red_max + + colormap->green_max + colormap->blue_max)); + + if (!ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color, first_index + i)) + return 0; + } + + /* construct a red ramp map */ + else if (colormap->green_max == 0 && colormap->blue_max == 0) + for (n = colormap->base_pixel, i = 0; i < ncolors; i++, n += delta) { + color.pixel = n; + color.red = (unsigned short)((i * 65535) / colormap->red_max); + color.green = color.blue = 0; + + if (!ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color, first_index + i)) + return 0; + } + + /* construct a green ramp map */ + else if (colormap->red_max == 0 && colormap->blue_max == 0) + for (n = colormap->base_pixel, i = 0; i < ncolors; i++, n += delta) { + color.pixel = n; + color.green = (unsigned short)((i * 65535) / colormap->green_max); + color.red = color.blue = 0; + + if (!ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color, first_index + i)) + return 0; + } + + /* construct a blue ramp map */ + else if (colormap->red_max == 0 && colormap->green_max == 0) + for (n = colormap->base_pixel, i = 0; i < ncolors; i++, n += delta) { + color.pixel = n; + color.blue = (unsigned short)((i * 65535) / colormap->blue_max); + color.red = color.green = 0; + + if (!ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color, first_index + i)) + return 0; + } + + /* construct a standard red green blue cube map */ + else { +#define calc(max,mult) (((n / colormap->mult) % \ + (colormap->max + 1)) * 65535) / colormap->max + + for (n = 0, i = 0; i < ncolors; i++, n += delta) { + color.pixel = n + colormap->base_pixel; + color.red = calc(red_max, red_mult); + color.green = calc(green_max, green_mult); + color.blue = calc(blue_max, blue_mult); + if (!ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color, first_index + i)) + return 0; + } +#undef calc + } + /* We have a read-only map defined. Now free unused cells, + * first those occuring before the contiguous sequence begins, + * then any following the contiguous sequence. + */ + + if (first_index) + XFreeColors(dpy, colormap->colormap, pixels, first_index, (unsigned long)0); + if (remainder) + XFreeColors(dpy, colormap->colormap, + &(pixels[first_index + ncolors]), remainder, (unsigned long)0); + + free((char *)pixels); + return 1; +} + +/****************************************************************************/ +static int ROmap(dpy, cmap, pixels, m, n) +Display *dpy; /* the X server connection */ +Colormap cmap; /* specifies colormap ID */ +unsigned long pixels[]; /* returns pixel allocations */ +int m; /* specifies colormap size */ +int n; /* specifies number of colors */ +{ + register int p; + + /* first try to allocate the entire colormap */ + if (XAllocColorCells(dpy, cmap, 1, (unsigned long *)NULL, (unsigned)0, pixels, (unsigned)m)) + return m; + + /* Allocate all available cells in the colormap, using a binary + * algorithm to discover how many cells we can allocate in the colormap. + */ + m--; + while (n <= m) { + p = n + ((m - n + 1) / 2); + if (XAllocColorCells(dpy, cmap, 1, (unsigned long *)NULL, (unsigned)0, pixels, (unsigned)p)) { + if (p == m) + return p; + else { + XFreeColors(dpy, cmap, pixels, p, (unsigned long)0); + n = p; + } + } else + m = p - 1; + } + return 0; +} + +/****************************************************************************/ +static Status contiguous(pixels, npixels, ncolors, delta, first, rem) +unsigned long pixels[]; /* specifies allocated pixels */ +int npixels; /* specifies count of alloc'd pixels */ +int ncolors; /* specifies needed sequence length */ +unsigned long delta; /* between pixels */ +int *first; /* returns first index of sequence */ +int *rem; /* returns first index after sequence, + * or 0, if none follow */ +{ + register int i = 1; /* walking index into the pixel array */ + register int count = 1; /* length of sequence discovered so far */ + + *first = 0; + if (npixels == ncolors) { + *rem = 0; + return 1; + } + *rem = npixels - 1; + while (count < ncolors && ncolors - count <= *rem) { + if (pixels[i - 1] + delta == pixels[i]) + count++; + else { + count = 1; + *first = i; + } + i++; + (*rem)--; + } + if (count != ncolors) + return 0; + return 1; +} + +/****************************************************************************/ +static Status ROorRWcell(dpy, cmap, pixels, npixels, color, p) +Display *dpy; +Colormap cmap; +unsigned long pixels[]; +int npixels; +XColor *color; +unsigned long p; +{ + unsigned long pixel; + XColor request; + + /* Free the read/write allocation of one cell in the colormap. + * Request a read only allocation of one cell in the colormap. + * If the read only allocation cannot be granted, give up, because + * there must be no free cells in the colormap. + * If the read only allocation is granted, but gives us a cell which + * is not the one that we just freed, it is probably the case that + * we are trying allocate White or Black or some other color which + * already has a read-only allocation in the map. So we try to + * allocate the previously freed cell with a read/write allocation, + * because we want contiguous cells for image processing algorithms. + */ + + pixel = color->pixel; + request.red = color->red; + request.green = color->green; + request.blue = color->blue; + + XFreeColors(dpy, cmap, &pixel, 1, (unsigned long)0); + if (!XAllocColor(dpy, cmap, color) + || (color->pixel != pixel && (!RWcell(dpy, cmap, color, &request, &pixel)))) { + free_cells(dpy, cmap, pixels, npixels, (int)p); + return 0; + } + return 1; +} + +/****************************************************************************/ +static void free_cells(dpy, cmap, pixels, npixels, p) +Display *dpy; +Colormap cmap; +unsigned long pixels[]; /* to be freed */ +int npixels; /* original number allocated */ +int p; +{ + /* One of the npixels allocated has already been freed. + * p is the index of the freed pixel. + * First free the pixels preceeding p, and there are p of them; + * then free the pixels following p, there are npixels - p - 1 of them. + */ + XFreeColors(dpy, cmap, pixels, p, (unsigned long)0); + XFreeColors(dpy, cmap, &(pixels[p + 1]), npixels - p - 1, (unsigned long)0); + free((char *)pixels); +} + +/****************************************************************************/ +static Status RWcell(dpy, cmap, color, request, pixel) +Display *dpy; +Colormap cmap; +XColor *color; +XColor *request; +unsigned long *pixel; +{ + unsigned long n = *pixel; + + XFreeColors(dpy, cmap, &(color->pixel), 1, (unsigned long)0); + if (!XAllocColorCells(dpy, cmap, (Bool) 0, (unsigned long *)NULL, (unsigned)0, pixel, (unsigned)1)) + return 0; + if (*pixel != n) { + XFreeColors(dpy, cmap, pixel, 1, (unsigned long)0); + return 0; + } + color->pixel = *pixel; + color->flags = DoRed | DoGreen | DoBlue; + color->red = request->red; + color->green = request->green; + color->blue = request->blue; + XStoreColors(dpy, cmap, color, 1); + return 1; +} + +/****************************************************************************/ +static int compare(e1, e2) +unsigned long *e1, *e2; +{ + if (*e1 < *e2) + return -1; + if (*e1 > *e2) + return 1; + return 0; +} + +/****************************************************************************/ +static Status readonly_map(dpy, vinfo, colormap) +Display *dpy; +XVisualInfo *vinfo; +XStandardColormap *colormap; +{ + int i, last_pixel; + XColor color; + + last_pixel = (colormap->red_max + 1) * (colormap->green_max + 1) * + (colormap->blue_max + 1) + colormap->base_pixel - 1; + + for (i = colormap->base_pixel; i <= last_pixel; i++) { + + color.pixel = (unsigned long)i; + color.red = (unsigned short) + (((i / colormap->red_mult) * 65535) / colormap->red_max); + + if (vinfo->class == StaticColor) { + color.green = (unsigned short) + ((((i / colormap->green_mult) % (colormap->green_max + 1)) * + 65535) / colormap->green_max); + color.blue = (unsigned short) + (((i % colormap->green_mult) * 65535) / colormap->blue_max); + } else /* vinfo->class == GrayScale, old style allocation XXX */ + color.green = color.blue = color.red; + + XAllocColor(dpy, colormap->colormap, &color); + if (color.pixel != (unsigned long)i) + return 0; + } + return 1; +}