/* colorinfo.c *** X program to display colormap information */

#include <sys/stat.h>
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <math.h>
#include <unistd.h>
#include <X11/IntrinsicP.h>
#include <X11/Xmu/Editres.h>
#include <X11/cursorfont.h>
#include <X11/Intrinsic.h>
#include <X11/Xatom.h>
#include <Xm/Xm.h>
#include <Xm/ArrowB.h>
#include <Xm/CascadeB.h>
#include <Xm/CascadeBG.h>
#include <Xm/DrawingA.h>
#include <Xm/Form.h>
#include <Xm/Label.h>
#include <Xm/MainW.h>
#include <Xm/MessageB.h>
#include <Xm/PushB.h>
#include <Xm/RowColumn.h>
#include <Xm/ScrolledW.h>
#include <Xm/Text.h>
#include <Xm/TextF.h>
#include <Xm/ToggleB.h>
#include <X11/Xmu/StdCmap.h>

#define VERSION "Colorinfo Version 1.1 (4-9-93)"
#define WIDTH 115
#define HEIGHT 24
#define COLUMNS 8
#define ROWS 32
#define NCOLORS 256
#define NPLANES 8
#define NDATA 750
#define NRGBMAPS 10
#define NCOLORMAPWINDOWS 3
#define GRAPHWINWIDTH COLUMNS*WIDTH
#define GRAPHWINHEIGHT ROWS*HEIGHT
#define DATABASEFILE "/usr/lib/X11/rgb.txt"
#define MAXARGS 10
#define CMAPWINDOW appshellwindow

#define FLOATNUM 11

#define sign(x) (((x) < 0)?-1:1)

/* Function prototypes */
void (*ecaerrmsg)(char *fmt, ...);
int main(int argc, char **argv);
void adddata(Widget w, XtPointer clientdata, XtPointer calldata);
void allocateallpossible(void);
void black(Widget w, XtPointer clientdata, XtPointer calldata);
void clear(Widget w, XtPointer clientdata, XtPointer calldata);
void colors(Widget w, XtPointer clientdata, XtPointer calldata);
Widget createlabelbox(Widget parent, char *widgetname, char *label,
  char *value, XtCallbackProc callback, caddr_t clientdata);
Widget createlabelwidget(Widget parent, char *widgetname, char *label);
void data(Widget w, XtPointer clientdata, XtPointer calldata);
void defaultcm(Widget w, XtPointer clientdata, XtPointer calldata);
void definestdcmappopup(void);
void destroyWidget(Widget w, XtPointer clientdata, XtPointer calldata);
void doxmuall(Widget w, XtPointer clientdata, XtPointer calldata);
void doxstdcmap(Widget w, XtPointer clientdata, XtPointer calldata);
void helpcb(Widget w, XtPointer clientdata, XtPointer calldata);
void list(Widget w, XtPointer clientdata, XtPointer calldata);
void numberbasecb(Widget w, XtPointer clientdata, XtPointer calldata);
void print(Widget w, XtPointer clientdata, XtPointer calldata);
void querycolors(void);
void quit(Widget w, XtPointer clientdata, XtPointer calldata);
void repaintgraph(Widget w, XtPointer clientdata, XtPointer calldata);
void rescan(Widget w, XtPointer clientdata, XtPointer calldata);
void resetgraph(void);
void rgbstdmap(void);
void stdcmap(Widget w, XtPointer clientdata, XtPointer calldata);
void stdcmapcb(Widget w, XtPointer clientdata, XtPointer calldata);
void xerrmsg(char *fmt, ...);
int xerrorhandler(Display *dpy, XErrorEvent *event);
void xinfomsg(char *fmt, ...);
void xterrorhandler(char *message);

/* Structures */

typedef struct {
    char name[17];
    Colormap cmap;
    VisualID vid;
    Atom atom;
    int class;
    int n;
    int index;
} STDCMAP;

/* Global variables */

XtAppContext appcontext;
Display *display;
Widget appshell,mainwin,mainmenu,mainform,warningbox,infobox;
Widget helppopup,stdcmappopup=0;
Widget grapharea;
Window rootwindow,graphareawindow,appshellwindow,mainwindow,mainformwindow;
Arg args[MAXARGS];
Cardinal nargs;

int screen;
GC gc,gcwhite,gcblack,gccolor;
Cursor crosshair,watch;
XGCValues gcvalues;
Colormap cmap,curmap,newmap;
Pixmap apspix;

char string[BUFSIZ];
XmString cstring;
STDCMAP stdcmaps[NRGBMAPS];
static char *vname[]={
    "StaticGray","GrayScale",
    "StaticColor","PseudoColor",
    "TrueColor","DirectColor"};
Visual *defvisual;
VisualID defvisualid;
int height,width,defplanes,defvisualclass;
XColor colordef[NCOLORS];
unsigned long newcolors[NCOLORS],planemasks[NPLANES];
char colorname[NCOLORS][80];
char datacolorname[NDATA][80];
int redcolor[NDATA],greencolor[NDATA],bluecolor[NDATA];
int nrgbmaps=0,currgbmap=0,ndata,nplanes,strategy=1;
int databaseread=0;
int datareadonly=0,datastart=1,nalloc=0;
int printhex=0,windowmessage=0;

/* Define icons (Refer to as name_bits[]) */

#include "../../xorbit/aps.icon"

/* Define help text */

#include "colorinfo.hlp"

