/*----------------------------------------------------------------------*\
 | A drawing program for X windows.  To change the drawing, you have to	|
 | write Xlib code into the refresh_window() routine and recompile.		|
 |																		|
 | Peter N. Schweitzer (U.S. Geological Survey, Reston, VA 22092)		|
\*----------------------------------------------------------------------*/

#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xos.h>
#include <X11/keysym.h>
#include <X11/Xresource.h>
#include <X11/Xatom.h>

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <pwd.h>

#include <tcl.h>

#define DEFAULT_FONT "9x15bold"

/*----------------------------------------------------------------------*\
 | Icon																	|
\*----------------------------------------------------------------------*/

#define icon_bitmap_width 40
#define icon_bitmap_height 40
static char icon_bitmap_bits[] = {
   0xff, 0x0f, 0x7f, 0xf8, 0xff, 0x01, 0xe0, 0x80, 0x03, 0x80, 0xa9, 0x18,
   0x00, 0x4c, 0x95, 0x55, 0x04, 0x00, 0x90, 0xaa, 0x29, 0x02, 0x00, 0x20,
   0x95, 0x15, 0x01, 0x00, 0x40, 0xaa, 0x89, 0x00, 0x08, 0x80, 0x94, 0x95,
   0x00, 0x08, 0x80, 0xa8, 0x49, 0x00, 0x08, 0x00, 0x95, 0x45, 0x00, 0x08,
   0x00, 0xa9, 0x49, 0x18, 0x08, 0x0c, 0x91, 0x25, 0x1c, 0x49, 0x1c, 0xaa,
   0x29, 0x0c, 0x08, 0x18, 0x92, 0x25, 0x00, 0x49, 0x00, 0xaa, 0x29, 0x08,
   0x08, 0x08, 0x92, 0x25, 0x00, 0x49, 0x00, 0xaa, 0x29, 0x08, 0x08, 0x08,
   0x92, 0x25, 0x00, 0x49, 0x00, 0xaa, 0x49, 0xfc, 0xff, 0x1f, 0x91, 0x55,
   0x06, 0x41, 0x30, 0xa9, 0x49, 0x05, 0x08, 0x50, 0x95, 0xd5, 0x04, 0x41,
   0x90, 0xa9, 0xc9, 0x08, 0x08, 0x88, 0x95, 0x55, 0x08, 0x41, 0x08, 0xa9,
   0x49, 0x10, 0x08, 0x04, 0x95, 0x15, 0x11, 0x00, 0x24, 0xa8, 0xa9, 0x22,
   0x08, 0x52, 0x95, 0x55, 0x25, 0x00, 0xa2, 0xaa, 0xa9, 0x4a, 0x1c, 0x51,
   0x95, 0x55, 0x55, 0x36, 0xa9, 0xaa, 0xa9, 0x8a, 0xf7, 0x54, 0x95, 0x55,
   0x95, 0x94, 0xa8, 0xaa, 0xa9, 0x2a, 0x14, 0x54, 0x95, 0x55, 0x55, 0x14,
   0xaa, 0xaa, 0xa9, 0xaa, 0x14, 0x55, 0x95, 0x55, 0x55, 0x94, 0xaa, 0xaa,
   0xa9, 0xaa, 0x14, 0x55, 0x95, 0x55, 0x55, 0x94, 0xaa, 0xaa, 0x01, 0x00,
   0x14, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff};

/*----------------------------------------------------------------------*\
 | Public data															|
\*----------------------------------------------------------------------*/

Display *display;
int screen;
GC gc;
GC rgc;
GC xgc;
GC sgc;
GC rsgc;
XFontStruct *font_info;
int font_height,font_width;
unsigned width,height;
Window win;
unsigned long foreground,background;
unsigned long status_fg,status_bg;
unsigned border_width;

/*----------------------------------------------------------------------*\
 | Static data															|
\*----------------------------------------------------------------------*/

static XSizeHints size_hints;
static XrmDatabase commandlineDB, rDB;

static char window_name[64];
static char program[64];
static char **file_name_list;
static int file_name_count;
static char dir_name[FILENAME_MAX];

