/*******************************************************************************
*                                                                              *
*                                   Viewmol                                    *
*                                                                              *
*                              V I E W M O L . C                               *
*                                                                              *
*                 Copyright (c) Joerg-R. Hill, October 2003                    *
*                                                                              *
********************************************************************************
*
* $Id: viewmol.c,v 1.6 2003/11/07 11:17:09 jrh Exp $
* $Log: viewmol.c,v $
* Revision 1.6  2003/11/07 11:17:09  jrh
* Release 2.4
*
* Revision 1.5  2000/12/10 15:17:58  jrh
* Release 2.3
*
* Revision 1.4  1999/05/24 01:27:46  jrh
* Release 2.2.1
*
* Revision 1.3  1999/02/07 21:58:09  jrh
* Release 2.2
*
* Revision 1.2  1998/01/26 00:49:40  jrh
* Release 2.1
*
* Revision 1.1  1996/12/10  18:44:18  jrh
* Initial revision
*
*/
#include<locale.h>
#include<signal.h>
#include<stdio.h>
#include<X11/Xlib.h>
#include<X11/Intrinsic.h>
#include<X11/Xatom.h>
#ifdef _SGI_EXTRA_PREDEFINES
#include<X11/SGIFastAtom.h>
#else
#define XSGIFastInternAtom(dpy,string,fast_name,how) XInternAtom(dpy,string,how)
#endif
#include<Xm/Xm.h>
#include<Xm/XmStrDefs.h>
#include<Xm/DrawingA.h>
#include<GL/gl.h>
#include<GL/glu.h>
#include<GL/glx.h>
#include "dialog.h"
#include "viewmol.h"
#include "fallbacks.h"
/* #include "xdnd.h" */

void reshape(Widget, caddr_t, XmDrawingAreaCallbackStruct *);
void setShape(int, Dimension, Dimension);
void getRotation(int, int, int, int);
void setDrawingDevice(int);
void ende(Widget, caddr_t, XmAnyCallbackStruct *);
void setIcon(Widget, XtPointer, XEvent *);
void signalHandler(int);
void installColormap(void);

extern void drawMolecule(Widget, caddr_t, XmDrawingAreaCallbackStruct *);
extern void processInput(Widget, caddr_t, XmDrawingAreaCallbackStruct *);
extern void printString(char *, double, double, double, double, GLuint, char);
extern void feedbackString(char *, double, double, double, double, GLuint, char);
extern void feedbackLineStipple(GLint, GLushort);
extern void feedbackLineWidth(GLfloat);
extern void feedbackDisable(GLenum);
extern void raytracerBegin(GLenum), raytracerEnd(void), raytracerVertex3d(double, double, double);
extern void raytracerNormal3d(double, double, double);
extern void raytracerColor4fv(const GLfloat *);
extern void raytracerClearColor(GLclampf, GLclampf, GLclampf, GLclampf);
extern void raytracerSphere(GLUquadricObj *, GLdouble, GLint, GLint);
extern void raytracerCylinder(GLUquadricObj *qobj, GLdouble, GLdouble, GLdouble, GLint, GLint);
extern void raytracerCone(GLUquadricObj *qobj, GLdouble, GLdouble, GLdouble, GLint, GLint);
extern void GetMessageBoxButton(Widget, XtPointer, caddr_t);
extern char *getStringResource(Widget, char *);
extern void pixelToWorld(int, double *, double *);
extern int  messgb(Widget, int, char *, struct PushButtonRow *, int);
extern void loadColorMap(void);
extern void findInputDevices(Widget);
extern int  getrc(void);
extern void showTitle(Widget, caddr_t, XmDrawingAreaCallbackStruct *);
extern int  initViewer(int, char **, Widget);
extern void redraw(int);
extern void fremem(void **);
extern void scaleAnnotation(float);
extern void processSpaceballEvent(XEvent *);
extern int  load(Widget, caddr_t, XmAnyCallbackStruct *);
extern void allocWindowColors(void);
extern XVisualInfo *getVisualInfo(Display *, Visual *);
extern Colormap getRGBcolormap(Display *, int, XVisualInfo *);
extern void incrementQuaternion(double, double, double, float *);
extern void initPython(int, char **);
extern void loadAtomColors(XVisualInfo *, Colormap);
extern int findShadowMapSupport(void);

extern void testBegin(GLenum), testEnd(void), testVertex(double, double, double), testNorm(double, double, double);