/**************************** main ****************************************/
int main(int argc, char **argv)
{
    Widget w,w1;

/* Constants and defaults */
/* Set up top level */
    XtToolkitInitialize();
    appcontext=XtCreateApplicationContext();

/* Get display parameters */
    display=XtOpenDisplay(appcontext,NULL,argv[0],"EvansApp",NULL,0,
      &argc,argv);
    if(display == NULL) {
	xerrmsg("Colorinfo initialization: Cannot open display");
	return(1);
    }
    screen=DefaultScreen(display);
    nplanes=DisplayPlanes(display,screen);
    rootwindow=RootWindow(display,screen);
    defplanes=DefaultDepth(display,screen);
    defvisual=DefaultVisual(display,screen);
    height=DisplayHeight(display,screen);
    width=DisplayWidth(display,screen);
    if(nplanes > NPLANES) {
	xerrmsg("%d planes are more than supported [%d]",
	  nplanes,NPLANES);
    }

/* Set error handlers */
    XtAppSetErrorHandler(appcontext,xterrorhandler);
    XtAppSetWarningHandler(appcontext,xterrorhandler);
    XSetErrorHandler(xerrorhandler);

/* DEBUG */
/*     XSynchronize(display,TRUE); */

/* Set icon */
    apspix=XCreatePixmapFromBitmapData(display,rootwindow,
      aps_bits,aps_width,aps_height,1,0,1);
    nargs=0;
    XtSetArg(args[nargs],XtNiconPixmap,apspix); nargs++;
    XtSetArg(args[nargs],XmNtitle,"Colorinfo"); nargs++; 
    appshell=XtAppCreateShell("colorinfo","EvansApp",
      applicationShellWidgetClass,display,args,nargs);

/* Enable Editres */
    XtAddEventHandler(appshell,(EventMask)NULL,TRUE,_XEditResCheckMessages,
      NULL);

/* Define main window */
    nargs=0;
    mainwin=XmCreateMainWindow(appshell,"mainWindow",args,nargs);
    XtManageChild(mainwin);

/* Define menu bar */
    nargs=0;
    mainmenu=XmCreateMenuBar(mainwin,"mainMenu",args,nargs);
    XtManageChild(mainmenu);

/* Define options button */
    nargs=0;
    XtSetArg(args[nargs],XmNtearOffModel,XmTEAR_OFF_ENABLED); nargs++;
    w=XmCreatePulldownMenu(mainmenu,"optionsMenu",args,nargs);

    nargs=0;
    w1=XmCreatePushButton(w,"Rescan",args,nargs);
    XtManageChild(w1);
    XtAddCallback(w1,XmNactivateCallback,rescan,(caddr_t)NULL);

    nargs=0;
    w1=XmCreatePushButton(w,"Show Available Cells",args,nargs);
    XtManageChild(w1);
    XtAddCallback(w1,XmNactivateCallback,black,(caddr_t)NULL);

    nargs=0;
    w1=XmCreatePushButton(w,"Show Color Labels",args,nargs);
    XtManageChild(w1);
    XtAddCallback(w1,XmNactivateCallback,data,(caddr_t)NULL);

    nargs=0;
    w1=XmCreatePushButton(w,"Show Database Colors",args,nargs);
    XtManageChild(w1);
    XtAddCallback(w1,XmNactivateCallback,adddata,(caddr_t)NULL);

    nargs=0;
    w1=XmCreatePushButton(w,"Free Allocated Cells",args,nargs);
    XtManageChild(w1);
    XtAddCallback(w1,XmNactivateCallback,clear,(caddr_t)NULL);

    nargs=0;
    w1=XmCreatePushButton(w,"Show Current Colormap",args,nargs);
    XtManageChild(w1);
    XtAddCallback(w1,XmNactivateCallback,list,(caddr_t)NULL);

    nargs=0;
    w1=XmCreatePushButton(w,"Set Default Colormap",args,nargs);
    XtManageChild(w1);
    XtAddCallback(w1,XmNactivateCallback,defaultcm,(caddr_t)NULL);

    nargs=0;
    w1=XmCreatePushButton(w,"Set Standard Colormaps...",args,nargs);
    XtManageChild(w1);
    XtAddCallback(w1,XmNactivateCallback,stdcmap,(caddr_t)NULL);

    nargs=0;
    w1=XmCreatePushButton(w,"Print Colors",args,nargs);
    XtManageChild(w1);
    XtAddCallback(w1,XmNactivateCallback,colors,(caddr_t)NULL);

    nargs=0;
    w1=XmCreatePushButton(w,"Print Colormap Summary",args,nargs);
    XtManageChild(w1);
    XtAddCallback(w1,XmNactivateCallback,print,(caddr_t)NULL);

    nargs=0;
    w1=XmCreatePushButton(w,"Run XmuAllStandardColormaps",args,nargs);
    XtManageChild(w1);
    XtAddCallback(w1,XmNactivateCallback,doxmuall,(caddr_t)NULL);

    nargs=0;
    w1=XmCreatePushButton(w,"Run Xstdcmap",args,nargs);
    XtManageChild(w1);
    XtAddCallback(w1,XmNactivateCallback,doxstdcmap,(caddr_t)NULL);

    nargs=0;
    w1=XmCreatePushButton(w,"Quit",args,nargs);
    XtManageChild(w1);
    XtAddCallback(w1,XmNactivateCallback,quit,(caddr_t)NULL);

    nargs=0;
    XtSetArg(args[nargs],XmNsubMenuId,w); nargs++;
    w1=XmCreateCascadeButton(mainmenu,"Options",args,nargs);
    XtManageChild(w1);

/* Define number base button */
    nargs=0;
    XtSetArg(args[nargs],XmNtearOffModel,XmTEAR_OFF_ENABLED); nargs++;
    w=XmCreatePulldownMenu(mainmenu,"numberbaseMenu",args,nargs);

    nargs=0;
    w1=XmCreatePushButton(w,"Decimal",args,nargs);
    XtManageChild(w1);
    XtAddCallback(w1,XmNactivateCallback,numberbasecb,(caddr_t)0);

    nargs=0;
    w1=XmCreatePushButton(w,"Hexadecimal",args,nargs);
    XtManageChild(w1);
    XtAddCallback(w1,XmNactivateCallback,numberbasecb,(caddr_t)1);

    nargs=0;
    XtSetArg(args[nargs],XmNsubMenuId,w); nargs++;
    w1=XmCreateCascadeButton(mainmenu,"Number Base",args,nargs);
    XtManageChild(w1);

/* Define help button */
    nargs=0;
    XtSetArg(args[nargs],XmNtearOffModel,XmTEAR_OFF_ENABLED); nargs++;
    w=XmCreatePulldownMenu(mainmenu,"helpMenu",args,nargs);

    nargs=0;
    w1=XmCreatePushButton(w,"Overview",args,nargs);
    XtManageChild(w1);
    XtAddCallback(w1,XmNactivateCallback,helpcb,(caddr_t)0);

    nargs=0;
    w1=XmCreatePushButton(w,"Version",args,nargs);
    XtManageChild(w1);
    XtAddCallback(w1,XmNactivateCallback,helpcb,(caddr_t)1);

    nargs=0;
    XtSetArg(args[nargs],XmNsubMenuId,w); nargs++;
    w1=XmCreateCascadeButton(mainmenu,"Help",args,nargs);
    XtManageChild(w1);

    nargs=0;
    XtSetArg(args[nargs],XmNmenuHelpWidget,w1); nargs++;
    XtSetValues(mainmenu,args,nargs);

/* Define form for rest of main window */
    nargs=0;
    mainform=XmCreateForm(mainwin,"form",args,nargs);
    XtManageChild(mainform);

/* Define graph drawing area */
    nargs=0;
    XtSetArg(args[nargs],XmNleftAttachment,XmATTACH_FORM); nargs++;
    XtSetArg(args[nargs],XmNrightAttachment,XmATTACH_FORM); nargs++;
    XtSetArg(args[nargs],XmNtopAttachment,XmATTACH_FORM); nargs++;
    XtSetArg(args[nargs],XmNbottomAttachment,XmATTACH_FORM); nargs++;
    XtSetArg(args[nargs],XmNheight,GRAPHWINHEIGHT); nargs++;
    XtSetArg(args[nargs],XmNwidth,GRAPHWINWIDTH); nargs++;
    grapharea=XmCreateDrawingArea(mainform,"graphArea",args,nargs);
    XtManageChild(grapharea);

/* Set main window areas */
    XmMainWindowSetAreas(mainwin,mainmenu,NULL,NULL,NULL,mainform);

/* Realize */
    XtRealizeWidget(appshell);

/* Get window ids */
    graphareawindow=XtWindow(grapharea);
    appshellwindow=XtWindow(appshell);
    mainwindow=XtWindow(mainwin);
    mainformwindow=XtWindow(mainform);
    XtAddCallback(grapharea,XmNexposeCallback,repaintgraph,(caddr_t)NULL);
    XtAddCallback(grapharea,XmNresizeCallback,repaintgraph,(caddr_t)NULL);

/* Tell window manager about windows that need their own colormaps */
/*
  ncolormapwindows=0;
  colormapwindows[ncolormapwindows++]=mainwindow;
  colormapwindows[ncolormapwindows++]=mainformwindow;
  colormapwindows[ncolormapwindows++]=graphareawindow;
  err=XSetWMColormapWindows(display,appshellwindow,colormapwindows,
  ncolormapwindows);
  */

/* Define cursors */
    crosshair=XCreateFontCursor(display,XC_crosshair);
    watch=XCreateFontCursor(display,XC_watch);

/* Define graphics contexts */
    gcvalues.background=WhitePixel(display,screen);
    gcvalues.foreground=BlackPixel(display,screen);
    gc=XCreateGC(display,rootwindow,
      GCBackground|GCForeground,&gcvalues);
    gcvalues.graphics_exposures = False;
    gcblack=XCreateGC(display,graphareawindow,
      GCForeground|GCBackground|GCGraphicsExposures,
      &gcvalues);
    gccolor=XCreateGC(display,graphareawindow,
      GCForeground|GCBackground|GCGraphicsExposures,
      &gcvalues);
    gcvalues.background=BlackPixel(display,screen);
    gcvalues.foreground=WhitePixel(display,screen);
    gcwhite=XCreateGC(display,graphareawindow,
      GCForeground|GCBackground|GCGraphicsExposures,
      &gcvalues);

/* Get colors */
    curmap=cmap=DefaultColormap(display,screen);
    querycolors();

/* Start */
    windowmessage=1;
    XtAppMainLoop(appcontext);
    return(0);
}
/**************************** adddata *************************************/
void adddata(Widget w, XtPointer clientdata, XtPointer calldata)
{
    XColor newcolordef;
    int i,j,index,alldone=0;
    int duplicated;

/* Read database if necessary */
    if(!databaseread) {
	datareadonly=1;
	data((Widget)NULL,(caddr_t)NULL,(caddr_t)NULL);
    }
/* See how many can be allocated and allocate the maximum */
    if(nalloc == 0) {
	nalloc=NCOLORS;
	while(1) {
	    if(XAllocColorCells(display,curmap,False,planemasks,0,
	      newcolors,nalloc))
	      break;
	    nalloc--;
	    if(nalloc <= 0) {
		xerrmsg("No more color cells to allocate");
		return;
	    }
	}
    }
/* Get color names from the database  */
    if(++datastart > ndata) datastart=0;
    index=datastart;
    for(i=0; i < nalloc; i++, index++) {
/* Check if this color is duplicated */	
	duplicated=1;
	while(duplicated && !alldone) {
	    duplicated=0;
	    for(j=index-1; j >= 0; j--) {
		if(redcolor[j] == redcolor[index] &&
		  greencolor[j] == greencolor[index] &&
		  bluecolor[j] == bluecolor[index]) {
		    index++;
		    if(index >= ndata-1) alldone=1;
		    duplicated=1;
		    break;
		}
	    }
	}
	if(alldone) break;
/* Define and store color */
	if(XParseColor(display,curmap,datacolorname[index],&newcolordef)) {
	    newcolordef.pixel=newcolors[i];
	    newcolordef.flags=DoRed|DoGreen|DoBlue;
	    XStoreColor(display,curmap,&newcolordef);
	}
	else {
	    xerrmsg("Error finding color cell for: %s",
	      datacolorname[index]);
	}
    }
/* Query the colors again */
    querycolors();
    datastart=index;
    resetgraph();
}
/**************************** allocateallpossible *************************/
void allocateallpossible(void)
{
    XColor newcolordef;
    int i,j;

    if(nalloc == 0) {
	nalloc=NCOLORS;
	while(1) {
	    if(XAllocColorCells(display,curmap,False,planemasks,0,
	      newcolors,nalloc)) break;
	    nalloc--;
	    if(nalloc <= 0) {
		xerrmsg("No more color cells to allocate");
		return;
	    }
	}
    }
    for(i=0; i < nalloc; i++) {
	j=newcolors[i];
	newcolordef.red=colordef[j].red;
	newcolordef.green=colordef[j].green;
	newcolordef.blue=colordef[j].blue;
	newcolordef.pixel=j;
	newcolordef.flags=DoRed|DoGreen|DoBlue;
	XStoreColor(display,curmap,&newcolordef);
    }
}
/**************************** black ***************************************/
void black(Widget w, XtPointer clientdata, XtPointer calldata)
{
    XColor newcolordef;
    int i;

/* Read database if necessary */
    if(!databaseread) {
	datareadonly=1;
	data((Widget)NULL,(caddr_t)NULL,(caddr_t)NULL);
    }
/* See how many can be allocated and allocate the maximum */
    if(nalloc == 0) {
	nalloc=NCOLORS;
	while(1) {
	    if(XAllocColorCells(display,curmap,False,planemasks,0,newcolors,
	      nalloc)) break;
	    nalloc--;
	    if(nalloc <= 0) {
		xerrmsg("No more color cells to allocate");
		return;
	    }
	}
    }
/* Define and store black */
    for(i=0; i < nalloc; i++) {
	newcolordef.red=0x100;
	newcolordef.green=0x100;
	newcolordef.blue=0x100;
	newcolordef.pixel=newcolors[i];
	newcolordef.flags=DoRed|DoGreen|DoBlue;
	XStoreColor(display,curmap,&newcolordef);
    }
/* Query the colors again */
    querycolors();
    resetgraph();
/* Free the colors so they are available */
    if(nalloc > 0) {
	XFreeColors(display,curmap,newcolors,nalloc,0);
	nalloc=0;
    }
}
/**************************** clear ***************************************/
void clear(Widget w, XtPointer clientdata, XtPointer calldata)
{
    if(nalloc <= 0) {
	xerrmsg("No allocated color cells to free");
	return;
    }
    XFreeColors(display,curmap,newcolors,nalloc,0);
    nalloc=0;
}
/**************************** colors **************************************/
void colors(Widget w, XtPointer clientdata, XtPointer calldata)
{
    int i;

/* Print RGB values */
    printf("\nColors:\n\n");
    for(i=0; i < NCOLORS; i++) {
	if(printhex) {
	    printf("%3d Red=%4.4x Green=%4.4x Blue=%4.4x\n",
	      i,colordef[i].red,colordef[i].green,colordef[i].blue);
	}
	else {
	    printf("%3d Red=%3d Green=%3d Blue=%3d\n",i,
	      colordef[i].red>>8,colordef[i].green>>8,colordef[i].blue>>8);
	}
    }
}
/**************************** createlabelbox ******************************/
Widget createlabelbox(Widget parent, char *widgetname, char *label,
  char *value, XtCallbackProc callback, caddr_t clientdata)
{
    Widget w0,w1,w2;
    int len;
    char name[64];

/* Create container */
    nargs=0;
    XtSetArg(args[nargs],XmNorientation,XmHORIZONTAL); nargs++;
    w0=XmCreateRowColumn(parent,widgetname,args,nargs);
    XtManageChild(w0);
/* Create label */    
    sprintf(name,"%sLabel\0",widgetname);
    cstring=XmStringCreateSimple(label);
    nargs=0;
    XtSetArg(args[nargs],XmNlabelString,cstring); nargs++;
    w1=XmCreateLabel(w0,name,args,nargs);
    XmStringFree(cstring);
    XtManageChild(w1);
/* Create text box */
    sprintf(name,"%sTextField\0",widgetname);
    len=strlen(value);
    nargs=0;
    XtSetArg(args[nargs],XmNcursorPosition,len); nargs++;
    XtSetArg(args[nargs],XmNvalue,value); nargs++;
/*    XtSetArg(args[nargs],XmNcolumns,FLOATNUM); nargs++;*/
    w2=XmCreateTextField(w0,name,args,nargs);
    XtManageChild(w2);
    XtAddCallback(w2,XmNactivateCallback,callback,clientdata);
/* Return */
    return(w0);
}
/**************************** createlabelwidget ***************************/
Widget createlabelwidget(Widget parent, char *widgetname, char *label)
{
    Widget w0,w1;
    char name[64];

/* Create container */
    nargs=0;
    XtSetArg(args[nargs],XmNorientation,XmHORIZONTAL); nargs++;
    w0=XmCreateRowColumn(parent,widgetname,args,nargs);
    XtManageChild(w0);
/* Create label */    
    sprintf(name,"%sLabel\0",widgetname);
    cstring=XmStringCreateSimple(label);
    nargs=0;
    XtSetArg(args[nargs],XmNlabelString,cstring); nargs++;
    w1=XmCreateLabel(w0,name,args,nargs);
    XmStringFree(cstring);
    XtManageChild(w1);
/* Return */
    return(w0);
}
/**************************** data ****************************************/
void data(Widget w, XtPointer clientdata, XtPointer calldata)
{
    int i,j,r,g,b,iend;
    FILE *file;

/* Read database */
    if(!databaseread) {
	file=fopen(DATABASEFILE,"r");
	if(file == (FILE *)NULL) {
	    xerrmsg("Cannot open database file %s",DATABASEFILE);
	    return;
	}
	clearerr(file);
	for(ndata=0, iend=0; ndata < NDATA; ndata++) {
	    fgets(string,79,file);
	    if(feof(file) | ferror(file)) {
		iend=1;
		break;
	    }
	    i=sscanf(string,"%d%d%d %[^\n]",&redcolor[ndata],
	      &greencolor[ndata],&bluecolor[ndata],datacolorname[ndata]);
	}
	fclose(file);
	if(!iend) {
	    xerrmsg("Stopping before end of database file "
	      "[%d entries completed]",NDATA);
	}
    }
/* Search for matches */
    for(i=0; i < NCOLORS; i++) {
	for(j=0; j < NDATA; j++) {
	    r=(colordef[i].red>>8);
	    g=(colordef[i].green>>8);
	    b=(colordef[i].blue>>8);
	    if(r == redcolor[j] && g == greencolor[j] && b == bluecolor[j]) {
		strcpy(colorname[i],datacolorname[j]);
		break;
	    }
	}
    }
    if(!datareadonly) resetgraph();
    datareadonly=0;
    databaseread=1;
}
/**************************** defaultcm ***********************************/
void defaultcm(Widget w, XtPointer clientdata, XtPointer calldata)
{
    XFreeColors(display,curmap,newcolors,nalloc,0);
    nalloc=0;
    if(curmap == newmap) XFreeColormap(display,newmap);
    XSetWindowColormap(display,CMAPWINDOW,cmap);
    curmap=cmap;
    querycolors();
    resetgraph();
}
/**************************** definestdcmappopup **************************/
void definestdcmappopup(void)
{
    Widget wparent,w,w1;
    int i;

/* Free colors first so it can have some to create the popup */
    if(nalloc > 0) {
	XFreeColors(display,curmap,newcolors,nalloc,0);
	nalloc=0;
    }

/* Define popup dialog box */
    cstring=XmStringCreateSimple("Standard Colormaps");
    nargs=0;
    XtSetArg(args[nargs],XmNdialogTitle,cstring); nargs++;
    stdcmappopup=XmCreateFormDialog(mainwin,"optPopup",args,nargs);
    XmStringFree(cstring);

/* Define quit button */
    nargs=0;
    XtSetArg(args[nargs],XmNtopAttachment,XmATTACH_FORM); nargs++;
    XtSetArg(args[nargs],XmNleftAttachment,XmATTACH_FORM); nargs++;
    w=XmCreatePushButton(stdcmappopup,"Remove",args,nargs);
    XtManageChild(w);
    XtAddCallback(w,XmNactivateCallback,stdcmapcb,(caddr_t)101);

/* Define set button */
    nargs=0;
    XtSetArg(args[nargs],XmNtopAttachment,XmATTACH_FORM); nargs++;
    XtSetArg(args[nargs],XmNleftAttachment,XmATTACH_WIDGET); nargs++;
    XtSetArg(args[nargs],XmNleftWidget,w); nargs++;
    w=XmCreatePushButton(stdcmappopup,"Set Colormap",args,nargs);
    XtManageChild(w);
    XtAddCallback(w,XmNactivateCallback,stdcmapcb,(caddr_t)102);

/* Define label */
    wparent=w;
    w=createlabelwidget(stdcmappopup,"label","Available Colormaps:");
    nargs=0;
    XtSetArg(args[nargs],XmNtopAttachment,XmATTACH_WIDGET); nargs++;
    XtSetArg(args[nargs],XmNtopWidget,wparent); nargs++;
    XtSetArg(args[nargs],XmNleftAttachment,XmATTACH_FORM); nargs++;
    XtSetArg(args[nargs],XmNrightAttachment,XmATTACH_FORM); nargs++;
    XtSetValues(w,args,nargs);
    XtManageChild(w);

/* Define RGB maps radiobox */
    nargs=0;
    XtSetArg(args[nargs],XmNtopAttachment,XmATTACH_WIDGET); nargs++;
    XtSetArg(args[nargs],XmNtopWidget,w); nargs++;
    XtSetArg(args[nargs],XmNleftAttachment,XmATTACH_FORM); nargs++;
    XtSetArg(args[nargs],XmNrightAttachment,XmATTACH_FORM); nargs++;
    XtSetArg(args[nargs],XmNorientation,XmVERTICAL); nargs++;
    XtSetArg(args[nargs],XmNpacking,XmPACK_TIGHT); nargs++;
    wparent=XmCreateRadioBox(stdcmappopup,"rgbmapButtons",args,nargs);
    XtManageChild(wparent);

    for(i=0; i < nrgbmaps; i++) {
	sprintf(string,"%16s %d   Colormap: %6lx   VisualID: %6lx   Type: %s ",
	  stdcmaps[i].name,stdcmaps[i].n,stdcmaps[i].cmap,stdcmaps[i].vid,
	  vname[stdcmaps[i].class]);
	nargs=0;
	w1=XmCreateToggleButton(wparent,string,args,nargs);
	XtManageChild(w1);
	XtAddCallback(w1,XmNvalueChangedCallback,stdcmapcb,
	  (caddr_t)stdcmaps[i].index);
	XmToggleButtonSetState(w1,currgbmap==i,TRUE);
    }

/* Define label */
    w=createlabelwidget(stdcmappopup,"label","Procedure:");
    nargs=0;
    XtSetArg(args[nargs],XmNtopAttachment,XmATTACH_WIDGET); nargs++;
    XtSetArg(args[nargs],XmNtopWidget,wparent); nargs++;
    XtSetArg(args[nargs],XmNleftAttachment,XmATTACH_FORM); nargs++;
    XtSetArg(args[nargs],XmNrightAttachment,XmATTACH_FORM); nargs++;
    XtSetValues(w,args,nargs);
    XtManageChild(w);

/* Define strategies radiobox */
    nargs=0;
    XtSetArg(args[nargs],XmNtopAttachment,XmATTACH_WIDGET); nargs++;
    XtSetArg(args[nargs],XmNtopWidget,w); nargs++;
    XtSetArg(args[nargs],XmNleftAttachment,XmATTACH_FORM); nargs++;
    XtSetArg(args[nargs],XmNrightAttachment,XmATTACH_FORM); nargs++;
    XtSetArg(args[nargs],XmNorientation,XmVERTICAL); nargs++;
    XtSetArg(args[nargs],XmNpacking,XmPACK_TIGHT); nargs++;
    wparent=XmCreateRadioBox(stdcmappopup,"strategyButtons",args,nargs);
    XtManageChild(wparent);
    
    nargs=0;
    w1=XmCreateToggleButton(wparent,"Install Defined Map",args,nargs);
    XtManageChild(w1);
    XtAddCallback(w1,XmNvalueChangedCallback,stdcmapcb,(caddr_t)103);
    XmToggleButtonSetState(w1,strategy==0,TRUE);

    nargs=0;
    w1=XmCreateToggleButton(wparent,"Create New Map",args,nargs);
    XtManageChild(w1);
    XtAddCallback(w1,XmNvalueChangedCallback,stdcmapcb,(caddr_t)104);
    XmToggleButtonSetState(w1,strategy==1,TRUE);

    nargs=0;
    w1=XmCreateToggleButton(wparent,"Use Default Map",args,nargs);
    XtManageChild(w1);
    XtAddCallback(w1,XmNvalueChangedCallback,stdcmapcb,(caddr_t)105);
    XmToggleButtonSetState(w1,strategy==2,TRUE);

/* Manage it */
    XtManageChild(stdcmappopup);
}
/**************************** doxmuall ************************************/
void doxmuall(Widget w, XtPointer clientdata, XtPointer calldata)
{
    XDefineCursor(display,mainwindow,watch);
    XFlush(display);
    if(!XmuAllStandardColormaps(display)) {
	xerrmsg("XmuAllStandardColormaps failed!\n"
	  "(Previous maps may be gone)");
    }
    else {
	xinfomsg("Any previous maps were overwritten");
    }
    XUndefineCursor(display,mainwindow);
}
/**************************** doxstdcmap **********************************/
void doxstdcmap(Widget w, XtPointer clientdata, XtPointer calldata)
{
    FILE *tmpfile;
    struct stat statinfo;
    char buf[BUFSIZ];
    char *tmpfilename="/tmp/colorinfo.XXXXXX";
    int size,filesize;

    XDefineCursor(display,mainwindow,watch);
    XFlush(display);
/* Run command */
    mktemp(tmpfilename);
    sprintf(string,"xstdcmap -all -verbose > %s 2>&1",tmpfilename);
    system(string);
/* Get output */
    if(stat(tmpfilename,&statinfo) == -1 ||
      (tmpfile=fopen(tmpfilename,"r")) == NULL) {
	xerrmsg("Error opening %s",tmpfilename);
    }
    else {
	filesize=statinfo.st_size;
	size=((BUFSIZ-1) < filesize)?(BUFSIZ-1):filesize;
	fread(buf,1,size,tmpfile);
	fclose(tmpfile);
	buf[size]='\0';
	xinfomsg(buf);
    }
    unlink(tmpfilename);
    XUndefineCursor(display,mainwindow);
}
/**************************** helpcb **************************************/
void helpcb(Widget w, XtPointer clientdata, XtPointer calldata)
{
    Widget w1,wparent;
    int n;
    n=(int)clientdata;

    switch(n) {
    case 0:
	cstring=XmStringCreateSimple("Help");
	nargs=0;
	XtSetArg(args[nargs],XmNdialogTitle,cstring); nargs++;
	helppopup=XmCreateFormDialog(mainwin,"optPopup",args,nargs);
	XmStringFree(cstring);
	
	nargs=0;
	XtSetArg(args[nargs],XmNtopAttachment,XmATTACH_FORM); nargs++;
	XtSetArg(args[nargs],XmNleftAttachment,XmATTACH_FORM); nargs++;
	w1=XmCreatePushButton(helppopup,"Remove",args,nargs);
	XtManageChild(w1);
	XtAddCallback(w1,XmNactivateCallback,helpcb,(caddr_t)2);

	wparent=w1;
	nargs=0;
	XtSetArg(args[nargs],XmNtopAttachment,XmATTACH_WIDGET); nargs++;
	XtSetArg(args[nargs],XmNtopWidget,wparent); nargs++;
	XtSetArg(args[nargs],XmNleftAttachment,XmATTACH_FORM); nargs++;
	XtSetArg(args[nargs],XmNeditMode,XmMULTI_LINE_EDIT); nargs++;
	XtSetArg(args[nargs],XmNeditable,FALSE); nargs++;
	XtSetArg(args[nargs],XmNrows,25); nargs++;
	XtSetArg(args[nargs],XmNcolumns,72); nargs++;
	w1=XmCreateScrolledText(helppopup,"scrolledHelp",args,nargs);
        XmTextSetString(w1,helptext);
	XtManageChild(w1);

	XtManageChild(helppopup);
	break;
    case 1:
	xinfomsg(VERSION);
	break;
    case 2:
	XtDestroyWidget(helppopup);
	break;
    }
}
/**************************** list ****************************************/
void list(Widget w, XtPointer clientdata, XtPointer calldata)
{
    Colormap *colormap;
    int nmaps,i,l;

    colormap=XListInstalledColormaps(display,CMAPWINDOW,&nmaps);
    sprintf(string,"%d Installed Colormap(s):",nmaps);
    for(i=0; i < nmaps; i++) {
	l=strlen(string);
	sprintf(string+l," %lx",colormap[i]);
    }
    l=strlen(string);
    sprintf(string+l,"\nCurrently Set Colormap: %lx",curmap);
    xinfomsg(string);
    XFree((caddr_t)colormap);
}
/**************************** numberbasecb ********************************/
void numberbasecb(Widget w, XtPointer clientdata, XtPointer calldata)
{
    printhex=(int)clientdata;
    resetgraph();
}
/**************************** print ***************************************/
void print(Widget w, XtPointer clientdata, XtPointer calldata)
{
    int i,j,k,err,numdepths,numvisuals,nmaps;
    int *depthslist;
    XStandardColormap *colormaps;
    XVisualInfo vtemplet,*vinfo=NULL;

    printf("\nColorinfo\n\n");
/* Print defaults */
    printf("Screen Width: %d\n",width);
    printf("Screen Height: %d\n",height);
    printf("Default Depth: %d\n",defplanes);
    printf("Default Colormap: %lx\n",cmap);
    printf("Default Visual: %p\n",defvisual);
    printf("\n");
/* Get depths */
    depthslist=XListDepths(display,screen,&numdepths);
    if(depthslist == NULL) {
	xerrmsg("Error finding available depths");
	return;
    }
    printf("Available depth(s):");
    for(i=0; i < numdepths; i++) {
	printf(" %d",depthslist[i]);
    }
    printf("\n");
/* Get visuals */
    vtemplet.screen=screen;
    for(i=0; i < numdepths; i++) {
	printf("\nDepth %d:\n",depthslist[i]);
	vtemplet.depth=depthslist[i];
	for(j=5; j >= 0; j--) {
	    vtemplet.class=j;
	    vinfo=XGetVisualInfo(display,
	      VisualScreenMask|VisualDepthMask|VisualClassMask,
	      &vtemplet,&numvisuals);
	    if(vinfo != NULL) {
		for(k=0; k < numvisuals; k++) {
		    printf("  Colormap Size: %d  Bits Per Pixel: %d",
		      vinfo[k].colormap_size,vinfo[k].bits_per_rgb);
		    printf("  Visual ID: %lx  Class: %s",
		      vinfo[k].visualid,vname[j]);
		    if(vinfo[k].visual == defvisual) {
			defvisualid=vinfo[k].visualid;
			defvisualclass=j;
			printf(" [Default]");
		    }
		    printf("\n");
		}
	    }
	}
    }
/* Get standard color maps */
    printf("\nStandard Maps:\n\n");
    err=XGetRGBColormaps(display,rootwindow,
      &colormaps,&nmaps,XA_RGB_DEFAULT_MAP);
    if(err == 0) nmaps=0;
    printf("There are %d maps with property RGB_DEFAULT_MAP\n",nmaps);
    for(i=0; i < nmaps; i++) {
	printf("  Colormap %d: %lx\n",i,colormaps[i].colormap);
	printf("    visualid: %lx\n",colormaps[i].visualid);
	printf("    base_pixel: %ld\n",colormaps[i].base_pixel);
	printf("    red_max: %ld\n",colormaps[i].red_max);
	printf("    red_mult: %ld\n",colormaps[i].red_mult);
	printf("    green_max: %ld\n",colormaps[i].green_max);
	printf("    green_mult: %ld\n",colormaps[i].green_mult);
	printf("    blue_max: %ld\n",colormaps[i].blue_max);
	printf("    blue_mult: %ld\n",colormaps[i].blue_mult);
    }
    err=XGetRGBColormaps(display,rootwindow,
      &colormaps,&nmaps,XA_RGB_BEST_MAP);
    if(err == 0) nmaps=0;
    printf("There are %d maps with property RGB_BEST_MAP\n",nmaps);
    for(i=0; i < nmaps; i++) {
	printf("  Colormap %d: %lx\n",i,colormaps[i].colormap);
	printf("    visualid: %lx\n",colormaps[i].visualid);
	printf("    base_pixel: %ld\n",colormaps[i].base_pixel);
	printf("    red_max: %ld\n",colormaps[i].red_max);
	printf("    red_mult: %ld\n",colormaps[i].red_mult);
	printf("    green_max: %ld\n",colormaps[i].green_max);
	printf("    green_mult: %ld\n",colormaps[i].green_mult);
	printf("    blue_max: %ld\n",colormaps[i].blue_max);
	printf("    blue_mult: %lx\n",colormaps[i].blue_mult);
    }
    err=XGetRGBColormaps(display,rootwindow,
      &colormaps,&nmaps,XA_RGB_RED_MAP);
    if(err == 0) nmaps=0;
    printf("There are %d maps with property RGB_RED_MAP\n",nmaps);
    for(i=0; i < nmaps; i++) {
	printf("  Colormap %d: %lx\n",i,colormaps[i].colormap);
	printf("    visualid: %lx\n",colormaps[i].visualid);
	printf("    base_pixel: %ld\n",colormaps[i].base_pixel);
	printf("    red_max: %ld\n",colormaps[i].red_max);
	printf("    red_mult: %ld\n",colormaps[i].red_mult);
	printf("    green_max: %ld\n",colormaps[i].green_max);
	printf("    green_mult: %ld\n",colormaps[i].green_mult);
	printf("    blue_max: %ld\n",colormaps[i].blue_max);
	printf("    blue_mult: %lx\n",colormaps[i].blue_mult);
    }
    err=XGetRGBColormaps(display,rootwindow,
      &colormaps,&nmaps,XA_RGB_GREEN_MAP);
    if(err == 0) nmaps=0;
    printf("There are %d maps with property RGB_GREEN_MAP\n",nmaps);
    for(i=0; i < nmaps; i++) {
	printf("  Colormap %d: %lx\n",i,colormaps[i].colormap);
	printf("    visualid: %lx\n",colormaps[i].visualid);
	printf("    base_pixel: %ld\n",colormaps[i].base_pixel);
	printf("    red_max: %ld\n",colormaps[i].red_max);
	printf("    red_mult: %ld\n",colormaps[i].red_mult);
	printf("    green_max: %ld\n",colormaps[i].green_max);
	printf("    green_mult: %ld\n",colormaps[i].green_mult);
	printf("    blue_max: %ld\n",colormaps[i].blue_max);
	printf("    blue_mult: %lx\n",colormaps[i].blue_mult);
    }
    err=XGetRGBColormaps(display,rootwindow,
      &colormaps,&nmaps,XA_RGB_BLUE_MAP);
    if(err == 0) nmaps=0;
    printf("There are %d maps with property RGB_BLUE_MAP\n",nmaps);
    for(i=0; i < nmaps; i++) {
	printf("  Colormap %d: %lx\n",i,colormaps[i].colormap);
	printf("    visualid: %lx\n",colormaps[i].visualid);
	printf("    base_pixel: %ld\n",colormaps[i].base_pixel);
	printf("    red_max: %ld\n",colormaps[i].red_max);
	printf("    red_mult: %ld\n",colormaps[i].red_mult);
	printf("    green_max: %ld\n",colormaps[i].green_max);
	printf("    green_mult: %ld\n",colormaps[i].green_mult);
	printf("    blue_max: %ld\n",colormaps[i].blue_max);
	printf("    blue_mult: %lx\n",colormaps[i].blue_mult);
    }
    err=XGetRGBColormaps(display,rootwindow,
      &colormaps,&nmaps,XA_RGB_GRAY_MAP);
    if(err == 0) nmaps=0;
    printf("There are %d maps with property RGB_GRAY_MAP\n",nmaps);
    for(i=0; i < nmaps; i++) {
	printf("  Colormap %d: %lx\n",i,colormaps[i].colormap);
	printf("    visualid: %lx\n",colormaps[i].visualid);
	printf("    base_pixel: %ld\n",colormaps[i].base_pixel);
	printf("    red_max: %ld\n",colormaps[i].red_max);
	printf("    red_mult: %ld\n",colormaps[i].red_mult);
	printf("    green_max: %ld\n",colormaps[i].green_max);
	printf("    green_mult: %ld\n",colormaps[i].green_mult);
	printf("    blue_max: %ld\n",colormaps[i].blue_max);
	printf("    blue_mult: %lx\n",colormaps[i].blue_mult);
    }
    XFree((caddr_t)colormaps);
    XFree((caddr_t)depthslist);
    XFree((caddr_t)vinfo);
}
/**************************** querycolors *********************************/
void querycolors(void)
{
    int i;

    for(i=0; i < NCOLORS; i++) {
	colordef[i].pixel=i;
	colordef[i].red=0;
	colordef[i].green=0;
	colordef[i].blue=0;
	colordef[i].flags=DoRed|DoGreen|DoBlue;     /* Not necessary */
	colorname[i][0]='\0';
    }
    XQueryColors(display,curmap,colordef,NCOLORS);
}
/**************************** quit ****************************************/
void quit(Widget w, XtPointer clientdata, XtPointer calldata)
{
    XtDestroyWidget(appshell);
    exit(0);
}
/**************************** destroyWidget ****************************************/
void destroyWidget(Widget w, XtPointer clientdata, XtPointer calldata)
{
    XtDestroyWidget(w);
}
/**************************** repaintgraph ********************************/
void repaintgraph(Widget w, XtPointer clientdata, XtPointer calldata)
{
    XEvent event;
    int i,j,len,offset1,offset2,namelen=18;
    float intensity;
    unsigned long c;

/* Clear any other expose events to prevent excessive redraws */
    while(XCheckTypedWindowEvent(display,graphareawindow,Expose,&event)) ;
/* Redraw */
    offset1=HEIGHT/2-2;
    offset2=HEIGHT-2;
    XClearArea(display,graphareawindow,0,0,GRAPHWINWIDTH,GRAPHWINHEIGHT,False);
    for(i=0, c=0; i < ROWS; i++) {
	for(j=0; j < COLUMNS; j++, c++) {
	    XSetForeground(display,gccolor,c);
/*	    XDrawRectangle(display,graphareawindow,gccolor,
	    j*WIDTH,i*HEIGHT,WIDTH-1,HEIGHT-1); */
	    XFillRectangle(display,graphareawindow,gccolor,
	      j*WIDTH,i*HEIGHT,WIDTH,HEIGHT);
	    if(printhex) {
		sprintf(string,"%4.4x %4.4x %4.4x",
		  colordef[c].red,colordef[c].green,colordef[c].blue);
	    }
	    else {
		sprintf(string,"%3d %3d %3d     ",
		  colordef[c].red>>8,colordef[c].green>>8,colordef[c].blue>>8);
	    }
	    intensity=(.30*(double)colordef[c].red+
	      .59*(double)colordef[c].green+
	      .11*(double)colordef[c].blue)/65536.;
	    if(intensity > .5) {
		len=strlen(colorname[c]);
		len=(len<namelen)?len:namelen;
		XDrawString(display,graphareawindow,gcblack,
		  j*WIDTH+2,i*HEIGHT+offset1,colorname[c],len);
		XDrawString(display,graphareawindow,gcblack,
		  j*WIDTH+2,i*HEIGHT+offset2,string,14);
	    }
	    else {
		len=strlen(colorname[c]);
		len=(len<namelen)?len:namelen;
		XDrawString(display,graphareawindow,gcwhite,
		  j*WIDTH+2,i*HEIGHT+offset1,colorname[c],len);
		XDrawString(display,graphareawindow,gcwhite,
		  j*WIDTH+2,i*HEIGHT+offset2,string,14);
	    }
	}
    }
}
/**************************** rescan **************************************/
void rescan(Widget w, XtPointer clientdata, XtPointer calldata)
{
    XQueryColors(display,curmap,colordef,NCOLORS);
    resetgraph();
}
/**************************** resetgraph **********************************/
void resetgraph(void)
{
    repaintgraph(grapharea,(caddr_t)NULL,(caddr_t)NULL);
}
/**************************** rgbstdmap ***********************************/
void rgbstdmap(void)
{
    Colormap vmap;
    XStandardColormap *colormaps;
    int nmaps;

/* Check if property is set */
    colormaps=NULL;
    vmap=0;
    if(XGetRGBColormaps(display,rootwindow,
      &colormaps,&nmaps,stdcmaps[currgbmap].atom)) {
/* Should not need the following statement (Is here so not over error msgs) */
/*	XtManageChild(stdcmappopup); */
	if(stdcmaps[currgbmap].n < nmaps) {
	    vmap=colormaps[stdcmaps[currgbmap].n].colormap;
	}
	else {
	    xerrmsg("There is no %s with number %d",
	      stdcmaps[currgbmap].name,stdcmaps[currgbmap].n);
	    XFree((caddr_t)colormaps);
	    return;
	}
/* Check for non-zero colormap */
	if(vmap) {
/* Switch depending on strategy */
	    switch(strategy) {
	    case 0: /* Set on window */
		if(defvisualclass == stdcmaps[currgbmap].class) {
		    XFreeColors(display,curmap,newcolors,nalloc,0);
		    nalloc=0;
		    XSetWindowColormap(display,CMAPWINDOW,vmap);
		    curmap=vmap;
		}
		else {
		    xerrmsg("%s has visual class: %s\n"
		      "The window has visual class: %s",
		      stdcmaps[currgbmap].name,
		      vname[stdcmaps[currgbmap].class],
		      vname[defvisualclass]);
		}
		break;
	    case 1: /* Create a new map and set it */
		XFreeColors(display,curmap,newcolors,nalloc,0);
		nalloc=0;
		newmap=XCreateColormap(display,rootwindow,defvisual,
		  AllocNone);
		XSetWindowColormap(display,CMAPWINDOW,newmap);
		curmap=vmap;
		querycolors();
		curmap=newmap;
		allocateallpossible();
		break;
	    case 2:  /* Use the default map */
		XFreeColors(display,curmap,newcolors,nalloc,0);
		nalloc=0;
		if(curmap == newmap) XFreeColormap(display,newmap);
		XSetWindowColormap(display,CMAPWINDOW,cmap);
		curmap=vmap;
		querycolors();
		curmap=cmap;
		allocateallpossible();
		break;
	    }
	    querycolors();
	    resetgraph();
	}
	else {
	    xerrmsg("%s is NULL",stdcmaps[currgbmap].name);
	}
    }
/* Not set (Could set one here) */
    else {
	xerrmsg("%s is not installed",stdcmaps[currgbmap].name);
    }
    XFree((caddr_t)colormaps);
}
/**************************** stdcmap *************************************/
void stdcmap(Widget w, XtPointer clientdata, XtPointer calldata)
{
    int i,j,k,err,numvisuals,dummy,nmaps;
    char name[16];
    Atom atom;
    XStandardColormap *colormaps;
    XVisualInfo vtemplet,*vinfo;

/* Get default visual and number of visuals */
    vtemplet.screen=screen;
    vtemplet.depth=defplanes;
    for(j=5; j >= 0; j--) {
	vtemplet.class=j;
	vinfo=XGetVisualInfo(display,
	  VisualScreenMask|VisualDepthMask|VisualClassMask,
	  &vtemplet,&numvisuals);
	if(vinfo != NULL) {
	    for(k=0; k < numvisuals; k++) {
		if(vinfo[k].visual == defvisual) {
		    defvisualid=vinfo[k].visualid;
		    defvisualclass=vinfo[k].class;
		}
	    }
	    XFree((caddr_t)vinfo);
	}
    }
/* Define default colormap */
    nrgbmaps=0;
    strcpy(stdcmaps[nrgbmaps].name,"Default Colormap");
    stdcmaps[nrgbmaps].cmap=cmap;
    stdcmaps[nrgbmaps].vid=defvisualid;
    stdcmaps[nrgbmaps].atom=XA_ATOM;
    stdcmaps[nrgbmaps].class=defvisualclass;
    stdcmaps[nrgbmaps].n=0;
    stdcmaps[nrgbmaps].index=nrgbmaps;
    nrgbmaps++;

/* Find standard colormaps */
    if(nrgbmaps == NRGBMAPS) {
	xerrmsg("Too many Standard Colormaps");
    }
    else {
	strcpy(name,"RGB_DEFAULT_MAP");
	atom=XA_RGB_DEFAULT_MAP;
	err=XGetRGBColormaps(display,rootwindow,
	  &colormaps,&nmaps,atom);
	if(err != 0) {
	    for(i=0; i < nmaps; i++) {
		vtemplet.visualid=colormaps[i].visualid;
		vinfo=XGetVisualInfo(display,
		  VisualIDMask,
		  &vtemplet,&dummy);
		strcpy(stdcmaps[nrgbmaps].name,name);
		stdcmaps[nrgbmaps].cmap=colormaps[i].colormap;
		stdcmaps[nrgbmaps].vid=colormaps[i].visualid;
		stdcmaps[nrgbmaps].atom=atom;
		stdcmaps[nrgbmaps].class=vinfo[0].class;
		stdcmaps[nrgbmaps].n=i;
		stdcmaps[nrgbmaps].index=nrgbmaps;
		XFree((caddr_t)vinfo);
		nrgbmaps++;
	    }
	    XFree((caddr_t)colormaps);
	}
    }
    if(nrgbmaps == NRGBMAPS) {
	xerrmsg("Too many Standard Colormaps");
    }
    else {
	strcpy(name,"RGB_BEST_MAP");
	atom=XA_RGB_BEST_MAP;
	err=XGetRGBColormaps(display,rootwindow,
	  &colormaps,&nmaps,atom);
	if(err != 0) {
	    for(i=0; i < nmaps; i++) {
		vtemplet.visualid=colormaps[i].visualid;
		vinfo=XGetVisualInfo(display,
		  VisualIDMask,
		  &vtemplet,&dummy);
		strcpy(stdcmaps[nrgbmaps].name,name);
		stdcmaps[nrgbmaps].cmap=colormaps[i].colormap;
		stdcmaps[nrgbmaps].vid=colormaps[i].visualid;
		stdcmaps[nrgbmaps].atom=atom;
		stdcmaps[nrgbmaps].class=vinfo[0].class;
		stdcmaps[nrgbmaps].n=i;
		stdcmaps[nrgbmaps].index=nrgbmaps;
		XFree((caddr_t)vinfo);
		nrgbmaps++;
	    }
	    XFree((caddr_t)colormaps);
	}
    }
    if(nrgbmaps == NRGBMAPS) {
	xerrmsg("Too many Standard Colormaps");
    }
    else {
	strcpy(name,"RGB_RED_MAP");
	atom=XA_RGB_RED_MAP;
	err=XGetRGBColormaps(display,rootwindow,
	  &colormaps,&nmaps,atom);
	if(err != 0) {
	    for(i=0; i < nmaps; i++) {
		vtemplet.visualid=colormaps[i].visualid;
		vinfo=XGetVisualInfo(display,
		  VisualIDMask,
		  &vtemplet,&dummy);
		strcpy(stdcmaps[nrgbmaps].name,name);
		stdcmaps[nrgbmaps].cmap=colormaps[i].colormap;
		stdcmaps[nrgbmaps].vid=colormaps[i].visualid;
		stdcmaps[nrgbmaps].atom=atom;
		stdcmaps[nrgbmaps].class=vinfo[0].class;
		stdcmaps[nrgbmaps].n=i;
		stdcmaps[nrgbmaps].index=nrgbmaps;
		XFree((caddr_t)vinfo);
		nrgbmaps++;
	    }
	    XFree((caddr_t)colormaps);
	}
    }
    if(nrgbmaps == NRGBMAPS) {
	xerrmsg("Too many Standard Colormaps");
    }
    else {
	strcpy(name,"RGB_GREEN_MAP");
	atom=XA_RGB_GREEN_MAP;
	err=XGetRGBColormaps(display,rootwindow,
	  &colormaps,&nmaps,atom);
	if(err != 0) {
	    for(i=0; i < nmaps; i++) {
		vtemplet.visualid=colormaps[i].visualid;
		vinfo=XGetVisualInfo(display,
		  VisualIDMask,
		  &vtemplet,&dummy);
		strcpy(stdcmaps[nrgbmaps].name,name);
		stdcmaps[nrgbmaps].cmap=colormaps[i].colormap;
		stdcmaps[nrgbmaps].vid=colormaps[i].visualid;
		stdcmaps[nrgbmaps].atom=atom;
		stdcmaps[nrgbmaps].class=vinfo[0].class;
		stdcmaps[nrgbmaps].n=i;
		stdcmaps[nrgbmaps].index=nrgbmaps;
		XFree((caddr_t)vinfo);
		nrgbmaps++;
	    }
	    XFree((caddr_t)colormaps);
	}
    }
    if(nrgbmaps == NRGBMAPS) {
	xerrmsg("Too many Standard Colormaps");
    }
    else {
	strcpy(name,"RGB_BLUE_MAP");
	atom=XA_RGB_BLUE_MAP;
	err=XGetRGBColormaps(display,rootwindow,
	  &colormaps,&nmaps,atom);
	if(err != 0) {
	    for(i=0; i < nmaps; i++) {
		vtemplet.visualid=colormaps[i].visualid;
		vinfo=XGetVisualInfo(display,
		  VisualIDMask,
		  &vtemplet,&dummy);
		strcpy(stdcmaps[nrgbmaps].name,name);
		stdcmaps[nrgbmaps].cmap=colormaps[i].colormap;
		stdcmaps[nrgbmaps].vid=colormaps[i].visualid;
		stdcmaps[nrgbmaps].atom=atom;
		stdcmaps[nrgbmaps].class=vinfo[0].class;
		stdcmaps[nrgbmaps].n=i;
		stdcmaps[nrgbmaps].index=nrgbmaps;
		XFree((caddr_t)vinfo);
		nrgbmaps++;
	    }
	    XFree((caddr_t)colormaps);
	}
    }
    if(nrgbmaps == NRGBMAPS) {
	xerrmsg("Too many Standard Colormaps");
    }
    else {
	strcpy(name,"RGB_GRAY_MAP");
	atom=XA_RGB_GRAY_MAP;
	err=XGetRGBColormaps(display,rootwindow,
	  &colormaps,&nmaps,atom);
	if(err != 0) {
	    for(i=0; i < nmaps; i++) {
		vtemplet.visualid=colormaps[i].visualid;
		vinfo=XGetVisualInfo(display,
		  VisualIDMask,
		  &vtemplet,&dummy);
		strcpy(stdcmaps[nrgbmaps].name,name);
		stdcmaps[nrgbmaps].cmap=colormaps[i].colormap;
		stdcmaps[nrgbmaps].vid=colormaps[i].visualid;
		stdcmaps[nrgbmaps].atom=atom;
		stdcmaps[nrgbmaps].class=vinfo[0].class;
		stdcmaps[nrgbmaps].n=i;
		stdcmaps[nrgbmaps].index=nrgbmaps;
		XFree((caddr_t)vinfo);
		nrgbmaps++;
	    }
	    XFree((caddr_t)colormaps);
	}
    }
/* Define and popup window */
    definestdcmappopup();
}
/**************************** stdcmapcb ***********************************/
void stdcmapcb(Widget w, XtPointer clientdata, XtPointer calldata)
{
    XmToggleButtonCallbackStruct *state;
    int n;

    n=(int)clientdata;
    state=(XmToggleButtonCallbackStruct *)calldata;
    switch(n) {
    case 101:
	if(stdcmappopup) {
	    XtDestroyWidget(stdcmappopup);
	    stdcmappopup=0;
	    XFlush(display);
	}
	break;
    case 102:
	if(currgbmap == 0) {
	    defaultcm((Widget)NULL,(caddr_t)NULL,(caddr_t)NULL);
/* 	    XtManageChild(stdcmappopup); */
	}
	else {
	    rgbstdmap();
	}
	break;
    case 103:
	if(state->set) strategy=0;
	break;
    case 104:
	if(state->set) strategy=1;
	break;
    case 105:
	if(state->set) strategy=2;
	break;
    case 0:
	if(n != currgbmap && state->set) currgbmap=n;
	break;
    default:
	if(n != currgbmap && state->set) currgbmap=n;
	break;
    }
}
/**************************** xerrmsg *************************************/
void xerrmsg(char *fmt, ...)
{
    Widget child;
    va_list vargs;
    static char lstring[BUFSIZ];
    
    va_start(vargs,fmt);
    (void)vsprintf(lstring,fmt,vargs);
    va_end(vargs);
    
    if(lstring[0] != '\0') {
	if(windowmessage) {
	    XBell(display,50); XBell(display,50); XBell(display,50); 
	    cstring=XmStringCreateLtoR(lstring,XmSTRING_DEFAULT_CHARSET);
	    nargs=0;
	    XtSetArg(args[nargs],XmNtitle,"Warning"); nargs++;
	    XtSetArg(args[nargs],XmNmessageString,cstring); nargs++;
	    warningbox=XmCreateWarningDialog(mainwin,"warningMessage",
	      args,nargs);
	    XmStringFree(cstring);
	    child=XmMessageBoxGetChild(warningbox,XmDIALOG_CANCEL_BUTTON);
	    XtDestroyWidget(child);
	    child=XmMessageBoxGetChild(warningbox,XmDIALOG_HELP_BUTTON);
	    XtDestroyWidget(child);
	    XtManageChild(warningbox);
	    XtAddCallback(warningbox,XmNokCallback,destroyWidget,NULL);
	}
    }
}
/**************************** xinfomsg ************************************/
void xinfomsg(char *fmt, ...)
{
    Widget child;
    va_list vargs;
    static char lstring[BUFSIZ];
    
    va_start(vargs,fmt);
    (void)vsprintf(lstring,fmt,vargs);
    va_end(vargs);
    
    if(lstring[0] != '\0') {
	cstring=XmStringCreateLtoR(lstring,XmSTRING_DEFAULT_CHARSET);
	nargs=0;
	XtSetArg(args[nargs],XmNtitle,"Information"); nargs++;
	XtSetArg(args[nargs],XmNmessageString,cstring); nargs++;
	infobox=XmCreateInformationDialog(mainwin,"informationMessage",
	  args,nargs);
	XmStringFree(cstring);
	child=XmMessageBoxGetChild(infobox,XmDIALOG_CANCEL_BUTTON);
	XtDestroyWidget(child);
	child=XmMessageBoxGetChild(infobox,XmDIALOG_HELP_BUTTON);
	XtDestroyWidget(child);
	XtManageChild(infobox);
	XtAddCallback(infobox,XmNokCallback,destroyWidget,NULL);
    }
}
/**************************** xerrorhandler *******************************/
int xerrorhandler(Display *dpy, XErrorEvent *event)
{
    char buf[BUFSIZ];

    XGetErrorText(dpy,event->error_code,buf,BUFSIZ);
    sprintf(string,"X Error:\n%s",buf);
    fprintf(stderr,string);
    if(windowmessage) xerrmsg("X Error:\n%s",buf);
    return(0);
}
/**************************** xterrorhandler ******************************/
void xterrorhandler(char *message)
{
    fprintf(stderr,message);
    if(windowmessage) xerrmsg(message);
}