static int opTableEntries = 19;
static XrmOptionDescRec opTable[] = {
{"-background",		"*background",					XrmoptionSepArg,	(caddr_t) NULL},
{"-backup",			"*backup",						XrmoptionNoArg,		(caddr_t) "off"},
{"-bd",				"*borderColor",					XrmoptionSepArg,	(caddr_t) NULL},
{"-bg",				"*background",					XrmoptionSepArg,	(caddr_t) NULL},
{"-bordercolor",	"*borderColor",					XrmoptionSepArg,	(caddr_t) NULL},
{"-borderwidth",	"*TopLevelShell.borderWidth",	XrmoptionSepArg,	(caddr_t) NULL},
{"-bw",				"*TopLevelShell.borderWidth",	XrmoptionSepArg,	(caddr_t) NULL},
{"-display",		".display",						XrmoptionSepArg,	(caddr_t) NULL},
{"-fg",				"*foreground",					XrmoptionSepArg,	(caddr_t) NULL},
{"-fn",				"*font",						XrmoptionSepArg,	(caddr_t) NULL},
{"-font",			"*font",						XrmoptionSepArg,	(caddr_t) NULL},
{"-foreground",		"*foreground",					XrmoptionSepArg,	(caddr_t) NULL},
{"-geometry",		"*geometry",					XrmoptionSepArg,	(caddr_t) NULL},
{"-keymap",			"*keymap",						XrmoptionSepArg,	(caddr_t) NULL},
{"-name",			"*name",						XrmoptionSepArg,	(caddr_t) NULL},
{"-title",			".TopLevelShell.title",			XrmoptionSepArg,	(caddr_t) NULL},
{"-status_fg",		"*status_fg",					XrmoptionSepArg,	(caddr_t) NULL},
{"-status_bg",		"*status_bg",					XrmoptionSepArg,	(caddr_t) NULL},
{"-xrm",			NULL,							XrmoptionResArg,	(caddr_t) NULL}
};

/*----------------------------------------------------------------------*\
 | DG's UNIX C library doesn't have these functions						|
\*----------------------------------------------------------------------*/

int memicmp (char *s, char *t, int n) {
	int d = 0;
	while (n-- > 0)
		if (d = toupper(*s++) - toupper(*t++)) break;
	return (d);
	}

int stricmp (char *s, char *t) {
	int d = 0;

	while (*s && *t && !(d = toupper(*s) - toupper(*t))) {
		s++;
		t++;
		}
	return (d);
	}

/*----------------------------------------------------------------------*\
\*----------------------------------------------------------------------*/

static void parseOpenDisp (int *argc, char *argv[]) {
	int i;
	XrmValue value;
	char *str_type[20];
	char str_name[128];
	char display_name[128];

	display_name[0] = 0;

	XrmParseCommand (&commandlineDB,opTable,opTableEntries,argv[0],argc,argv);

	if (*argc > 1) {
		file_name_count = *argc - 1;
		if (file_name_list = (char **) malloc (file_name_count * sizeof (char *))) {
			for (i=0; i < file_name_count; i++)
				if (file_name_list[i] = (char *) malloc (1 + strlen (argv[i+1])))
					strcpy (file_name_list[i],argv[i+1]);
				else {
					printf ("Error: could not allocate space for file names\n");
					exit (1);
					}
			}
		else {
			printf ("Error: could not allocate file name list\n");
			exit (1);
			}
		}

	strcpy (str_name,program);
	strcat (str_name,".display");

	if (XrmGetResource (commandlineDB,str_name,"Canvas.Display",str_type,&value) == True)
		strncpy (display_name,value.addr,(int)value.size);

	if (!(display = XOpenDisplay (display_name))) {
		fprintf (stderr,"%s: Can't open display '%s'\n",argv[0],XDisplayName(display_name));
		exit (1);
		}

	screen = DefaultScreen (display);
	}

static char *GetHomeDir (char *dest) {
	int uid;
	extern int getuid (void);
	struct passwd *pw;
	char *ptr;

	if (ptr = getenv ("HOME")) strcpy (dest,ptr);
	else {
		if (ptr = getenv ("USER")) pw = getpwnam (ptr);
		else {
			uid = getuid();
			pw = getpwuid (uid);
			}
		if (pw) strcpy (dest,pw->pw_dir);
		else strcpy (dest," ");
		}
	return (dest);
	}

