aboutsummaryrefslogtreecommitdiff
path: root/nx-X11/lib/dps/dpsXcmu.c
diff options
context:
space:
mode:
Diffstat (limited to 'nx-X11/lib/dps/dpsXcmu.c')
-rw-r--r--nx-X11/lib/dps/dpsXcmu.c1602
1 files changed, 0 insertions, 1602 deletions
diff --git a/nx-X11/lib/dps/dpsXcmu.c b/nx-X11/lib/dps/dpsXcmu.c
deleted file mode 100644
index 502649d51..000000000
--- a/nx-X11/lib/dps/dpsXcmu.c
+++ /dev/null
@@ -1,1602 +0,0 @@
-/*
- * dpsXcmu.c -- Simple color management/allocation utility
- *
- * (c) Copyright 1988-1994 Adobe Systems Incorporated.
- * All rights reserved.
- *
- * Permission to use, copy, modify, distribute, and sublicense this software
- * and its documentation for any purpose and without fee is hereby granted,
- * provided that the above copyright notices appear in all copies and that
- * both those copyright notices and this permission notice appear in
- * supporting documentation and that the name of Adobe Systems Incorporated
- * not be used in advertising or publicity pertaining to distribution of the
- * software without specific, written prior permission. No trademark license
- * to use the Adobe trademarks is hereby granted. If the Adobe trademark
- * "Display PostScript"(tm) is used to describe this software, its
- * functionality or for any other purpose, such use shall be limited to a
- * statement that this software works in conjunction with the Display
- * PostScript system. Proper trademark attribution to reflect Adobe's
- * ownership of the trademark shall be given whenever any such reference to
- * the Display PostScript system is made.
- *
- * ADOBE MAKES NO REPRESENTATIONS ABOUT THE SUITABILITY OF THE SOFTWARE FOR
- * ANY PURPOSE. IT IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY.
- * ADOBE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
- * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NON- INFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT SHALL ADOBE BE LIABLE
- * TO YOU OR ANY OTHER PARTY FOR ANY SPECIAL, INDIRECT, OR CONSEQUENTIAL
- * DAMAGES OR ANY DAMAGES WHATSOEVER WHETHER IN AN ACTION OF CONTRACT,
- * NEGLIGENCE, STRICT LIABILITY OR ANY OTHER ACTION ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ADOBE WILL NOT
- * PROVIDE ANY TRAINING OR OTHER SUPPORT FOR THE SOFTWARE.
- *
- * Adobe, PostScript, and Display PostScript are trademarks of Adobe Systems
- * Incorporated which may be registered in certain jurisdictions
- *
- * Portions Copyright 1989 by the Massachusetts Institute of Technology
- *
- * Permission to use, copy, modify, and distribute this software and its
- * documentation for any purpose and without fee is hereby granted, provided
- * that the above copyright notice appear in all copies and that both that
- * copyright notice and this permission notice appear in supporting
- * documentation, and that the name of M.I.T. not be used in advertising
- * or publicity pertaining to distribution of the software without specific,
- * written prior permission. M.I.T. makes no representations about the
- * suitability of this software for any purpose. It is provided "as is"
- * without express or implied warranty.
- *
- * M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL M.I.T.
- * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- *
- * Author: Adobe Systems Incorporated and Donna Converse, MIT X Consortium
- */
-/* $XFree86: xc/lib/dps/dpsXcmu.c,v 1.4 2000/09/26 15:56:59 tsi Exp $ */
-
-#include <X11/X.h>
-#include <X11/Xlib.h>
-#include <X11/Xutil.h>
-#include <X11/Xatom.h>
-#include <X11/Xresource.h>
-#include <X11/Xos.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <pwd.h>
-
-#include "dpsassert.h"
-#include "cslibint.h"
-
-/* Defines for standard colormap routines */
-
-#define PrivSort qsort
-#include <stddef.h>
-
-static char redsName[] = "reds";
-static char greensName[] = "greens";
-static char bluesName[] = "blues";
-static char graysName[] = "grays";
-
-/* Database containing DPS default color cube values */
-
-typedef struct _dpyRec {
- Display *dpy;
- XrmDatabase db;
- Atom XA_GRAY_DEFAULT_MAP;
- struct _dpyRec *next;
-} DpyRec;
-
-static DpyRec *dpyRec = NULL;
-static DpyRec *curDpyRec;
-static DpyRec *FindDpyRec(Display *);
-
-typedef struct {
- unsigned long *pixels;
- int npixels;
-} PixelRec;
-
-static Bool AllocateColor(Display *, Colormap, XColor *);
-static Bool AllocateColormap(Display *, XStandardColormap *, XVisualInfo *, int *, PixelRec *, int *, int *, unsigned long);
-static Bool CheckCube(XColor *, XColor *, XStandardColormap *);
-static Bool CubicCube(XStandardColormap *);
-static Bool GetColorCubeFromProperty(Display *, XVisualInfo *, XStandardColormap *, XStandardColormap **, int *);
-static Bool GetGrayRampFromProperty(Display *, XVisualInfo *, XStandardColormap *, XStandardColormap **, int *);
-Status XDPSCreateStandardColormaps(Display *, Drawable, Visual *, int, int, int, int, XStandardColormap *, XStandardColormap *, Bool);
-static Status contiguous(unsigned long *, int, int *, unsigned long, int *, int *);
-static XVisualInfo *PickCorrectVisual(Display *, XVisualInfo *, int, Colormap);
-static int FindRampSize(XColor *, XColor *);
-static long NumColors(char *, char *, char *);
-static void AllocateColorCube(Display *, XVisualInfo *, XStandardColormap *, PixelRec *);
-static void AllocateGrayRamp(Display *, XVisualInfo *, XStandardColormap *, XStandardColormap *, PixelRec *);
-static void ColorValuesFromMask(unsigned long, unsigned long *, unsigned long *);
-static void CreateDefaultsDb(Display *);
-static void DefineProperty(Display *, XStandardColormap *, XVisualInfo *, XStandardColormap *, int, Atom);
-static void FindStaticColorCube(Display *, XVisualInfo *, XStandardColormap *);
-static void FindStaticGrayRamp(Display *, XVisualInfo *, XStandardColormap *, XStandardColormap *);
-static void GetDatabaseValues(Display *, XVisualInfo *, XStandardColormap *, XStandardColormap *);
-static void GetHomeDir(char *);
-static void SetRamp(XColor *, XColor *, int, int *, unsigned long *);
-static void ShrinkMapToFit(XStandardColormap *, int *, XVisualInfo *);
-static void UseGrayCorners(XStandardColormap *, XStandardColormap *);
-static void UseGrayDiagonal(XStandardColormap *, XStandardColormap *);
-
-#define SCALE 65535
-#undef ABS
-#define ABS(x) ((x) < 0 ? -(x) : (x))
-
-void XDPSGetDefaultColorMaps(
- Display *dpy,
- Screen *screen,
- Drawable drawable,
- XStandardColormap *colorCube,
- XStandardColormap *grayRamp)
-{
- Window root;
- Visual *visual;
- XStandardColormap g;
-
- /* If there is a screen specified, use it; otherwise use the drawable */
-
- if (screen == NULL) {
- if (drawable == None || ScreenCount(dpy) == 1) {
- root = DefaultRootWindow(dpy);
- screen = DefaultScreenOfDisplay(dpy);
- } else {
- /* Have to get the root for this drawable */
- int x, y;
- int i;
- unsigned int width, height, bwidth, depth;
- if (!XGetGeometry(dpy, drawable, &root, &x, &y, &width, &height,
- &bwidth, &depth)) root = DefaultRootWindow(dpy);
- for (i = 0;
- i < ScreenCount(dpy) && root != RootWindow(dpy, i);
- i++) {}
- screen = ScreenOfDisplay(dpy, i);
- }
- } else root = RootWindowOfScreen(screen);
-
- if (grayRamp == NULL) grayRamp = &g;
-
- visual = DefaultVisualOfScreen(screen);
- grayRamp->colormap = DefaultColormapOfScreen(screen);
- if (colorCube != NULL) colorCube->colormap = grayRamp->colormap;
-
- (void) XDPSCreateStandardColormaps(dpy, root, visual,
- 0, 0, 0, 0, colorCube, grayRamp, True);
-}
-
-Status XDPSCreateStandardColormaps(
- Display *dpy,
- Drawable drawable,
- Visual *visual,
- int reds, int greens, int blues, int grays,
- XStandardColormap *colorCube,
- XStandardColormap *grayRamp,
- Bool retain)
-{
- XVisualInfo vtemp, *vinfo;
- int nvis;
- XStandardColormap *propCube = NULL, *propRamp = NULL;
- int nPropCube = 0, nPropRamp = 0;
- Bool gotCube = False, gotRamp;
- PixelRec pixels;
-
- if (grayRamp == NULL) return 0;
- if (colorCube != NULL &&
- colorCube->colormap != grayRamp->colormap) return 0;
-
- if (dpy == NULL || (drawable == None && visual == NULL)) return 0;
-
- if (visual == NULL) {
- XWindowAttributes attr;
- if (XGetWindowAttributes(dpy, drawable, &attr) == 0) return 0;
- visual = attr.visual;
- }
-
- if (grayRamp->colormap == None && drawable == None) return 0;
-
- curDpyRec = FindDpyRec(dpy);
- if (curDpyRec == NULL) return 0;
-
- vtemp.visualid = XVisualIDFromVisual(visual);
- vinfo = XGetVisualInfo(dpy, VisualIDMask, &vtemp, &nvis);
- if (nvis == 0) return 0;
-
- if (nvis > 1) {
- vinfo = PickCorrectVisual(dpy, vinfo, nvis, grayRamp->colormap);
- }
- if (vinfo == NULL) return 0;
-
- if (grays <= 1) grayRamp->red_max = 0;
- else grayRamp->red_max = grays - 1;
-
- if (colorCube != NULL) {
- if (reds <= 1) colorCube->red_max = 0;
- else colorCube->red_max = reds - 1;
- if (greens <= 1) colorCube->green_max = 0;
- else colorCube->green_max = greens - 1;
- if (blues <= 1) colorCube->blue_max = 0;
- else colorCube->blue_max = blues - 1;
- }
-
- if ((vinfo->class == StaticGray || vinfo->class == GrayScale) &&
- colorCube != NULL) {
- /* Can't do a color cube in a gray visual! */
- colorCube->red_max = colorCube->green_max = colorCube->blue_max =
- colorCube->red_mult = colorCube->green_mult = colorCube->blue_mult =
- colorCube->base_pixel = 0;
- colorCube = NULL;
- }
-
- if (retain) {
- Display *newDpy = XOpenDisplay(XDisplayString(dpy));
- if (newDpy == NULL) retain = False;
- else dpy = newDpy;
- XGrabServer(dpy);
- }
-
- if (grayRamp->colormap == None) {
- grayRamp->colormap = XCreateColormap(dpy, drawable, vinfo->visual,
- AllocNone);
- if (colorCube != NULL) colorCube->colormap = grayRamp->colormap;
- }
-
- if (colorCube != NULL) {
- gotCube = GetColorCubeFromProperty(dpy, vinfo, colorCube,
- &propCube, &nPropCube);
- }
- gotRamp = GetGrayRampFromProperty(dpy, vinfo, grayRamp,
- &propRamp, &nPropRamp);
-
- if (!gotRamp || (colorCube != NULL && !gotCube)) {
- /* Couldn't find at least one thing we wanted, so let's look in the
- database */
-
- GetDatabaseValues(dpy, vinfo, colorCube, grayRamp);
-
- pixels.pixels = NULL;
- pixels.npixels = 0;
-
- if (colorCube != NULL) {
- if (colorCube->red_max != 0) {
- AllocateColorCube(dpy, vinfo, colorCube, &pixels);
- }
- if (colorCube->red_max == 0) {
- colorCube->green_max = colorCube->blue_max =
- colorCube->red_mult = colorCube->green_mult =
- colorCube->blue_mult = 0;
- }
- }
-
- if (grayRamp->red_max != 0) {
- AllocateGrayRamp(dpy, vinfo, grayRamp, colorCube, &pixels);
- }
-
- if (pixels.pixels != NULL) {
- if (pixels.npixels != 0) {
- XFreeColors(dpy, grayRamp->colormap,
- pixels.pixels, pixels.npixels, 0);
- }
- free((char *) pixels.pixels);
- }
-
- if (retain) {
- Pixmap p;
-
- /* Create something to put in killid field so the entries can
- be deleted sometime */
- p = XCreatePixmap(dpy, RootWindow(dpy, vinfo->screen), 1, 1, 1);
- if (colorCube != NULL && !gotCube && colorCube->red_max != 0) {
- colorCube->visualid = vinfo->visualid;
- colorCube->killid = p;
- DefineProperty(dpy, colorCube, vinfo, propCube, nPropCube,
- XA_RGB_DEFAULT_MAP);
- }
- if (!gotRamp && grayRamp->red_max != 0) {
- grayRamp->visualid = vinfo->visualid;
- grayRamp->killid = p;
- DefineProperty(dpy, grayRamp, vinfo, propRamp, nPropRamp,
- (vinfo->class == GrayScale ? XA_RGB_GRAY_MAP :
- curDpyRec->XA_GRAY_DEFAULT_MAP));
- }
- XSetCloseDownMode(dpy, RetainTemporary);
- }
- }
-
- if (grayRamp->red_max == 0) {
- /* Use special magic values. If this is a default colormap,
- the server recognizes a gray ramp with red_max=1, red_mult=1,
- base_pixel=0 to mean a 2 gray ramp with BlackPixel being
- the lowest intensity gray and WhitePixel being the highest
- intensity gray. If it's not a default colormap, then the
- server will either generate a BadValue error, or just happily
- use pixel values 0 and 1; either is better than the alternative,
- silently converting into a null device. */
- grayRamp->red_max = 1;
- grayRamp->red_mult = 1;
- grayRamp->base_pixel = 0;
- }
-
- if (retain) {
- XUngrabServer(dpy);
- XCloseDisplay(dpy);
- }
- if (propCube != NULL) XFree((void *) propCube);
- if (propRamp != NULL) XFree((void *) propRamp);
- XFree((void *) vinfo);
- return 1;
-}
-
-static DpyRec *FindDpyRec(Display *dpy)
-{
- DpyRec *d;
-
- for (d = dpyRec; d != NULL; d = d->next) {
- if (d->dpy == dpy) return d;
- }
-
- d = (DpyRec *) malloc(sizeof(DpyRec));
- if (d == NULL) return NULL;
- d->XA_GRAY_DEFAULT_MAP = XInternAtom(dpy, "DEFAULT_GRAY", False);
- d->db = NULL;
- d->next = dpyRec;
- dpyRec = d;
- return d;
-}
-
-static XVisualInfo *PickCorrectVisual(
- Display *dpy,
- XVisualInfo *vlist,
- int n,
- Colormap cmap)
-{
- register int i;
- register int screen_number;
- Bool def_cmap = False;
-
- /* 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.
- */
-
- for (screen_number = ScreenCount(dpy); --screen_number >= 0; /**/) {
- if (cmap == DefaultColormap(dpy, screen_number)) {
- def_cmap = True;
- break;
- }
- }
-
- if (def_cmap) {
- for (i = 0; i < n; i++, vlist++) {
- if (vlist->visual == DefaultVisual(dpy, screen_number)) {
- return vlist;
- }
- }
- return NULL; /* Visual does not match colormap */
- } else {
- int maxdepth = 0;
- XVisualInfo *v = 0;
-
- for (i = 0; i < n; i++, vlist++) {
- if (vlist->depth > maxdepth) {
- maxdepth = vlist->depth;
- v = vlist;
- }
- }
- return v;
- }
-}
-
-/* Do some rudimentary checking of the properties to avoid obviously bad ones.
- How did they get there, anyway? */
-
-static Bool ValidCube(
- XStandardColormap *c,
- XVisualInfo *vinfo)
-{
- unsigned long max = 1 << vinfo->depth;
- unsigned long pixel;
-
- if (c->red_max < 1 || c->green_max < 1 || c->blue_max < 1) return False;
- if (c->base_pixel > max) return False;
- pixel = (c->red_max * c->red_mult + c->green_max * c->green_mult +
- c->blue_max * c->blue_mult + c->base_pixel) & 0xFFFFFFFF;
- if (pixel > max) return False;
-
- return True;
-}
-
-static Bool ValidRamp(
- XStandardColormap *c,
- XVisualInfo *vinfo)
-{
- unsigned long max = 1 << vinfo->depth;
- unsigned long pixel;
-
- if (c->red_max < 1) return False;
- if (c->base_pixel > max) return False;
- pixel = (c->red_max * c->red_mult + c->base_pixel) & 0xFFFFFFFF;
- if (pixel > max) return False;
-
- return True;
-}
-
-static Bool GetColorCubeFromProperty(
- Display *dpy,
- XVisualInfo *vinfo,
- XStandardColormap *colorCube,
- XStandardColormap **cube,
- int *ncube)
-{
- int gotCube;
- int i;
- register XStandardColormap *c;
-
- gotCube = XGetRGBColormaps(dpy, RootWindow(dpy, vinfo->screen), cube,
- ncube, XA_RGB_DEFAULT_MAP);
-
- if (gotCube) {
- /* Try to find a match with the visual */
- c = *cube;
- for (i = 0; i < *ncube; i++) {
- if (c->colormap == colorCube->colormap &&
- c->visualid == vinfo->visualid &&
- ValidCube(c, vinfo)) {
- colorCube->red_max = c->red_max;
- colorCube->red_mult = c->red_mult;
- colorCube->green_max = c->green_max;
- colorCube->green_mult = c->green_mult;
- colorCube->blue_max = c->blue_max;
- colorCube->blue_mult = c->blue_mult;
- colorCube->base_pixel = c->base_pixel;
- colorCube->visualid = c->visualid;
- colorCube->killid = c->killid;
- break;
- }
- c++;
- }
- if (i == *ncube) gotCube = False;
- }
- return gotCube;
-}
-
-static Bool GetGrayRampFromProperty(
- Display *dpy,
- XVisualInfo *vinfo,
- XStandardColormap *grayRamp,
- XStandardColormap **ramp,
- int *nramp)
-{
- int gotRamp;
- int i;
- Atom grayAtom;
- register XStandardColormap *c;
-
- if (vinfo->class == GrayScale) grayAtom = XA_RGB_GRAY_MAP;
- else grayAtom = curDpyRec->XA_GRAY_DEFAULT_MAP;
-
- gotRamp = XGetRGBColormaps(dpy, RootWindow(dpy, vinfo->screen), ramp,
- nramp, grayAtom);
-
- if (gotRamp) {
- /* Try to find a match with the visual */
- c = *ramp;
- for (i = 0; i < *nramp; i++) {
- if (c->colormap == grayRamp->colormap &&
- c->visualid == vinfo->visualid &&
- ValidRamp(c, vinfo)) {
- grayRamp->red_max = c->red_max;
- grayRamp->red_mult = c->red_mult;
- grayRamp->base_pixel = c->base_pixel;
- grayRamp->visualid = c->visualid;
- grayRamp->killid = c->killid;
- break;
- }
- c++;
- }
- if (i == *nramp) gotRamp = False;
- }
- return gotRamp;
-}
-
-static void GetDatabaseValues(
- Display *dpy,
- XVisualInfo *vinfo,
- XStandardColormap *colorCube,
- XStandardColormap *grayRamp)
-{
- char *class, *depth;
- char namePrefix[40], classPrefix[40];
- unsigned long max;
- XStandardColormap fakeCube;
-
- switch (vinfo->class) {
- default:
- case StaticGray: class = "StaticGray."; break;
- case GrayScale: class = "GrayScale."; break;
- case StaticColor: class = "StaticColor."; break;
- case PseudoColor: class = "PseudoColor."; break;
- case TrueColor: class = "TrueColor."; break;
- case DirectColor: class = "DirectColor."; break;
- }
-
- if (vinfo->depth >= 24) depth = "24.";
- else if (vinfo->depth >= 12) depth = "12.";
- else if (vinfo->depth >= 8) depth = "8.";
- else if (vinfo->depth >= 4) depth = "4.";
- else if (vinfo->depth >= 2) depth = "2.";
- else depth = "1.";
-
- (void) strcpy(namePrefix, "dpsColorCube.");
- (void) strcat(strcat(namePrefix, class), depth);
- (void) strcpy(classPrefix, "DPSColorCube.");
- (void) strcat(strcat(classPrefix, class), depth);
-
- CreateDefaultsDb(dpy);
-
- if (colorCube == NULL && vinfo->class == TrueColor) {
- /* We'll need the color cube information to compute the gray ramp,
- even if it wasn't asked for, so make colorCube point to a
- temporary structure */
- colorCube = &fakeCube;
- }
-
- if (colorCube != NULL) {
- switch (vinfo->class) {
- case StaticGray:
- case GrayScale:
- /* We can't do a color cube for these visuals */
- break;
-
- case TrueColor:
- /* Rewrite whatever was there before with real values */
- ColorValuesFromMask(vinfo->red_mask, &colorCube->red_max,
- &colorCube->red_mult);
- ColorValuesFromMask(vinfo->green_mask, &colorCube->green_max,
- &colorCube->green_mult);
- ColorValuesFromMask(vinfo->blue_mask, &colorCube->blue_max,
- &colorCube->blue_mult);
- colorCube->base_pixel = 0;
- break;
-
- case DirectColor:
- /* Get the mults from the masks; ignore maxes */
- ColorValuesFromMask(vinfo->red_mask, &max,
- &colorCube->red_mult);
- ColorValuesFromMask(vinfo->green_mask, &max,
- &colorCube->green_mult);
- ColorValuesFromMask(vinfo->blue_mask, &max,
- &colorCube->blue_mult);
- /* Get the maxes from the database */
- if (colorCube->red_max == 0) {
- colorCube->red_max =
- NumColors(namePrefix, classPrefix, redsName) - 1;
- }
- if (colorCube->green_max == 0) {
- colorCube->green_max =
- NumColors(namePrefix, classPrefix, greensName) - 1;
- }
- if (colorCube->blue_max == 0) {
- colorCube->blue_max =
- NumColors(namePrefix, classPrefix, bluesName) - 1;
- }
- colorCube->base_pixel = 0;
- break;
-
- case PseudoColor:
- if (colorCube->red_max == 0) {
- colorCube->red_max =
- NumColors(namePrefix, classPrefix, redsName) - 1;
- }
- if (colorCube->green_max == 0) {
- colorCube->green_max =
- NumColors(namePrefix, classPrefix, greensName) - 1;
- }
- if (colorCube->blue_max == 0) {
- colorCube->blue_max =
- NumColors(namePrefix, classPrefix, bluesName) - 1;
- }
- colorCube->red_mult = (colorCube->green_max + 1) *
- (colorCube->blue_max + 1);
- colorCube->green_mult = colorCube->blue_max + 1;
- colorCube->blue_mult = 1;
- break;
-
- case StaticColor:
- FindStaticColorCube(dpy, vinfo, colorCube);
- break;
- }
- }
-
- switch (vinfo->class) {
- case GrayScale:
- case PseudoColor:
- case DirectColor:
- if (grayRamp->red_max == 0) {
- grayRamp->red_max =
- NumColors(namePrefix, classPrefix, graysName) - 1;
- }
- grayRamp->red_mult = 1;
- break;
-
- case TrueColor:
- /* If the color cube is truly a cube, use its diagonal. Otherwise
- were SOL and have to use a two-element ramp. */
- if (CubicCube(colorCube)) UseGrayDiagonal(colorCube, grayRamp);
- else UseGrayCorners(colorCube, grayRamp);
- break;
-
- case StaticColor:
- case StaticGray:
- FindStaticGrayRamp(dpy, vinfo, grayRamp, colorCube);
- break;
- }
-}
-
-static Bool CubicCube(XStandardColormap *cube)
-{
- return cube->red_max == cube->green_max && cube->red_max ==
- cube->blue_max;
-}
-
-static void UseGrayDiagonal(XStandardColormap *cube, XStandardColormap *ramp)
-{
- ramp->red_max = cube->red_max;
- ramp->red_mult = cube->red_mult + cube->green_mult + cube->blue_mult;
- ramp->base_pixel = cube->base_pixel;
-}
-
-static void UseGrayCorners(XStandardColormap *cube, XStandardColormap *ramp)
-{
- ramp->red_max = 1;
- ramp->red_mult = (cube->red_max + 1) * (cube->green_max + 1) *
- (cube->blue_max + 1) - 1;
- if (* (int *) &(cube->red_mult) < 0) ramp->red_mult *= -1;
- ramp->base_pixel = cube->base_pixel;
-}
-
-static void ColorValuesFromMask(
- unsigned long mask,
- unsigned long *maxColor,
- unsigned long *mult)
-{
- *mult = 1;
- while ((mask & 1) == 0) {
- *mult <<= 1;
- mask >>= 1;
- }
- *maxColor = mask;
-}
-
-/*
-Resource definitions for default color cube / gray ramp sizes
-are based on visual class and depth. Working from least choices
-to most, here's motivation for the defaults:
-
-If unspecified, default is 0 values for red, green, and blue,
-and 2 (black and white) for grays. This covers StaticGray, StaticColor,
-and depths less than 4 of the other visual classes.
-
-If we have a choice, we try to allocate a gray ramp with an odd number
-of colors; this is so 50% gray can be rendered without dithering.
-In general we don't want to allocate a large cube (even when many
-colormap entries are available) because allocation of each entry
-requires a round-trip to the server (entries allocated read-only
-via XAllocColor).
-
-For GrayScale, any depth less than 4 is treated as monochrome.
-
-PseudoColor depth 4 we try for a 2x2x2 cube with the gray ramp on
-the diagonal. Depth 8 uses a 4x4x4 cube with a separate 9 entry
-gray ramp. Depth 12 uses a 6x6x5 "cube" with a separate 17 entry gray
-ramp. The cube is non-symmetrical; we don't want to use the diagonal
-for a gray ramp and we can get by with fewer blues than reds or greens.
-
-For DirectColor, allocating a gray ramp separate from the color cube
-is wasteful of map entries, so we specify a symmetrical cube and
-share the diagonal entries for the gray ramp.
-
-For TrueColor, # color shades is set equal to the # shades / primary;
-we don't actually allocate map entries, but it's handy to be able to
-do the resource lookup blindly and get the right value.
-*/
-
-static char dpsDefaults[] = "\
-*reds: 0\n\
-*greens: 0\n\
-*blues: 0\n\
-*grays: 2\n\
-\
-*GrayScale.4.grays: 9\n\
-*GrayScale.8.grays: 17\n\
-\
-*PseudoColor.4.reds: 2\n\
-*PseudoColor.4.greens: 2\n\
-*PseudoColor.4.blues: 2\n\
-*PseudoColor.4.grays: 2\n\
-*PseudoColor.8.reds: 4\n\
-*PseudoColor.8.greens: 4\n\
-*PseudoColor.8.blues: 4\n\
-*PseudoColor.8.grays: 9\n\
-*PseudoColor.12.reds: 6\n\
-*PseudoColor.12.greens: 6\n\
-*PseudoColor.12.blues: 5\n\
-*PseudoColor.12.grays: 17\n\
-\
-*DirectColor.8.reds: 4\n\
-*DirectColor.8.greens: 4\n\
-*DirectColor.8.blues: 4\n\
-*DirectColor.8.grays: 4\n\
-*DirectColor.12.reds: 6\n\
-*DirectColor.12.greens: 6\n\
-*DirectColor.12.blues: 6\n\
-*DirectColor.12.grays: 6\n\
-*DirectColor.24.reds: 7\n\
-*DirectColor.24.greens: 7\n\
-*DirectColor.24.blues: 7\n\
-*DirectColor.24.grays: 7\n\
-\
-*TrueColor.12.reds: 16\n\
-*TrueColor.12.greens: 16\n\
-*TrueColor.12.blues: 16\n\
-*TrueColor.12.grays: 16\n\
-*TrueColor.24.reds: 256\n\
-*TrueColor.24.greens: 256\n\
-*TrueColor.24.blues: 256\n\
-*TrueColor.24.grays: 256\n\
-";
-
-static XrmDatabase defaultDB = NULL;
-
-static void CreateDefaultsDb(Display *dpy)
-{
- char home[256], *dpyDefaults;
-
- if (defaultDB == NULL) defaultDB = XrmGetStringDatabase(dpsDefaults);
-
- if (curDpyRec->db != NULL) return;
-
- dpyDefaults = XResourceManagerString(dpy);
- if (dpyDefaults != NULL) {
- curDpyRec->db = XrmGetStringDatabase(dpyDefaults);
- }
-
- if (curDpyRec->db == NULL) {
- GetHomeDir(home);
- strcpy(home, "/.Xdefaults");
- curDpyRec->db = XrmGetFileDatabase(home);
- }
-}
-
-static void GetHomeDir(char *buf)
-{
-#ifndef X_NOT_POSIX
- uid_t uid;
-#else
- int uid;
- extern int getuid();
-#ifndef SYSV386
- extern struct passwd *getpwuid(), *getpwnam();
-#endif
-#endif
- struct passwd *pw;
- static char *ptr = NULL;
-
- if (ptr == NULL) {
- if (!(ptr = getenv("HOME"))) {
- if ((ptr = getenv("USER")) != 0) pw = getpwnam(ptr);
- else {
- uid = getuid();
- pw = getpwuid(uid);
- }
- if (pw) ptr = pw->pw_dir;
- else {
- ptr = NULL;
- *buf = '\0';
- }
- }
- }
-
- if (ptr)
- (void) strcpy(buf, ptr);
-
- buf += strlen(buf);
- *buf = '/';
- buf++;
- *buf = '\0';
- return;
-}
-
-static long NumColors(char *namePrefix, char *classPrefix, char *color)
-{
- char name[40], class[40];
- XrmValue rtnValue;
- char *rtnType;
- long value;
-
- (void) strcpy(name, namePrefix);
- (void) strcpy(class, classPrefix);
- if (! XrmGetResource(curDpyRec->db, strcat(name, color),
- strcat(class, color), &rtnType, &rtnValue)) {
- if (! XrmGetResource(defaultDB, name, class, &rtnType, &rtnValue)) {
- /* This should never happen, as our defaults cover all cases */
- return 0;
- }
- }
-
- /* Resource value is number of shades of specified color. If value
- is not an integer, atoi returns 0, so we return 0. If value
- is less than 2, it is invalid (need at least 2 shades of a color).
- Explicitly setting 0 is ok for colors (means to not use a color
- cube) but merits a warning for gray. */
-
- if (strcmp(rtnValue.addr, "0") == 0 && strcmp(color, "grays") != 0) {
- return 0;
- }
-
- value = atol(rtnValue.addr);
- if (value < 2) {
- char mbuf[512];
- sprintf(mbuf, "%% Value '%s' is invalid for %s resource\n",
- rtnValue.addr, name);
- DPSWarnProc(NULL, mbuf);
- }
- return value;
-}
-
-/* Query the entire colormap in the static color case, then try to find
- a color cube. Check pairs of black and white cells trying to find
- a cube between them and take the first one you find. */
-
-static void FindStaticColorCube(
- Display *dpy,
- XVisualInfo *vinfo,
- XStandardColormap *colorCube)
-{
- XColor *ramp, *black, *white, *altBlack, *altWhite;
- int i, entries;
-
- entries = 1 << vinfo->depth;
- ramp = (XColor *) calloc(entries, sizeof(XColor));
-
- if (ramp == NULL) {
- colorCube->red_max = 0;
- return;
- }
-
- /* Query the colormap */
- for (i = 0; i < entries; i++) ramp[i].pixel = i;
- XQueryColors(dpy, colorCube->colormap, ramp, entries);
-
- /* Find the white and black entries */
-
- black = white = altBlack = altWhite = NULL;
- for (i = 0; i < entries; i++) {
- if (ramp[i].flags != (DoRed | DoBlue | DoGreen)) continue;
- if (ramp[i].red == 0 && ramp[i].blue == 0 &&
- ramp[i].green == 0) {
- if (black == NULL) black = ramp+i;
- else if (altBlack == NULL) altBlack = ramp+i;
- } else if (ramp[i].red == SCALE && ramp[i].blue == SCALE &&
- ramp[i].green == SCALE) {
- if (white == NULL) white = ramp+i;
- else if (altWhite == NULL) altWhite = ramp+i;
- }
- }
-
- if (black == NULL || white == NULL) {
- colorCube->red_max = 0;
- free(ramp);
- return;
- }
-
- /* Look for cubes between pairs of black & white */
- if (!CheckCube(black, white, colorCube) &&
- !CheckCube(altBlack, white, colorCube) &&
- !CheckCube(black, altWhite, colorCube) &&
- !CheckCube(altBlack, altWhite, colorCube)) {
- colorCube->red_max = 0;
- }
-
- free(ramp);
-}
-
-#define R 1
-#define G 2
-#define B 4
-#define C 8
-#define M 16
-#define Y 32
-
-#define SMALLSCALE 255
-#define CheckColor(color,r,g,b) ((((color)->red >> 8) == (r) * SMALLSCALE) && \
- (((color)->green >> 8) == (g) * SMALLSCALE) && \
- (((color)->blue >> 8) == (b) * SMALLSCALE))
-
-static Bool CheckCube(
- XColor *black,
- XColor *white,
- XStandardColormap *cube)
-{
- int r = 0, g = 0, b = 0, c = 0, m = 0, y = 0, k, w;
- XColor *color;
- unsigned int found = 0;
- int small, middle, large;
- int smallMult, smallMax, middleMult, middleMax, largeMult, largeMax;
- Bool backwards = False;
- int mult = 1;
- XStandardColormap test; /* Test cube */
- int i;
- int size;
-
- if (black == NULL || white == NULL) return False;
-
- k = black->pixel;
- w = white->pixel - k;
-
- size = ABS(w);
- if (w < 0) {
- backwards = True;
- mult = -1;
- }
-
- for (i = 1; i < size; i++) {
- color = black + i*mult;
- if (color->flags != (DoRed | DoBlue | DoGreen)) return False;
-
- /* If black or white is in the middle of the cube, can't work */
- if (CheckColor(color, 0, 0, 0)) return False;
- if (CheckColor(color, 1, 1, 1)) return False;
-
- /* Check for red, green, blue, cyan, magenta, and yellow */
- if (CheckColor(color, 1, 0, 0)) {r = color->pixel-k; found |= R;}
- else if (CheckColor(color, 0, 1, 0)) {g = color->pixel-k; found |= G;}
- else if (CheckColor(color, 0, 0, 1)) {b = color->pixel-k; found |= B;}
- else if (CheckColor(color, 0, 1, 1)) {c = color->pixel-k; found |= C;}
- else if (CheckColor(color, 1, 0, 1)) {m = color->pixel-k; found |= M;}
- else if (CheckColor(color, 1, 1, 0)) {y = color->pixel-k; found |= Y;}
- }
-
- /* If any color is missing no cube is possible */
- if (found != (R | G | B | C | M | Y)) return False;
-
- /* Next test. Make sure B + G = C, R + B = M, R + G = Y,
- and R + G + B = W */
- if (b + g != c) return False;
- if (r + b != m) return False;
- if (r + g != y) return False;
- if (r + g + b != w) return False;
-
- /* Looking good! Compensate for backwards cubes */
- if (backwards) {
- w = ABS(w);
- r = ABS(r);
- g = ABS(g);
- b = ABS(b);
- }
-
- /* Find the smallest, middle, and largest difference */
- if (r < b && b < g) {
- small = r; middle = b; large = g;
- } else if (r < g && g < b) {
- small = r; middle = g; large = b;
- } else if (b < r && r < g) {
- small = b; middle = r; large = g;
- } else if (b < g && g < r) {
- small = b; middle = g; large = r;
- } else if (g < r && r < b) {
- small = g; middle = r; large = b;
- } else {
- small = g; middle = b; large = r;
- }
-
- /* The smallest must divide the middle, and the middle the large */
- if ((middle % (small + 1)) != 0) return False;
- if ((large % (small + middle + 1)) != 0) return False;
-
- /* OK, we believe we have a cube. Compute the description */
- smallMult = 1;
- smallMax = small;
- middleMult = small + 1;
- middleMax = middle / middleMult;
- largeMult = small + middle + 1;
- largeMax = large / largeMult;
-
- if (small == r) {
- test.red_max = smallMax; test.red_mult = smallMult;
- if (middle == b) {
- test.blue_max = middleMax; test.blue_mult = middleMult;
- test.green_max = largeMax; test.green_mult = largeMult;
- } else {
- test.green_max = middleMax; test.green_mult = middleMult;
- test.blue_max = largeMax; test.blue_mult = largeMult;
- }
- } else if (small == g) {
- test.green_max = smallMax; test.green_mult = smallMult;
- if (middle == b) {
- test.blue_max = middleMax; test.blue_mult = middleMult;
- test.red_max = largeMax; test.red_mult = largeMult;
- } else {
- test.red_max = middleMax; test.red_mult = middleMult;
- test.blue_max = largeMax; test.blue_mult = largeMult;
- }
- } else { /* small == b */
- test.blue_max = smallMax; test.blue_mult = smallMult;
- if (middle == r) {
- test.red_max = middleMax; test.red_mult = middleMult;
- test.green_max = largeMax; test.green_mult = largeMult;
- } else {
- test.green_max = middleMax; test.green_mult = middleMult;
- test.red_max = largeMax; test.red_mult = largeMult;
- }
- }
-
- /* Re-compensate for backwards cube */
- if (backwards) {
- test.red_mult *= -1;
- test.green_mult *= -1;
- test.blue_mult *= -1;
- }
-
- /* Finally, test the hypothesis! The answer must be correct within 1
- bit. Only look at the top 8 bits; the others are too noisy */
-
- for (i = 1; i < size; i++) {
-#define calc(i, max, mult) ((((i / test.mult) % \
- (test.max + 1)) * SCALE) / test.max)
- r = ((unsigned short) calc(i, red_max, red_mult) >> 8) -
- (black[i*mult].red >> 8);
- g = ((unsigned short) calc(i, green_max, green_mult) >> 8) -
- (black[i*mult].green >> 8);
- b = ((unsigned short) calc(i, blue_max, blue_mult) >> 8) -
- (black[i*mult].blue >> 8);
-#undef calc
- if (ABS(r) > 2 || ABS(g) > 2 || ABS(b) > 2) return False;
- }
- cube->red_max = test.red_max;
- cube->red_mult = test.red_mult;
- cube->green_max = test.green_max;
- cube->green_mult = test.green_mult;
- cube->blue_max = test.blue_max;
- cube->blue_mult = test.blue_mult;
- cube->base_pixel = k;
- return True;
-}
-
-#undef R
-#undef G
-#undef B
-#undef C
-#undef M
-#undef Y
-
-/* Query the entire colormap in the static gray case, then try to find
- a gray ramp. This handles there being 2 white or black entries
- in the colormap and finds the longest linear ramp between pairs of
- white and black. If there is a color cube, also check its diagonal and
- use its corners if we need to */
-
-static void FindStaticGrayRamp(
- Display *dpy,
- XVisualInfo *vinfo,
- XStandardColormap *grayRamp,
- XStandardColormap *colorCube)
-{
- XColor *ramp, *black, *white, *altBlack, *altWhite;
- int i, r0, r1, r2, r3, size, entries, redMult;
- unsigned long base;
-
- entries = 1 << vinfo->depth;
- ramp = (XColor *) calloc(entries, sizeof(XColor));
-
- if (ramp == NULL) {
- grayRamp->red_max = 0;
- return;
- }
-
- /* Query the colormap */
- for (i = 0; i < entries; i++) ramp[i].pixel = i;
- XQueryColors(dpy, grayRamp->colormap, ramp, entries);
-
- /* Find the white and black entries */
-
- black = white = altBlack = altWhite = NULL;
- for (i = 0; i < entries; i++) {
- if (ramp[i].flags != (DoRed | DoBlue | DoGreen)) continue;
- if (CheckColor(ramp+i, 0, 0, 0)) {
- if (black == NULL) black = ramp+i;
- else if (altBlack == NULL) altBlack = ramp+i;
- } else if (CheckColor(ramp+i, 1, 1, 1)) {
- if (white == NULL) white = ramp+i;
- else if (altWhite == NULL) altWhite = ramp+i;
- }
- }
-
- if (black == NULL || white == NULL) {
- grayRamp->red_max = 0;
- free(ramp);
- return;
- }
-
- /* Find out how large a ramp exists between pairs of black & white */
- r0 = FindRampSize(black, white);
- r1 = FindRampSize(altBlack, white);
- r2 = FindRampSize(black, altWhite);
- r3 = FindRampSize(altBlack, altWhite);
-
- size = r0;
- if (r1 > size) size = r1;
- if (r2 > size) size = r2;
- if (r3 > size) size = r3;
- if (size == r0) SetRamp(black, white, size, &redMult, &base);
- else if (size == r1) SetRamp(altBlack, white, size, &redMult, &base);
- else if (size == r2) SetRamp(black, altWhite, size, &redMult, &base);
- else if (size == r3) SetRamp(altBlack, altWhite, size, &redMult, &base);
-
- if (colorCube != NULL && CubicCube(colorCube) &&
- colorCube->red_max > size) {
- UseGrayDiagonal(colorCube, grayRamp);
- } else {
- grayRamp->red_max = size;
- grayRamp->red_mult = redMult;
- grayRamp->base_pixel = base;
- }
-
- free(ramp);
-}
-
-static int FindRampSize(XColor *black, XColor *white)
-{
- XColor *c;
- int r;
- int mult = 1;
- int i, size;
-
- if (black == NULL || white == NULL) return 0;
- size = ABS(white - black);
-
- /* See if we have a backwards ramp */
- if (black > white) mult = -1;
-
- /* See if all cells between black and white are linear, to within 1 bit.
- Only look at the high order 8 bits */
-
- for (i = 1; i < size; i++) {
- c = &black[i*mult];
- if (c->red != c->blue || c->red != c->green) return 1;
- r = ((unsigned short) ((i * SCALE) / size) >> 8) - (c->red >> 8);
- if (ABS(r) > 2) return 1;
- }
- return size;
-}
-
-static void SetRamp(
- XColor *black,
- XColor *white,
- int size,
- int *mult,
- unsigned long *base)
-{
- *base = black->pixel;
- *mult = (white - black) / size;
-}
-
-#define lowbit(x) ((x) & (~(x) + 1))
-
-static unsigned long shiftdown(unsigned long x)
-{
- while ((x & 1) == 00) {
- x = x >> 1;
- }
- return x;
-}
-
-static void AllocateColorCube(
- Display *dpy,
- XVisualInfo *vinfo,
- XStandardColormap *colorCube,
- PixelRec *pixels)
-{
- int count, first, remain, n, j;
- unsigned long i;
- Colormap cmap = colorCube->colormap;
- unsigned long delta;
- XColor color;
-
- /* We do no allocation for TrueColor or StaticColor */
- if (vinfo->class == TrueColor || vinfo->class == StaticColor) return;
-
- if (vinfo->class == DirectColor) {
- if ((i = shiftdown(vinfo->red_mask)) > colorCube->red_max)
- colorCube->red_max = i;
- if ((i = shiftdown(vinfo->green_mask)) > colorCube->green_max)
- colorCube->green_max = i;
- if ((i = shiftdown(vinfo->blue_mask)) > colorCube->blue_max)
- colorCube->blue_max = i;
-
- /* We only handle symmetric DirectColor */
- count = colorCube->red_max + 1;
- if (colorCube->blue_max + 1 < count) count = colorCube->blue_max + 1;
- if (colorCube->green_max + 1 < count) count = colorCube->green_max + 1;
- colorCube->red_max = colorCube->blue_max = colorCube->green_max =
- count - 1;
-
- delta = lowbit(vinfo->red_mask) + lowbit(vinfo->green_mask) +
- lowbit(vinfo->blue_mask);
- } else {
- count = (colorCube->red_max + 1) * (colorCube->blue_max + 1) *
- (colorCube->green_max + 1);
- delta = 1;
- }
-
- colorCube->base_pixel = 0; /* temporary, may change */
-
- pixels->pixels = (unsigned long *) calloc(vinfo->colormap_size,
- sizeof(unsigned long));
- if (pixels->pixels == NULL) {
- colorCube->red_max = 0;
- return;
- }
-
- if (!AllocateColormap(dpy, colorCube, vinfo, &count, pixels,
- &first, &remain, delta)) {
- free((char *) pixels->pixels);
- pixels->pixels = NULL;
- colorCube->red_max = 0;
- return;
- }
-
- colorCube->base_pixel = pixels->pixels[first];
- color.flags = DoRed | DoGreen | DoBlue;
-
- /* Define colors */
- for (n = 0, j = 0; j < count; ++j, n += delta) {
- color.pixel = n + pixels->pixels[first];
- if (vinfo->class == PseudoColor) {
-#define calc(i, max, mult) ((((i / colorCube->mult) % \
- (colorCube->max + 1)) * SCALE) / colorCube->max)
- color.red = (unsigned short) calc(n, red_max, red_mult);
- color.green = (unsigned short) calc(n, green_max, green_mult);
- color.blue = (unsigned short) calc(n, blue_max, blue_mult);
-#undef calc
- } else {
- color.red = color.green = color.blue =
- (j * SCALE) / colorCube->red_max;
- }
- if (!AllocateColor(dpy, cmap, &color)) {
- XFreeColors(dpy, cmap, pixels->pixels, count+first+remain, 0);
- free((char *) pixels->pixels);
- pixels->pixels = NULL;
- colorCube->red_max = 0;
- return;
- }
- }
-
- /* Smush down unused pixels, if any */
-
- for (j = 0; j < remain; j++) {
- pixels->pixels[first+j] = pixels->pixels[first+count+j];
- }
- pixels->npixels -= count;
-}
-
-static void AllocateGrayRamp(
- Display *dpy,
- XVisualInfo *vinfo,
- XStandardColormap *grayRamp,
- XStandardColormap *colorCube,
- PixelRec *pixels)
-{
- int count, first, remain, n, i;
- Colormap cmap = grayRamp->colormap;
- XColor color;
- unsigned long delta;
-
- /* Allocate cells in read/write visuals only */
- if (vinfo->class != PseudoColor && vinfo->class != GrayScale &&
- vinfo->class != DirectColor) return;
-
- if (vinfo->class == DirectColor) {
- delta = lowbit(vinfo->red_mask) + lowbit(vinfo->green_mask) +
- lowbit(vinfo->blue_mask);
- } else delta = 1;
-
- /* First of all see if there's a usable gray ramp in the color cube */
-
- if (colorCube != NULL) {
- if (CubicCube(colorCube)) {
- if (colorCube->red_max >= grayRamp->red_max) {
- /* diagonal is long enough! use it */
- UseGrayDiagonal(colorCube, grayRamp);
- return;
- }
- }
- }
-
- grayRamp->base_pixel = 0; /* temporary, may change */
-
- count = grayRamp->red_max + 1;
-
- if (pixels->pixels == NULL) {
- pixels->pixels = (unsigned long *) calloc(vinfo->colormap_size,
- sizeof(unsigned long));
- if (pixels->pixels == NULL) {
- grayRamp->red_max = 0;
- return;
- }
- }
-
- if (!AllocateColormap(dpy, grayRamp, vinfo, &count, pixels,
- &first, &remain, delta)) {
- /* Last gasp: try any diagonal or the corners of the color cube */
- if (colorCube != NULL) {
- if (CubicCube(colorCube)) UseGrayDiagonal(colorCube, grayRamp);
- else UseGrayCorners(colorCube, grayRamp);
- } else {
- grayRamp->red_max = 0;
- }
- return;
- }
-
- grayRamp->base_pixel = pixels->pixels[first];
- color.flags = DoRed | DoGreen | DoBlue;
-
- /* Define colors */
- for (n = 0, i = 0; i < count; ++i, n += delta) {
- color.pixel = n + pixels->pixels[first];
- color.red = (unsigned short)((n * SCALE) / (grayRamp->red_max));
- color.green = color.red;
- color.blue = color.red;
-
- if (!AllocateColor(dpy, cmap, &color)) {
- /* Don't need to free pixels here; we'll do it on return */
- grayRamp->red_max = 0;
- return;
- }
- }
-
- /* Smush down unused pixels, if any */
-
- for (i = 0; i < remain; i++) {
- pixels->pixels[first+i] = pixels->pixels[first+count+i];
- }
- pixels->npixels -= count;
-}
-
-static int compare(const void *a1, const void *a2)
-{
- register unsigned long *e1 = (unsigned long *) a1,
- *e2 = (unsigned long *) a2;
-
- if (*e1 < *e2) return -1;
- if (*e1 > *e2) return 1;
- return 0;
-}
-
-static Bool AllocateColormap(
- Display *dpy,
- XStandardColormap *map,
- XVisualInfo *vinfo,
- int *count,
- PixelRec *pixels,
- int *first, int *remain,
- unsigned long delta)
-{
- Colormap cmap = map->colormap;
- int npixels, ok, i;
- Bool success = False;
-
- if (pixels->npixels == 0) {
- /* First try to allocate the entire colormap */
- npixels = vinfo->colormap_size;
- ok = XAllocColorCells(dpy, cmap, 1, NULL, 0, pixels->pixels, npixels);
- if (ok) success = True;
- else {
- int total;
- int top, mid = 0;
-
- /* If it's a gray ramp or direct color we need at least 2;
- others 8 */
- if (map->blue_max == 0 || vinfo->class == DirectColor) total = 2;
- else total = 8;
-
- /* Allocate all available cells, using binary backoff */
- top = vinfo->colormap_size - 1;
- while (total <= top) {
- mid = total + ((top - total + 1) / 2);
- ok = XAllocColorCells(dpy, cmap, 1, NULL, 0,
- pixels->pixels, mid);
- if (ok) {
- if (mid == top) {
- success = True;
- break;
- } else {
- XFreeColors(dpy, cmap, pixels->pixels, mid, 0);
- total = mid;
- }
- } else top = mid - 1;
- }
- if (success) npixels = mid;
- else npixels = 0;
- }
- } else {
- /* We must be in the gray ramp case, so we need at least 2 entries */
- npixels = pixels->npixels;
- if (map->blue_max != 0 || npixels >= 2) success = True;
- }
-
- if (success) {
- /* Avoid pessimal case by testing to see if already sorted */
- for (i = 0; i < npixels-1; ++i) {
- if (pixels->pixels[i] != pixels->pixels[i+1]-1) break;
- }
-
- if (i < npixels-1) {
- PrivSort((char *)pixels->pixels, npixels,
- sizeof(unsigned long), compare);
- }
-
- if (!contiguous(pixels->pixels, npixels, count, delta,
- first, remain)) {
- /* If there are enough free cells, shrink the map to fit.
- Otherwise fail; we'll free the pixels later */
- if (((map->blue_max == 0 || vinfo->class == DirectColor) &&
- *count >= 2) || *count >=8) {
- ShrinkMapToFit(map, count, vinfo);
- *remain = npixels - *first - *count;
- } else success = False;
- }
- }
-
- pixels->npixels = npixels;
- return success;
-}
-
-static Bool contiguous(
- unsigned long pixels[], /* specifies allocated pixels */
- int npixels, /* specifies count of alloc'd pixels */
- int *ncolors, /* specifies needed sequence length
- If not available, returns max
- available contiguous sequence */
- unsigned long delta,
- 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 */
- int max = 1; /* longest sequence we found */
- int maxstart = 0;
-
- *first = 0;
- while (count < *ncolors && i < npixels) {
- if (pixels[i-1] + delta == pixels[i]) count++;
- else {
- if (count > max) {
- max = count;
- maxstart = *first;
- }
- count = 1;
- *first = i;
- }
- i++;
- }
- if (i == npixels && count > max) {
- max = count;
- maxstart = *first;
- }
- *rem = npixels - i;
- if (count != *ncolors) {
- *ncolors = max;
- *first = maxstart;
- return False;
- } return True;
-}
-
-static Bool AllocateColor(
- Display *dpy,
- Colormap cmap,
- XColor *color)
-{
- unsigned long pix = color->pixel;
- XColor request;
- int ok;
-
- request = *color;
-
- /* Free RW, Alloc RO, if fails, try RW */
- XFreeColors(dpy, cmap, &pix, 1, 0);
- ok = XAllocColor(dpy, cmap, &request);
-
- /* If the pixel we get back isn't the request one, probably RO
- White or Black, so shove it in RW so our cube is correct.
- If alloc fails, try RW. */
-
- if (!ok || request.pixel != color->pixel) {
- ok = XAllocColorCells(dpy, cmap, 0, NULL, 0, &pix, 1);
-
- if (pix != color->pixel) XFreeColors(dpy, cmap, &pix, 1, 0);
- if (!ok || pix != color->pixel) {
- return False;
- }
- request = *color;
- XStoreColor(dpy, cmap, &request);
- }
- return True;
-}
-
-static void ShrinkMapToFit(
- XStandardColormap *map,
- int *space,
- XVisualInfo *vinfo)
-{
- if (map->blue_max == 0) map->red_max = *space - 1;
- else if (vinfo->class == DirectColor) {
- if (map->red_max > *space - 1) map->red_max = *space - 1;
- if (map->green_max > *space - 1) map->green_max = *space - 1;
- if (map->blue_max > *space - 1) map->blue_max = *space - 1;
- } else {
- int which = 2;
- while ((map->red_max + 1) * (map->green_max + 1) *
- (map->blue_max + 1) > *space) {
- if (which == 0) {
- if (map->red_max > 1) map->red_max--;
- which = 1;
- } else if (which == 1) {
- if (map->green_max > 1) map->green_max--;
- which = 2;
- } else {
- if (map->blue_max > 1) map->blue_max--;
- which = 0;
- }
- }
- *space = (map->red_max + 1) * (map->green_max + 1) *
- (map->blue_max + 1);
-
- map->red_mult = (map->green_max + 1) * (map->blue_max + 1);
- map->green_mult = map->blue_max + 1;
- map->blue_mult = 1;
- }
-}
-
-static void DefineProperty(
- Display *dpy,
- XStandardColormap *map,
- XVisualInfo *vinfo,
- XStandardColormap *prop,
- int nProp,
- Atom atom)
-{
- XStandardColormap *copy;
- int i;
-
- if (nProp == 0) {
- XSetRGBColormaps(dpy, RootWindow(dpy, vinfo->screen), map, 1, atom);
- return;
- }
-
- copy = (XStandardColormap *) calloc(nProp+1, sizeof(XStandardColormap));
-
- /* Hm. If I can't allocate the list, is it better to just put our
- property on, or to leave the ones there? I'll guess the latter... */
- if (copy == NULL) return;
-
- if (vinfo->visual == DefaultVisual(dpy, vinfo->screen) &&
- map->colormap == DefaultColormap(dpy, vinfo->screen)) {
- /* Put new entry first; it's more likely to be useful */
- for (i = 0; i < nProp; i++) copy[i+1] = prop[i];
- i = 0;
- } else {
- /* Put it at the end */
- for (i = 0; i < nProp; i++) copy[i] = prop[i];
- /* i = nProp; (it does already) */
- }
-
- copy[i] = *map;
- XSetRGBColormaps(dpy, RootWindow(dpy, vinfo->screen), copy, nProp+1, atom);
-
- free((void *) copy);
-}