void (*drawBegin)(GLenum), (*drawEnd)(void), (*drawVertex3d)(double, double, double);
void (*drawVertex2d)(double, double), (*drawNormal3d)(double, double, double);
void (*drawColor4fv)(const GLfloat *);
void (*drawClearColor)(GLclampf, GLclampf, GLclampf, GLclampf);
void (*drawSphere)(GLUquadricObj *, GLdouble, GLint, GLint);
void (*drawCylinder)(GLUquadricObj *qobj, GLdouble, GLdouble, GLdouble, GLint, GLint);
void (*drawCone)(GLUquadricObj *qobj, GLdouble, GLdouble, GLdouble, GLint, GLint);
void (*drawString)(char *, double, double, double, double, GLuint, char);
void (*drawLineStipple)(GLint, GLushort);
void (*drawLineWidth)(GLfloat);
void (*drawDisable)(GLenum);

struct MOLECULE *molecules=NULL;
struct ELEMENT *elements;
struct WINDOW windows[4];
struct OPTION *options=NULL;
struct OPTION *output=NULL;
struct ANNOTATION *annotation=NULL;
struct UNDO *undo=NULL;
Pixel stdcol[9], historyColor;
XtAppContext app;
Widget topShell, fileBox, bfMenu, undoButton=NULL;
PyObject *viewmolModule, *moleculeModule;
double *grid=NULL;
double bndfac=1.0, amplitude, forceScale, wnScale=1.0, hbondThreshold=2.0, scaleRadius=1.0;
double tmat[4][4];
double paperWidth=0.0, paperHeight=0.0, sphereres=10., lineWidth=0.0, spectrumLineWidth=1.0;
double temp, pressure=1.0, weight=0.0;
double e1, e2, denres=(1.);
double level=0.05, gridres=(-1.), torsionDefault=180.0, drawingSpeed=0.0;
float *transObject=NULL, *rotObject=NULL;
float historyColor_rgb[4] = {0.0, 0.0, 1.0, 0.0};
GLfloat light0p[4] = {0.0, 0.0, 1.0, 0.0};
GLfloat light1p[4] = {0.0, 1.0, 0.0, 0.0};
int ne, nopt=0, noutput=0, nUndo=0;
int nmolecule=0, imol, ireaction=0;
int rotateXY=FALSE, rotateZ=FALSE;
int primitive, animate=ANIMATE, lights=3, moveItem=MOLECULES, projectionMode=ORTHO;
int lines=TRUE, showForces=FALSE, setins=FALSE, xIsTop=TRUE, showGrid=TRUE;
int showUnitCell=TRUE, bondOrderDefault=1;
int showInertia=FALSE, selectAtom=FALSE, simplify=TRUE;
int rgbMode, picking=FALSE, swapBuffers=TRUE, shadows=FALSE, ground=TRUE, drawIcon=FALSE;
int drawingDevice, bondType=CONJUGATION, showHBond=TRUE, localGeometry=TRUE;
int label, outputType=0, automaticRecalculate=FALSE;
int showWarning=TRUE, debug, annotate=FALSE, saveAll=TRUE;
int nAnnotations=0, normalModeAnnotation=(-1), selectAtomAnnotation=(-1);
int historyAnnotation=(-1), setinsAnnotation=(-1);
int unit, bfatom, element=0, modifyMolecule=NOTHING;
int thermoUnits=JOULES, pythonInterrupt=FALSE;
int spaceballButtonPress, spaceballMotionNotify;
int showMenu=TRUE, saveLanguage=FALSE;
int iwavef=ALL_OFF, interp=IP_LINEAR;
int format=TIFFFILE, landscape=TRUE;
int shadowMap=FALSE;
char *formBondLength, *formBondAngle, *formTorsionAngle;
char *text, *textPointer, *moduleName;
char language[20];
char webbrowser[MAXLENLINE]={""}, moloch[MAXLENLINE]={""};
char raytracer[MAXLENLINE]={""}, displayImage[MAXLENLINE]={""};
pid_t manual_pid=0, raypid=0;