static void getUsersDatabase (void) {
	XrmDatabase homeDB, serverDB, applicationDB;

	char filenamebuf[1024];
	char *filename = filenamebuf;
	char *environment;
	char *classname = "Canvas";
	char name[255];
	char *string;

	strcpy (name,"/usr/lib/X11/app-defaults/");
	strcat (name,classname);
	applicationDB = XrmGetFileDatabase (name);
	XrmMergeDatabases (applicationDB,&rDB);

	if (string = XResourceManagerString (display))
		serverDB = XrmGetStringDatabase (string);
	else {
		GetHomeDir (filename);
		strcat (filename,".Xdefaults");
		serverDB = XrmGetFileDatabase (filename);
		}
	XrmMergeDatabases (serverDB,&rDB);

	if ((environment = getenv ("XENVIRONMENT")) == NULL) {
		int len;
		environment = GetHomeDir (filename);
		strcat (environment,".Xdefaults");
		len = strlen (environment);
		gethostname (environment+len,1024-len);
		}
	homeDB = XrmGetFileDatabase (environment);
	XrmMergeDatabases (homeDB,&rDB);
	}

static void mergeOpts (void) {
	char str_name[128];
	char *str_type[20];
	char buffer[20];
	long flags;
	XrmValue value;
	int x,y;
	XColor screen_def;
	char fontname[128];
	Colormap cmap = DefaultColormap (display,screen);

	XrmMergeDatabases (commandlineDB, &rDB);

	/*------------------------------------------------------------------*\
	 | Get font info from user preference database and load the font.	|
	\*------------------------------------------------------------------*/

	strcpy (str_name,program);
	strcat (str_name,".font");

	if (XrmGetResource (rDB,str_name,"Canvas.Font",str_type,&value) == True)
		strncpy (fontname,value.addr,(int)value.size);
	else
		strcpy (fontname,DEFAULT_FONT);

	if ((font_info = XLoadQueryFont (display,fontname)) == NULL) {
		fprintf (stderr,"Canvas: cannot open font %s\n",fontname);
		exit (-1);
		}
	font_height = font_info->max_bounds.ascent + font_info->max_bounds.descent;
	font_width = XTextWidth (font_info," ",1);

	x = 0;
	y = 0;
	width = 640;
	height = 480;

	/*------------------------------------------------------------------*\
	 | Get geometry info from user preference database.					|
	\*------------------------------------------------------------------*/

	strcpy (str_name,program);
	strcat (str_name,".geometry");

	if (XrmGetResource (rDB,str_name,"Canvas.Geometry",str_type,&value) == True)
		strncpy (buffer,value.addr,(int)value.size);
	else
		buffer[0] = 0;

	if (*buffer) {
		flags = XParseGeometry (buffer,&x,&y,&width,&height);
		if (XValue & flags)
			if (XNegative & flags)
				x = DisplayWidth (display,screen) + x - width;
		if (YValue & flags)
			if (YNegative & flags)
				y = DisplayHeight (display,screen) + y - height;
		}

	size_hints.x = x;
	size_hints.y = y;
	size_hints.width = width;
	size_hints.height = height;

	/*------------------------------------------------------------------*\
	 | Get foreground color info from user database.					|
	\*------------------------------------------------------------------*/

	strcpy (str_name,program);
	strcat (str_name,".foreground");

	if (XrmGetResource (rDB,str_name,"Canvas.Foreground",str_type,&value) == True) {
		strncpy (buffer,value.addr,(int)value.size);
		if (XParseColor (display,cmap,buffer,&screen_def) == 0) {
			fprintf (stderr,"xed: fg color specification %s is invalid\n",buffer);
			foreground = BlackPixel (display,screen);
			}
		else {
			XAllocColor (display,cmap,&screen_def);
			foreground = screen_def.pixel;
			}
		}
	else
		foreground = BlackPixel (display,screen);

	/*------------------------------------------------------------------*\
	 | Get background color info from user database.					|
	\*------------------------------------------------------------------*/

	strcpy (str_name,program);
	strcat (str_name,".background");

	if (XrmGetResource (rDB,str_name,"Canvas.Background",str_type,&value) == True) {
		strncpy (buffer,value.addr,(int)value.size);
		if (XParseColor (display,cmap,buffer,&screen_def) == 0) {
			background = WhitePixel (display,screen);
			}
		else {
			XAllocColor (display,cmap,&screen_def);
			background = screen_def.pixel;
			}
		}
	else
		background = WhitePixel (display,screen);

	/*------------------------------------------------------------------*\
	 | Get border width info from user database.						|
	\*------------------------------------------------------------------*/

	strcpy (str_name,program);
	strcat (str_name,".borderWidth");

	if (XrmGetResource (rDB,str_name,"Canvas.BorderWidth",str_type,&value) == True) {
		strncpy (buffer,value.addr,(int)value.size);
		border_width = (unsigned) strtoul (buffer,0,0);
		}
	else
		border_width = 4;

	/*------------------------------------------------------------------*\
	 | Get window name from user database.								|
	\*------------------------------------------------------------------*/

	strcpy (str_name,program);
	strcat (str_name,".name");

	if (XrmGetResource (rDB,str_name,"Canvas.Name",str_type,&value) == True)
		strncpy (window_name,value.addr,(int)value.size);
	else
		strcpy (window_name,"Canvas");

	}

