/*
**	A utility to prevent colormap flashing by performing
**	a closest match when the allocation fails.
**
**	V1.01 dated 26th March 1997.
**	Written by David Tong, Sun Microsystems Inc.
**
**	To use, first build and then
**		setenv LD_PRELOAD /<full path name>/libnoflash.so.1
*/	

/*
**	Makefile follows:
**
all:	libnoflash.so.1

libnoflash.so.1:	preload.c
	cc -g -K PIC preload.c -c -I. -I/usr/openwin/include
	ld -G -ztext preload.o -R/usr/lib -ldl -lc -o libnoflash.so
	mv libnoflash.so libnoflash.so.1
**
*/

#include	<sys/types.h>
#include	<sys/timeb.h>
#include	<X11/StringDefs.h>
#include	<X11/Intrinsic.h>
#include	<X11/IntrinsicP.h>
#define NEED_REPLIES
#include	<X11/Xlibint.h>

#include <dlfcn.h>

void *X11 = NULL;

void init();

Status (*_XAllocColor) (Display*, Colormap, XColor*);
int (*_XFreeColors) (Display*, Colormap, unsigned long*, int, unsigned long);

#define COLOR_FACTOR       3
#define BRIGHTNESS_FACTOR  1

Status XAllocColor(register Display *dpy, Colormap cmap, XColor *xcolor)
{
	Status retstat;

	if (!X11)
		init();

	if (!(retstat = _XAllocColor(dpy, cmap, xcolor))) {
		XColor *cols;
		unsigned int ncols, i, closepix;
		long int closediff;

		ncols = 1 << DefaultDepth(dpy, DefaultScreen(dpy));

		cols = (XColor * )calloc(ncols, sizeof(XColor));
		for (i = 0; i < ncols; ++i) 
			cols[i].pixel = i;
		XQueryColors(dpy, cmap, cols, ncols);

		do {
		    for (i = 0, closediff = 0x7FFFFFFF; i < ncols; ++i) {

				long int	newclosediff = 
				  COLOR_FACTOR *(
					abs((long)xcolor->red   -(long)cols[i].red)   + 
					abs((long)xcolor->green -(long)cols[i].green) + 
					abs((long)xcolor->blue  -(long)cols[i].blue)) + 
				  BRIGHTNESS_FACTOR *abs(
					((long)xcolor->red + (long)xcolor->green + (long)xcolor->blue) -
					((long)cols[i].red + (long)cols[i].green + (long)cols[i].blue));

				if (newclosediff < closediff) { 
					closepix = i; 
					closediff = newclosediff; 
				}
		    }

		    xcolor->red   = cols[closepix].red;
		    xcolor->green = cols[closepix].green;
		    xcolor->blue  = cols[closepix].blue;
		    /*
		    ** Now paint it black so we don't loop
		    ** in the case that this colour is read-write.
		    */
		    cols[closepix].red = 0;
		    cols[closepix].green = 0;
		    cols[closepix].blue = 0;
		    retstat = _XAllocColor(dpy, cmap, xcolor);
		} while (retstat == 0);
		free(cols);
	}
	return(retstat);
}

void init()
{

	/* Tip from john.m.martin@Central - don't hard-code the library path */

	_XAllocColor = dlsym(RTLD_NEXT, "XAllocColor");
	_XFreeColors = dlsym(RTLD_NEXT, "XFreeColors");	/* Not currently used */
	X11 = (void *) 1;

/*
**	if ((X11 = dlopen("/usr/openwin/lib/libX11.so.4", RTLD_LAZY)) == 0) {
**		printf("%s\n", dlerror());
**		exit(1);
**	}
**
**	_XAllocColor = dlsym(X11, "XAllocColor");
**	_XFreeColors = dlsym(X11, "XFreeColors");
*/

}