int main(int argc, char** argv)
{
  Display *display;
  XVisualInfo *vi;
  Colormap colormap;
  XEvent event;
/*DndClass dnd;*/
  String translations="<KeyDown>:    DrawingAreaInput()\n\
                       <Btn1Motion>: DrawingAreaInput()\n\
                       <Btn2Motion>: DrawingAreaInput()\n\
                       <BtnDown>:    DrawingAreaInput()\n\
                       <BtnUp>:      DrawingAreaInput()";
  int attrib[] = {GLX_RED_SIZE, 1,
                  GLX_GREEN_SIZE, 1,
                  GLX_BLUE_SIZE, 1,
                  GLX_DEPTH_SIZE, 1,
                  GLX_DOUBLEBUFFER,
                  GLX_RGBA,
                  GLX_STENCIL_SIZE, 2,
                  None};
  static struct PushButtonRow buttons[] = {{"exit", GetMessageBoxButton,
                                           (XtPointer)0, NULL}};
/*Atom dropType;
  int dropBufferSize, dropX, dropY;
  unsigned char *dropBuffer; */
  char *line, *locale;

  locale=setlocale(LC_ALL, "");
  signal(SIGBUS,  signalHandler);
  signal(SIGFPE,  signalHandler);
  signal(SIGSEGV, signalHandler);

  XtSetLanguageProc(NULL, NULL, NULL);
  topShell=XtVaAppInitialize(&app, "Viewmol", NULL, 0, &argc, argv, fallbacks,
                             NULL);
  if (topShell == NULL)
  {
    fprintf(stderr, "%s: ERROR: Cannot connect to X server.\n", PROGRAM);
    exit(-1);
  }
  display=XtDisplay(topShell);
  rgbMode=TRUE;
  if ((vi=glXChooseVisual(display, XScreenNumberOfScreen(XtScreen(topShell)),
       attrib)) == NULL || vi->class == DirectColor)
  {
    /* Could not find a double buffered RGB visual with stencil buffer,
       try to find one without stencil buffer */
    attrib[10]=None;
    if ((vi=glXChooseVisual(display, XScreenNumberOfScreen(XtScreen(topShell)),
         attrib)) == NULL)
    {
      /* Could not find a double buffered RGB visual, try to find a
         color mapped one */
      attrib[9]=None;
      rgbMode=FALSE;
      if ((vi=glXChooseVisual(display, XScreenNumberOfScreen(XtScreen(topShell)),
           attrib)) == NULL)
      {
	/* Still no success, give up */
        line=getStringResource(topShell, "noVisual");
        messgb(topShell, 3, line, buttons, 1);
        exit(-1);
      }
    }
  }
  colormap=getRGBcolormap(display, vi->screen, vi);
/* AIX doesn't return anything meanigful here, but also requires that
   the color map is not set */
/*if (strlen(glXQueryServerString(display, vi->screen, GLX_VERSION)) > 0) */
    XtVaSetValues(topShell, XtNvisual, vi->visual, XtNdepth, vi->depth,
                  XtNcolormap, colormap, NULL);
/*else
    XtVaSetValues(topShell, XtNvisual, vi->visual, XtNdepth, vi->depth, NULL);*/
  XtRealizeWidget(topShell);

  windows[VIEWER].left=-1.0;
  windows[VIEWER].right=1.0;
  windows[VIEWER].bottom=-1.0;
  windows[VIEWER].top=1.0;
  windows[VIEWER].near=-1.0;
  windows[VIEWER].far=1.0;
  windows[VIEWER].widget=XtVaCreateManagedWidget("viewer", xmDrawingAreaWidgetClass, topShell,
                                                 XtNvisual, vi->visual,
						 XmNtranslations, XtParseTranslationTable(translations),
                                                 XmNmarginHeight, 0,
                                                 XmNmarginWidth, 0,
                                                 NULL);

  windows[VIEWER].context=glXCreateContext(XtDisplay(windows[VIEWER].widget),
                                           vi, None, GL_TRUE);
  glXMakeCurrent(XtDisplay(windows[VIEWER].widget), XtWindow(windows[VIEWER].widget), windows[VIEWER].context);

  loadColorMap();
  findInputDevices(windows[VIEWER].widget);
/*XtAddEventHandler(topShell, PropertyChangeMask, False,
                    (XtEventHandler)setIcon, (XtPointer)NULL); */
  shadowMap=findShadowMapSupport();
  if (getrc())
  {
    setDrawingDevice(SCREEN);
    XtAddCallback(windows[VIEWER].widget, XmNexposeCallback, (XtCallbackProc)showTitle, NULL);
    XtAddCallback(windows[VIEWER].widget, XmNinputCallback,  (XtCallbackProc)processInput, NULL);
    XtAddCallback(windows[VIEWER].widget, XmNresizeCallback, (XtCallbackProc)reshape, (XtPointer)VIEWER);
    showTitle((Widget)0, (caddr_t)0, (XmDrawingAreaCallbackStruct *)0);
    allocWindowColors();
    initPython(argc, argv);
    windows[VIEWER].menu=NULL;
    if (!initViewer(argc, argv, windows[VIEWER].widget))
      (void)load((Widget)0, (caddr_t)0, (XmAnyCallbackStruct *)0);
    if (molecules)
    {
      XtRemoveAllCallbacks(windows[VIEWER].widget, XmNexposeCallback);
      XtAddCallback(windows[VIEWER].widget, XmNexposeCallback, (XtCallbackProc)drawMolecule, NULL);
    }
  }
/*xdnd_init(&dnd, display);
  xdnd_set_dnd_aware(&dnd, XtWindow(topShell), NULL); */
  while (TRUE)
  {                                                    
    XtAppNextEvent(app, &event);
/*  xdnd_get_drop(display, &event, NULL, NULL, &dropBuffer, &dropBufferSize,
			&dropType, &dropX, &dropY); */
    if (event.type == spaceballMotionNotify || event.type == spaceballButtonPress)
      processSpaceballEvent(&event);
    else
      XtDispatchEvent(&event);
  }
}