/*----------------------------------------------------------------------*\
\*----------------------------------------------------------------------*/

static void user_exit (void) {
	XUnloadFont (display,font_info->fid);
	XFreeGC (display,gc);
	XFreeGC (display,rgc);
	XFreeGC (display,xgc);
	XFreeGC (display,sgc);
	XCloseDisplay (display);
	exit (0);
	}

/*----------------------------------------------------------------------*\
\*----------------------------------------------------------------------*/

static int io_error_handler (Display *display) {
	user_exit();
	}

/*----------------------------------------------------------------------*\
\*----------------------------------------------------------------------*/

static void allocate_colors (void);
static void refresh_window (XExposeEvent *e);

void main (int argc, char *argv[]) {
	int i,j,k;
	int x = 0, y = 0;		   /* window position */
	char *icon_name = "xed";
	Pixmap icon_pixmap;
	XEvent report;
	unsigned long valuemask = 0;	/* ignore XGCvalues and use defaults */
	XGCValues values;
	XWMHints wmhints;
	char c;
	char *s;

	strcpy (program,argv[0]);

	XrmInitialize();
	parseOpenDisp (&argc,argv);
	getUsersDatabase();
	mergeOpts();

	/* create window */
	win = XCreateSimpleWindow ( display,
								RootWindow(display,screen),
								x,y,width,height,
								border_width,
								foreground,
								background);

	/* create pixmap of depth 1 (bitmap) for icon */
	icon_pixmap = XCreateBitmapFromData (display,win,icon_bitmap_bits,
										 icon_bitmap_width,icon_bitmap_height);

	/* initialize size hint property for window manager */
	size_hints.flags = PPosition | PSize | PMinSize;
	size_hints.min_width = 0;
	size_hints.min_height = 0;

	/* set properties for window manager (always before mapping) */
	XSetStandardProperties (display,
							win,
							window_name,
							icon_name,
							icon_pixmap,
							argv,
							argc,
							&size_hints);

	/* Select event types wanted */
	XSelectInput (display,win,
				  ExposureMask |
				  KeyPressMask |
				  ButtonPressMask |
				  StructureNotifyMask);

	/* Create graphics contexts */

	gc = XCreateGC (display,win,valuemask,&values);
	XSetFont (display,gc,font_info->fid);
	XSetBackground (display,gc,background);
	XSetForeground (display,gc,foreground);

	rgc = XCreateGC (display,win,valuemask,&values);
	XSetFont (display,rgc,font_info->fid);
	XSetBackground (display,rgc,foreground);
	XSetForeground (display,rgc,background);

	xgc = XCreateGC (display,win,valuemask,&values);
	XSetBackground (display,xgc,0);
	if (background == 0) XSetForeground (display,xgc,foreground);
	else				 XSetForeground (display,xgc,background);
	XSetFunction (display,xgc,GXxor);

	sgc = XCreateGC (display,win,valuemask,&values);
	XSetFont (display,sgc,font_info->fid);
	XSetBackground (display,sgc,status_bg);
	XSetForeground (display,sgc,status_fg);

	rsgc = XCreateGC (display,win,valuemask,&values);
	XSetFont (display,rsgc,font_info->fid);
	XSetBackground (display,rsgc,status_fg);
	XSetForeground (display,rsgc,status_bg);

	/* Ensure that keyboard events are received under olwm */

	wmhints.flags = InputHint | IconPixmapHint;
	wmhints.input = True;
	wmhints.icon_pixmap = icon_pixmap;
	XSetWMHints (display,win,&wmhints);

	/* Display window */
	XMapWindow (display,win);

	/*------------------------------------------------------------------*\
	 | Set a fatal IO error handler to exit gracefully when the user	|
	 | closes the window through the window manager.					|
	\*------------------------------------------------------------------*/

	XSetIOErrorHandler (io_error_handler);

	/*------------------------------------------------------------------*\
	 | Allocate colors													|
	\*------------------------------------------------------------------*/

	allocate_colors();

	/*------------------------------------------------------------------*\
	 | Get commands from the user										|
	\*------------------------------------------------------------------*/

	if (file_name_count > 0) {
		Tcl_Interp *interp;
		int code;
		int number;

		interp = Tcl_CreateInterp();
		code = Tcl_EvalFile (interp, file_name_list[0]);
		if ((number = atoi (Tcl_GetVar (interp,"width",0))) > 0) width = number;
		if ((number = atoi (Tcl_GetVar (interp,"height",0))) > 0) height = number;
		}

	/*------------------------------------------------------------------*\
	 | Event loop														|
	\*------------------------------------------------------------------*/

	while (1) {
		XNextEvent (display,&report);
		switch (report.type) {

			case Expose:
				refresh_window ((XExposeEvent *) &report);
				break;

			case ConfigureNotify:
				if (report.xconfigure.window == win) {
					width = report.xconfigure.width;
					height = report.xconfigure.height;
					}
				break;

			case ButtonPress:
				break;

			case KeyPress:
				break;

			case MappingNotify:
				XRefreshKeyboardMapping ((XMappingEvent *) &report);
				break;

			case DestroyNotify:
				if (report.xdestroywindow.window == win) user_exit();
				break;

			case SelectionNotify:
				break;

			default:
				break;
			}
		}
	}