void reshape(Widget widget, caddr_t window, XmDrawingAreaCallbackStruct *data)
{
  Dimension width, height;
  int w=(int)window;

  XtVaGetValues(widget, XmNwidth, &width, XmNheight, &height, NULL);
  glXMakeCurrent(XtDisplay(windows[w].widget), XtWindow(windows[w].widget), windows[w].context);
  setShape((int)window, width, height);
  redraw(w);
}

void setShape(int window, Dimension width, Dimension height)
{
  double rel;

  XtVaSetValues(windows[window].widget, XmNwidth, width, XmNheight, height,
                NULL);
  glViewport(0, 0, width, height);
  if (window == VIEWER)
  {
    if (width > height)
    {
      rel=((double)width/(double)height-1.0)*windows[VIEWER].near;
      windows[VIEWER].left=windows[VIEWER].near+rel;
      windows[VIEWER].right=windows[VIEWER].far-rel;
      windows[VIEWER].bottom=windows[VIEWER].near;
      windows[VIEWER].top=windows[VIEWER].far;
    }
    else
    {
      rel=((double)height/(double)width-1.0)*windows[VIEWER].near;
      windows[VIEWER].left=windows[VIEWER].near;
      windows[VIEWER].right=windows[VIEWER].far;
      windows[VIEWER].bottom=windows[VIEWER].near+rel;
      windows[VIEWER].top=windows[VIEWER].far-rel;
    }
  }
}

void getRotation(int x, int y, int z, int mode)
{
  static int xold, yold, zold;
  double factor=1.0;

  if (mode == 2)
  {
    xold=x;
    yold=y;
    zold=z;
    return;
  }

  if (x < 0) x=xold;
  if (y < 0) y=yold;
  if (z < 0) z=zold;
  if (moveItem == VIEWPOINT) factor=0.25;
  if (mode == 1)
  {
    incrementQuaternion(factor*(double)y, factor*(double)x, factor*(double)z,
				&rotObject[4*moveItem]);
  }
  else
  {
    incrementQuaternion(factor*(double)(yold-y), factor*(double)(xold-x),
				factor*(double)(z-zold), &rotObject[4*moveItem]);
  }
  if (mode == 0)
  {
    xold=x;
    yold=y;
    zold=z;
  }
}

void getTranslation(int x, int y, int mode)
{
  static int xold, yold;
  Dimension width, height;
  double xpix, ypix;

  if (rotateXY == 1)
  {
    pixelToWorld(VIEWER, &xpix, &ypix);
    if (moveItem & 0x80000000)
    {
      XtVaGetValues(windows[VIEWER].widget, XmNwidth, &width, XmNheight, &height, NULL);
      if (mode == 1)
      {
        annotation[moveItem & 0x7fffffff].x+=2.0*(double)x/(double)width;
        annotation[moveItem & 0x7fffffff].y+=2.0*(double)y/(double)height;
      }
      else
      {
        annotation[moveItem & 0x7fffffff].x+=2.0*(double)(x-xold)/(double)width;
        annotation[moveItem & 0x7fffffff].y+=2.0*(double)(yold-y)/(double)height;
      }
    }
    else
    {
      if (mode == 1)
      {
        transObject[3*moveItem]+=(float)x*xpix;
        transObject[3*moveItem+1]+=(float)y*ypix;
      }
      else
      {
        transObject[3*moveItem]+=(float)(x-xold)*xpix;
        transObject[3*moveItem+1]+=(float)(yold-y)*ypix;
      }
    }
  }
  if (rotateXY == -1) rotateXY=1;

  xold=x;
  yold=y;
}

void getEnlargement(int x, int mode)
{
  static int xold=(-1);
  float  scale;

  if (rotateZ == 1)
  {
    if (projectionMode == ORTHO)
    {
      if (mode == 1)
        scale=1.+(float)x*0.025;
      else
        scale=1.+(float)(x-xold)*0.025;
      windows[VIEWER].top*=scale;
      windows[VIEWER].bottom*=scale;
      windows[VIEWER].right*=scale;
      windows[VIEWER].left*=scale;
      if (nAnnotations) scaleAnnotation(scale);
    }
    else
    {
      if (mode == 1)
        transObject[3*moveItem+2]+=(float)x;
      else
        transObject[3*moveItem+2]+=(float)(x-xold);
    }
  }
  if (rotateZ == -1) rotateZ=1;
  xold=x;
  redraw(VIEWER);
}

void setDrawingDevice(int device)
{
  drawingDevice=device;

  switch (device)
  {
    case SCREEN:     drawBegin=glBegin;
                     drawEnd=glEnd;
                     drawVertex3d=glVertex3d;
                     drawVertex2d=glVertex2d;
                     drawNormal3d=glNormal3d;
                     drawColor4fv=glColor4fv;
                     drawClearColor=glClearColor;
                     drawSphere=gluSphere;
                     drawCylinder=gluCylinder;
                     drawCone=gluCylinder;
                     drawString=printString;
                     drawLineStipple=glLineStipple;
                     drawLineWidth=glLineWidth;
                     drawDisable=glDisable;
                     break;
    case HPGL:
    case POSTSCRIPT: drawBegin=glBegin;
                     drawEnd=glEnd;
                     drawVertex3d=glVertex3d;
                     drawVertex2d=glVertex2d;
                     drawNormal3d=glNormal3d;
                     drawColor4fv=glColor4fv;
                     drawClearColor=glClearColor;
                     drawLineStipple=glLineStipple;
                     drawLineWidth=glLineWidth;
                     drawDisable=glDisable;
                     drawSphere=gluSphere;
                     drawCylinder=gluCylinder;
                     drawCone=gluCylinder;
                     drawString=feedbackString;
                     drawLineStipple=feedbackLineStipple;
                     drawLineWidth=feedbackLineWidth;
                     drawDisable=feedbackDisable;
                     break;
    case RAYTRACER:  drawBegin=raytracerBegin;
                     drawEnd=raytracerEnd;
                     drawVertex3d=raytracerVertex3d;
                     drawVertex2d=glVertex2d;
                     drawNormal3d=raytracerNormal3d;
                     drawColor4fv=raytracerColor4fv;
                     drawClearColor=raytracerClearColor;
                     drawSphere=raytracerSphere;
                     drawCylinder=raytracerCylinder;
                     drawCone=raytracerCone;
                     drawString=printString;
                     drawLineStipple=glLineStipple;
                     drawLineWidth=glLineWidth;
                     drawDisable=glDisable;
                     break;
  }
}

void ende(Widget widget, caddr_t client_data, XmAnyCallbackStruct *call_data)
{
  struct MOLECULE *mol;
  register int i;

  fremem((void **)&windows[VIEWER].font);
  if (windows[SPECTRUM].font != NULL) fremem((void **)&windows[SPECTRUM].font);
  if (windows[HISTORY].font != NULL) fremem((void **)&windows[HISTORY].font);
  if (windows[MO].font != NULL) fremem((void **)&windows[MO].font);
  for (i=0; i<nmolecule; i++)
  {
    mol=&molecules[i];
    fremem((void **)&(mol->atoms));
    fremem((void **)&(mol->bonds));
    if (mol->cnm != NULL)          fremem((void **)&(mol->cnm));
    if (mol->normal_modes != NULL) fremem((void **)&(mol->normal_modes));
    if (mol->history != NULL)      fremem((void **)&(mol->history));
    if (mol->optimization != NULL) fremem((void **)&(mol->optimization));
    if (mol->orbitals != NULL)     fremem((void **)&(mol->orbitals));
    if (mol->basisset != NULL)     fremem((void **)&(mol->basisset));
    if (mol->exponents != NULL)    fremem((void **)&(mol->exponents));
  }
  if (options != NULL) fremem((void **)&options);
  fremem((void **)&molecules);
  nmolecule=0;
  if (manual_pid && kill(manual_pid, 0) != -1) kill(manual_pid, SIGTERM);
  if (raypid && kill(raypid, 0) != -1) kill(raypid, SIGTERM);
  Py_Exit(0);
  exit(0);
}