/*----------------------------------------------------------------------*\
\*----------------------------------------------------------------------*/

static unsigned long white,black;

struct labeled_color {
	unsigned short r,g,b;
	unsigned short t;
	char *s;
	unsigned long p;
	};

struct labeled_color label[] = {
	{0xff00,0x0000,0x0000,1,"      above 6000m ",0},
	{0xff00,0x0000,0x0000,1,"  5000m to  6000m ",0},
	{0xff00,0x1000,0x0000,1,"  4000m to  5000m ",0},
	{0xff00,0x2000,0x0000,1,"  3000m to  4000m ",0},
	{0xff00,0x3000,0x0000,1,"  2000m to  3000m ",0},
	{0xff00,0x4000,0x0000,1,"  1000m to  2000m ",0},
	{0xff00,0x5000,0x0000,0,"   900m to  1000m ",0},
	{0xff00,0x6000,0x0000,0,"   800m to   900m ",0},
	{0xff00,0x7000,0x0000,0,"   700m to   800m ",0},
	{0xff00,0x8000,0x0000,0,"   600m to   700m ",0},
	{0xff00,0x9000,0x0000,0,"   500m to   600m ",0},
	{0xff00,0xa000,0x0000,0,"   400m to   500m ",0},
	{0xff00,0xb000,0x0000,0,"   300m to   400m ",0},
	{0xff00,0xc000,0x0000,0,"   200m to   300m ",0},
	{0xff00,0xd000,0x0000,0,"   190m to   200m ",0},
	{0xff00,0xe000,0x0000,0,"   180m to   190m ",0},
	{0xff00,0xf000,0x0000,0,"   170m to   180m ",0},
	{0xff00,0xff00,0x0000,0,"   160m to   170m ",0},
	{0xf000,0xff00,0x0000,0,"   150m to   160m ",0},
	{0xe000,0xff00,0x0000,0,"   140m to   150m ",0},
	{0xd000,0xff00,0x0000,0,"   130m to   140m ",0},
	{0xc000,0xff00,0x0000,0,"   120m to   130m ",0},
	{0xb000,0xff00,0x0000,0,"   110m to   120m ",0},
	{0xa000,0xff00,0x0000,0,"   100m to   110m ",0},
	{0x9000,0xff00,0x0000,0,"    90m to   100m ",0},
	{0x8000,0xff00,0x0000,0,"    80m to    90m ",0},
	{0x7000,0xff00,0x0000,0,"    70m to    80m ",0},
	{0x6000,0xff00,0x0000,0,"    60m to    70m ",0},
	{0x5000,0xff00,0x0000,0,"    50m to    60m ",0},
	{0x4000,0xff00,0x0000,0,"    40m to    50m ",0},
	{0x3000,0xff00,0x0000,0,"    30m to    40m ",0},
	{0x2000,0xff00,0x0000,0,"    20m to    30m ",0},
	{0x1000,0xff00,0x0000,0,"    10m to    20m ",0},
	{0x0000,0xff00,0x0000,0,"     0m to    10m ",0},
	{0x0000,0xff00,0xff00,0,"   -10m to     0m ",0},
	{0x0000,0xf000,0xff00,0,"   -20m to   -10m ",0},
	{0x0000,0xe000,0xff00,0,"   -30m to   -20m ",0},
	{0x0000,0xd000,0xff00,0,"   -40m to   -30m ",0},
	{0x0000,0xc000,0xff00,1,"   -50m to   -40m ",0},
	{0x0000,0xb000,0xff00,1,"   -60m to   -50m ",0},
	{0x0000,0xa000,0xff00,1,"   -70m to   -60m ",0},
	{0x0000,0x9000,0xff00,1,"   -80m to   -70m ",0},
	{0x0000,0x8000,0xff00,1,"   -90m to   -80m ",0},
	{0x0000,0x7000,0xff00,1,"  -100m to   -90m ",0},
	{0x0000,0x6000,0xff00,1,"  -110m to  -100m ",0},
	{0x0000,0x5000,0xff00,1,"  -120m to  -110m ",0},
	{0x0000,0x4000,0xff00,1,"  -130m to  -120m ",0},
	{0x0000,0x3000,0xff00,1,"  -140m to  -130m ",0},
	{0x0000,0x2000,0xff00,1,"  -150m to  -140m ",0},
	{0x0000,0x1000,0xff00,1,"  -160m to  -150m ",0},
	{0x0000,0x0000,0xff00,1,"  -170m to  -160m ",0},
	{0x0000,0x0000,0xf000,1,"  -180m to  -170m ",0},
	{0x0000,0x0000,0xe000,1,"  -190m to  -180m ",0},
	{0x0000,0x0000,0xd000,1,"  -200m to  -190m ",0},
	{0x0000,0x0000,0xc000,1,"  -300m to  -200m ",0},
	{0x0000,0x0000,0xb000,1,"  -400m to  -300m ",0},
	{0x0000,0x0000,0xa000,1,"  -500m to  -400m ",0},
	{0x0000,0x0000,0x9000,1,"  -600m to  -500m ",0},
	{0x0000,0x0000,0x8000,1,"  -700m to  -600m ",0},
	{0x0000,0x0000,0x7000,1,"  -800m to  -700m ",0},
	{0x0000,0x0000,0x6000,1,"  -900m to  -800m ",0},
	{0x0000,0x0000,0x5000,1," -1000m to  -900m ",0},
	{0x0000,0x0000,0x4000,1," -2000m to -1000m ",0},
	{0x0000,0x0000,0x3000,1," -3000m to -2000m ",0},
	{0x0000,0x0000,0x2000,1," -4000m to -3000m ",0},
	{0x0000,0x0000,0x1000,1," -5000m to -4000m ",0},
	{0x0000,0x0000,0x0000,1,"     below -5000m ",0},
	{     0,     0,     0,0,                NULL,0}
	};