void setIcon(Widget widget, XtPointer dummy, XEvent *e)
{
  static int iconic=FALSE;
  static Dimension width, height;
  Display *display;
  Screen *screen;
  XVisualInfo *visualInfo;
  XPropertyEvent *event=(XPropertyEvent *)e;
  Atom wmStateAtom=(Atom)0;
  XIconSize *sizes;
  Pixmap pixmap;
  GLXPixmap glxPixmap;
  GLXContext context;
  int count, restore=FALSE;
  unsigned int w, h;

#if defined LINUX || defined DARWIN || defined FREEBSD
  wmStateAtom=XInternAtom(XtDisplay(topShell), "XmSWM_STATE", False);
#else
  wmStateAtom=XSGIFastInternAtom(XtDisplay(topShell), "XmSWM_STATE",
					   SGI_XA_WM_STATE, False);
#endif
  if (event->atom == wmStateAtom)
  {
    if (!iconic)
    {
      display=XtDisplay(topShell);
      screen=XtScreen(topShell);
      if (XGetIconSizes(display, RootWindowOfScreen(screen), &sizes, &count))
      {
        w=sizes[0].max_width;
        h=sizes[0].max_height;
        XFree(sizes);
      }
      else
      {
        w=32;
        h=32;
      }
      visualInfo=getVisualInfo(display, DefaultVisualOfScreen(screen));
      pixmap=XCreatePixmap(display, XtWindow(topShell), w, h, (unsigned int)(visualInfo->depth));
      glxPixmap=glXCreateGLXPixmap(display, visualInfo, pixmap);
      context=glXCreateContext(display, visualInfo, NULL, FALSE);
      glXMakeCurrent(display, glxPixmap, context);
      drawIcon=TRUE;
      if (rgbMode && visualInfo->class == PseudoColor)
      {
  	  restore=TRUE;
	  rgbMode=FALSE;
	  loadAtomColors(visualInfo, DefaultColormapOfScreen(screen));
      }
      XtVaGetValues(windows[VIEWER].widget, XmNwidth, &width, XmNheight, &height, NULL);
      setShape(VIEWER, (Dimension)w, (Dimension)h);
      drawMolecule((Widget)0, (caddr_t)0, (XmDrawingAreaCallbackStruct *)0);
      if (restore) rgbMode=TRUE;
      drawIcon=FALSE;
      XtVaSetValues(topShell, XtNiconPixmap, pixmap, NULL);
    }
    else
      setShape(VIEWER, width, height);
    iconic=!iconic;
  }
}

void signalHandler(int signalNumber)
{
  struct PushButtonRow buttons[] = {{"exit", GetMessageBoxButton, (XtPointer)0, NULL}};
  char *word=NULL;

  switch (signalNumber)
  {
    case SIGBUS:  word=getStringResource(topShell, "BusError");
                  break;
    case SIGFPE:  word=getStringResource(topShell, "FloatingPointException");
                  break;
    case SIGSEGV: word=getStringResource(topShell, "SegmentationViolation");
                  break;
  }
  messgb(topShell, 3, word, buttons, 1);
  exit(-1);                                                             
}

void installColormap(void)
{
  int status;
  Window windows[1], *windowsReturn, *windowList;
  int countReturn, i;

  status=XGetWMColormapWindows(XtDisplay(topShell), XtWindow(topShell),
                               &windowsReturn, &countReturn);
  if(!status)
  {
    windows[0]=XtWindow(topShell);
    XSetWMColormapWindows(XtDisplay(topShell),XtWindow(topShell),windows,1);
  }

      /* there was a property, add myself to the beginning */
  else
  {
    windowList=(Window *)XtMalloc((sizeof(Window))*(countReturn+1));
    windowList[0]=XtWindow(topShell);
    for(i=0; i<countReturn; i++)
      windowList[i+1]=windowsReturn[i];
    XSetWMColormapWindows(XtDisplay(topShell),XtWindow(topShell),windowList,countReturn+1);
    XtFree((char*)windowList);
    XtFree((char*)windowsReturn);
  }
}