static unsigned long allocate_one_color (unsigned short r, unsigned short g, unsigned short b) {
	Colormap cmap;
	XColor cell;

	cmap = DefaultColormap (display,screen);
	cell.flags = DoRed | DoGreen | DoBlue;
	cell.red   = r;
	cell.green = g;
	cell.blue  = b;

	if (XAllocColor (display,cmap,&cell)) return (cell.pixel);
	else
		return (foreground);
	}

static void allocate_colors (void) {
	int i;

	white = WhitePixel (display,screen);
	black = BlackPixel (display,screen);
	for (i=0; label[i].s; i++) {
		label[i].p = allocate_one_color (label[i].r,label[i].g,label[i].b);
		}
	}

static void refresh_window (XExposeEvent *e) {
	int i,n,x,y,w,h;

	x = 0;
	y = 0;
	h = font_height + 2;
	for (i=0; label[i].s; i++) {
		n = strlen (label[i].s);
		w = n * font_width;

		XSetForeground (display,gc,label[i].p);
		XFillRectangle (display,win,gc,x,y,w+1,h+1);

		y += 1 + font_info->max_bounds.ascent;
		if (label[i].t) XSetForeground (display,gc,white);
		else XSetForeground (display,gc,black);
		XDrawString (display,win,gc,x,y,label[i].s,n);

		y += 1 + font_info->max_bounds.descent;
		if (y + font_height > height) {
			x += w;
			y = 0;
			}
		}
	XResizeWindow (display,win,width,height);
	}

/*----------------------------------------------------------------------*\
\*----------------------------------------------------------------------*/

