#ifdef SCCS
static char sccsid[]="@(#)rdr.c	1.15 Oki 93/05/24";
#endif
/*
 *			Copyright (c) 1992 by
 *			Oki Electric Industry Co., Ltd.
 *			All Rights Reserved
 *
 * Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose and without fee is hereby granted,
 * provided that the above copyright notice appear in all copies and that
 * both that copyright notice and this permission notice appear in
 * supporting documentation, and that the name of Oki Electric not be
 * used in advertising or publicity pertaining to distribution of the
 * software without specific, written prior permission. Oki Electric
 * makes no representations about the suitability of this software for any
 * purpose.  It is provided "as is" without express or implied warranty.
 *
 *************************************************************************
 * rdr.c - the methods for using a PHIGS Workstation resource as the
 * render object.
 *
 *  rdrInit
 *  rdrReDraw
 *  rdrMapXtoMC
 *  rdrMapMCtoX
 *  rdrSetView
 *  rdrSetNPCtoDC
 *  rdrPost
 *  rdrDeleteAll
 *  rdrPickOne
 */

#include <stdio.h>

#include <math.h>

#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xatom.h>

#include <X11/PEX5/PEXlib.h>
#include "pexdraw.h"
#include "util/pexutdb.h"  /* this ain't Right, but life is too short */

/*************************************************************************
 * State Variables
 */
static int myMCSeqNo = -1;
static int thePickInitFlag = 0;

static int theRdrViewLUT;

static int rPostCount = 0;
static long *rPostTable = (long *)0;

static Drawable the3DBuffer;
static int thePMWidth, thePMHeight;
static PEXPipelineContext thePC;
extern int theDBFlag;

PEXNPCSubVolume theVolume;
PEXViewport theViewport;
PEXMatrix theXToMCMatrix;
int theMatrixValidFlag = 0;

extern int theHPFlag;
/* L O C A L  P r o c s */

/*************************************************************************
 *
 */
XID  rdrInit( dpy,  w, colorLUT, lightLUT, textLUT, depthCueLUT,colorApproxLUT)
     Display *dpy;
     Window w;
     PEXLookupTable colorLUT;
     PEXLookupTable lightLUT;
     PEXLookupTable textLUT;
     PEXLookupTable depthCueLUT;
     PEXLookupTable colorApproxLUT;
{
  XID                           renderObj;
  PEXNameSet			incl, excl;
  PEXName names[2];
  PEXRendererAttributes		rAttrs;	/* renderer attributes */
  long                          rMask;
  XWindowAttributes             winAttrs;

  PEXPCAttributes		pcAttrs;
  unsigned long			pcMask[3];
  
  XColor                        background;
  Drawable                      id;
  int                           dbstat;
/*************************************************************************/

  theRdrViewLUT = PEXCreateLookupTable( theDisplay, theWindow, PEXLUTView);

  incl = PEXCreateNameSet(theDisplay);
  names[0] = 1; names[1] = 2; names[2] = 3; /* do an extra, for the heck */
  PEXChangeNameSet(theDisplay, incl, PEXNSAdd, 3, names);
  excl = PEXCreateNameSet(theDisplay);

/*
 * init the NPC to DC transform so we have it when we need it.
 */
  theVolume.min.x = theVolume.min.y = theVolume.min.z = 0.0;
  theVolume.max.x = theVolume.max.y = theVolume.max.z = 1.0;

  XGetWindowAttributes(theDisplay, theWindow, &winAttrs );

  theViewport.min.x = theViewport.min.y = theViewport.min.z = 0.0;
  theViewport.max.x = winAttrs.width;
  theViewport.max.y = winAttrs.height;
  theViewport.max.z = 1.0;
  theViewport.use_drawable = 1;

/*
 * Init the Pipeline Context for TextHeight and CurveApprox Criteria.
 */
  pcAttrs.char_height = 0.08;
  pcAttrs.curve_approx.method = PEXApproxConstantBetweenKnots;
  pcAttrs.curve_approx.tolerance = 16.0;
  pcAttrs.surface_approx.method = PEXApproxConstantBetweenKnots;
  pcAttrs.surface_approx.u_tolerance = 4.0;
  pcAttrs.surface_approx.v_tolerance = 4.0;

  pcMask[0] = pcMask[1] = pcMask[2] = 0;
  if (CheckEnumType(PEXETCurveApproxMethod, PEXApproxConstantBetweenKnots))
    {PEXSetPCAttributeMask(pcMask, PEXPCCurveApprox);
     PEXSetPCAttributeMask(pcMask, PEXPCSurfaceApprox);}
  PEXSetPCAttributeMask(pcMask, PEXPCCharHeight );
  if (theHPFlag == 0)
  thePC = PEXCreatePipelineContext(theDisplay, pcMask, &pcAttrs);

/*
 * now set all of the accumulated attributes into the struct and set the flags.
 */
  rAttrs.pipeline_context = thePC;
  rAttrs.npc_subvolume = theVolume;
  rAttrs.viewport = theViewport;
  rAttrs.view_table = theRdrViewLUT;
  rAttrs.light_table = lightLUT;
  rAttrs.hlhsr_mode = PEXHLHSRZBuffer;
  rAttrs.depth_cue_table = depthCueLUT;
  rAttrs.color_approx_table = colorApproxLUT;
  rAttrs.color_table = colorLUT;
  rAttrs.text_font_table = textLUT;
  rAttrs.pick_incl = incl;
  rAttrs.pick_excl = excl;
  rAttrs.pick_excl = excl;
  rAttrs.clear_image = True;
  rAttrs.clear_z = True;

  rMask = PEXRAPipelineContext|PEXRALightTable|PEXRAHLHSRMode|
    PEXRAViewTable|PEXRADepthCueTable|PEXRAColorTable|
      PEXRAColorApproxTable|PEXRAPickIncl|PEXRAPickExcl|
	PEXRANPCSubVolume|PEXRAViewport|PEXRAClearImage|
	  PEXRAClearZ|PEXRATextFontTable;

/*  if (theHPFlag == 0)   mask |= PEXRAPipelineContext; byte swapping bug? */

  renderObj = PEXCreateRenderer(theDisplay, theWindow, rMask, &rAttrs);

  background.pixel = BlackPixel(theDisplay,theScreen);
  background.red = 0;
  background.green = 0;
  background.blue = 0;
  background.flags = DoRed|DoGreen|DoBlue;

  if (theDBFlag) {
    dbstat = PEXUtDBConfig(theDisplay, theWindow, True,&background,False,&id);	
    printf(" dbstat %x, id %x, win %x\n", dbstat, id, theWindow );
    if (theWindow != id) {
      printf(" Pixmap or MBX - reassinging theWindow! \n");
      the3DBuffer = id;
    } else {
      the3DBuffer = theWindow;
    }
  } else {
    the3DBuffer = theWindow;
  }
  return (renderObj);
}

/*************************************************************************
 * ReDraw - does a redraw for the renderer case.
 */
void  rdrReDraw()
{
  int i;
  Drawable id;

  PEXBeginRendering(theDisplay, the3DBuffer, theRenderObj);

  for (i = 0; i < rPostCount; i++ )
    PEXExecuteStructure(theDisplay, theRenderObj, PEXOCRender, rPostTable[i] );
  
  PEXEndRendering(theDisplay, theRenderObj, 1);
  
  if (theDBFlag) {
    id = PEXUtDBSwap(theDisplay, theWindow, False );
    the3DBuffer = id;
  }
  XFlush(theDisplay);
}

/*************************************************************************
 * MapPoints 
 */
int  rdrMapXToMC(mc, nCoords, xPoints, mcPoints )
     MCMatrix *mc;
     int nCoords;
     XPoint *xPoints;
     PEXCoord **mcPoints;
{
  int i;
  int error;
  unsigned long valueMask[2];
  PEXRendererAttributes *rdrAttrs;
  PEXMatrix WCtoXC, NPCtoXC, XtoMC;
  XPoint *xp;
  PEXCoord p, *m;

  error = PEXNPCToXCTransform( &theVolume, (PEXDeviceCoord *)&theViewport, 
			      theWinHeight, NPCtoXC );
  if(error != 0) printf("imagine a Motif alarm, NPCtoXC err = %d\n",error);

  PEXMatrixMult( theMatMap, theMatOri, WCtoXC );
  PEXMatrixMult( NPCtoXC, WCtoXC, WCtoXC );
  if (myMCSeqNo != mc->seqNo) myMCSeqNo = mc->seqNo; /* cache this someday */
  PEXMatrixMult( WCtoXC, mc->matrix, WCtoXC );
  
  error = PEXInvertMatrix( WCtoXC, XtoMC );
  if(error != 0) printf("imagine a Motif alarm, Invert err = %d\n",error);

  m = (PEXCoord *)malloc(nCoords * sizeof(PEXCoord));

  for (i = 0, xp = xPoints; i < nCoords; i++, xp++ ) {
    p.x = (float)xp->x;
    p.y = (float)xp->y;
    p.z = theDepth;
    PEXTransformPoints(XtoMC, 1, &p, &m[i]);
  }

  *mcPoints = m;
  return (nCoords);
}

/*************************************************************************
 * MapMCToX
 *
 * MC xform struct.
 * count
 * points in
 * returns points out.
 * functions returns count
 */
int rdrMapMCToX( mc, inCount, mcPoints, xPoints )
     MCMatrix *mc;
     int inCount;
     PEXCoord *mcPoints;
     XPoint **xPoints;
{
  int i;
  int error;
  PEXMatrix WCtoXC, NPCtoXC, XtoMC;
  XPoint *xp;
  PEXCoord p, *m;

  error = PEXNPCToXCTransform( &theVolume, (PEXDeviceCoord *)&theViewport, 
			      theWinHeight, NPCtoXC );
  if(error != 0) printf("imagine a Motif alarm, NPCtoXC err = %d\n",error);

  PEXMatrixMult( theMatMap, theMatOri, WCtoXC );
  PEXMatrixMult( NPCtoXC, WCtoXC, WCtoXC );
  if (myMCSeqNo != mc->seqNo) myMCSeqNo = mc->seqNo; /* cache this someday */
  PEXMatrixMult( WCtoXC, mc->matrix, WCtoXC );

  *xPoints = (XPoint *)malloc(inCount * sizeof(XPoint));

  for (i = 0, xp = *xPoints; i < inCount; i++, xp++ ) {
    PEXTransformPoints(WCtoXC, 1, &mcPoints[i], &p);
    xp->x = p.x;
    xp->y = p.y;
  }

  return (inCount);
}

/*************************************************************************
 *
 */
void  rdrSetView( viewNumber, view)
     int viewNumber;
     PEXViewEntry *view;
{
  PEXSetTableEntries(theDisplay, theRdrViewLUT,1,1, PEXLUTView,(char *)view);
}

/*************************************************************************
 *
 */
void  rdrSetNPCToDC( volume, viewport )
     PEXNPCSubVolume *volume;
     PEXViewport *viewport;
{
  PEXRendererAttributes		rAttrs;	/* renderer attributes */

  rAttrs.npc_subvolume = *volume;
  rAttrs.viewport = *viewport;
  PEXChangeRenderer( theDisplay, theRenderObj, 
		    PEXRANPCSubVolume|PEXRAViewport, &rAttrs );

  theMatrixValidFlag = 0;
  theVolume = *volume;
  theViewport = *viewport;
 }

/*************************************************************************
 * P O S T - rdrPost
 *
 * put the struxid in the "to be redrawn" list.
 */
void  rdrPost( struxid )
long struxid;
{
  int i;
/*
 * Check to see if this strux is already in use.
 * This quite inefficient if you have lots of structures. Perhaps
 * keep a pointer to an encoded ROC packet with all of the executes.
 */
  for (i = 0; i < rPostCount; i++ )
    if (rPostTable[i] == struxid) 
      { printf("alarm, alread posted %d\n", struxid ); return; }

  rPostCount++;
  if (rPostCount == 1) {
    rPostTable = (long *)malloc(rPostCount*sizeof(long *));
  } else {
    rPostTable = (long *)realloc(rPostTable, rPostCount*sizeof(long *));
  }

  if (!rPostTable) {printf("alarm, malloc failed in rdrPost\n"); }

  rPostTable[rPostCount-1] = struxid;
}

/*************************************************************************
 *  DeleteAllStrux
 *
 *  PHIGS Workstation Version, get all of the posted structres and delete them
 *  Should probably do a PEXGetDescendants, to be really thorough.
 */
void  rdrDeleteAll()
{
  PEXDestroyStructures(theDisplay, rPostCount, (PEXStructure *)rPostTable);
  rPostCount = 0;
  free(rPostTable);
  theNewStrux = 0;
  theSelectedElement = -1;
}


/*************************************************************************
 * PickSomething - returns structure and element, else element == -1
 */
#if NeedFunctionPrototypes
/* need to do this to avoid warning about initialization, due to shorts */
void  rdrPickOne( short x, short y, long *strux, int *element )
#else
void  rdrPickOne( x, y, strux, element )
     short x;
     short y;
     long *strux;
     int *element;
#endif
{
  PEXPDDCHitBox hitInfo;
  PEXPickPath *pickReturn;
  int i;
  int statusReturn, hidden;
  XColor                        background;
  Drawable                      id;
  int                           dbstat;

  hitInfo.position.x = x;
  hitInfo.position.y = theWinHeight - y;
  hitInfo.distance = 10;

/*
 * this is just to test both cases.
 * Since there is the default structure in the beginning. When we add one we
 * have two, to get the PEXPickOne, delete all then add something.
 */
  if (rPostCount == 1) {
    pickReturn =  PEXPickOne(theDisplay, theWindow, theRenderObj,
			     rPostTable[0],  PEXPickLast,  
			     PEXPickDeviceDCHitBox, (PEXPickRecord *)&hitInfo, 
			     &statusReturn, &hidden);
  } else {
    PEXBeginPickOne(theDisplay, theWindow, theRenderObj, (XID)1, PEXPickLast,  
		    PEXPickDeviceDCHitBox, (PEXPickRecord *)&hitInfo );
    
    for (i = 0; i < rPostCount; i++ )
      PEXExecuteStructure(theDisplay, theRenderObj, PEXOCRender, rPostTable[i]);
    
    pickReturn = PEXEndPickOne(theDisplay, theRenderObj,
			       &statusReturn, &hidden);
  }

  if (statusReturn == PEXPick) {
    /*
     * Get the last struxure/element in the pick path
     */
    *strux   = pickReturn->elements[pickReturn->count-1].sid;
    *element = pickReturn->elements[pickReturn->count-1].offset;
  } else {
    *element = -1;
  }

  if (statusReturn == PEXPick) {
    PEXColor echoColor;
    PEXElementRef eRefs[4];
    int i;
    PEXRendererAttributes	rAttrs;	/* renderer attributes */
    int count, offset;
/*
 * just testing for now. Really should try to do something useful.
 * count -1 here is because we are skipping over the dummy structure
 * in the return path.
 * we are copying from a pick return path to an element ref path
 */
    if (rPostCount == 1) {
      count = pickReturn->count;
      offset = 0;
    } else {
      count = pickReturn->count - 1;
      offset = 1;
    }
    if (count > 4) return;
    for (i = 0; i < count; i++ ) {
      eRefs[i].structure =  pickReturn->elements[i+offset].sid;
      eRefs[i].offset    =  pickReturn->elements[i+offset].offset;
    }

    rAttrs.clear_image = False;
    PEXChangeRenderer( theDisplay, theRenderObj, PEXRAClearImage, &rAttrs );

    background.pixel = BlackPixel(theDisplay,theScreen);
    background.red = 0;
    background.green = 0;
    background.blue = 0;
    background.flags = DoRed|DoGreen|DoBlue;
    if (theDBFlag)
      dbstat = PEXUtDBConfig(theDisplay, theWindow, False,&background,False, &id);

    PEXBeginRendering(theDisplay, theWindow, theRenderObj);
    PEXAccumulateState(theDisplay, theRenderObj, count, eRefs );
    echoColor.rgb.red   = 1.0;
    echoColor.rgb.green = 1.0;
    echoColor.rgb.blue  = 0.0;
    PEXSetLineColor( theDisplay, theRenderObj, PEXOCRender,
		    PEXColorTypeRGB, &echoColor );
    PEXSetTextColor( theDisplay, theRenderObj, PEXOCRender,
		    PEXColorTypeRGB, &echoColor );
    PEXSetSurfaceColor( theDisplay, theRenderObj, PEXOCRender,
		    PEXColorTypeRGB, &echoColor );
    PEXRenderElements(theDisplay, theRenderObj, *strux, PEXBeginning, *element,
			     PEXBeginning, *element );
    PEXEndRendering(theDisplay, theRenderObj, 1);

    XSync(theDisplay, 0);
    if (theDBFlag) {
      dbstat = PEXUtDBConfig(theDisplay, theWindow, True,&background,False,&id);	
      printf(" dbstat %x, id %x, win %x\n", dbstat, id, theWindow );
      if (theWindow != id) {
        printf(" Pixmap or MBX - reassinging theWindow! \n");
        the3DBuffer = id;
      } else {
        the3DBuffer = theWindow;
      }
    }
    rAttrs.clear_image = True;
    PEXChangeRenderer( theDisplay, theRenderObj, PEXRAClearImage, &rAttrs );
  }

}

/*************************************************************************
 * rdrPickAll - 
 */
#if NeedFunctionPrototypes
/* need to do this to avoid warning about initialization, due to shorts */
void rdrPickAll( short x, short y, short x2, short y2,
		int *nFound, long **struxArray, int **elemArray )
#else
void rdrPickAll( x, y, x2, y2, nFound, struxArray, elemArray )
     short x;
     short y;
     short x2;
     short y2;
     int *nFound;
     long **struxArray;
     int **elemArray;
#endif
{
  PEXPDNPCHitVolume  hitBox;
  PEXPickPath *pickReturn, *pps;
  int i;
  int statusReturn, hidden;
  PEXMatrix XCtoNPC;
  PEXCoord p[2];
  int more;
  unsigned long hitCount;
  float t;
  int notDone = 1;

  *nFound = 0;

  i = PEXXCToNPCTransform( &theVolume, (PEXDeviceCoord *)&theViewport,
			  theWinHeight, XCtoNPC );
  if (i!=0) {printf("rdrPickAll bad XCtoNPC %d\n", i); return; }

  p[0].x = x;
  p[0].y = y;
  p[0].z = 1.0;
  p[1].x = x2;
  p[1].y = y2;
  p[1].z = 0.0;

  PEXTransformPoints(XCtoNPC, 2, p, (PEXCoord *)&hitBox);

#define SWAP(a,b) {t=a;a=b;b=t;}

  if (hitBox.min.x > hitBox.max.x) SWAP(hitBox.min.x, hitBox.max.x);
  if (hitBox.min.y > hitBox.max.y) SWAP(hitBox.min.y, hitBox.max.y);
  if (hitBox.min.z > hitBox.max.z) SWAP(hitBox.min.z, hitBox.max.z);

  if (rPostCount == 1) {
    PEXRendererAttributes	rAttrs;	/* renderer attributes */
    PEXElementRef       ep[1];

    rAttrs.pick_start_path.count = 1;
    rAttrs.pick_start_path.elements = ep;
    rAttrs.pick_start_path.elements[0].structure = rPostTable[0];
    rAttrs.pick_start_path.elements[0].offset = 0; /* begins after */

    PEXChangeRenderer(theDisplay, theRenderObj, PEXRAPickStartPath, &rAttrs );
    *nFound = 0;

    while (notDone) {
      pickReturn = PEXPickAll(theDisplay, theWindow, theRenderObj,
			    PEXPickLast, /* max hits */3, 
			    PEXPickDeviceNPCHitVolume,
			    (PEXPickRecord *)&hitBox,
			    &statusReturn, &more, &hitCount );

      if (statusReturn == PEXPick) {
	if (*nFound == 0) {
	  *struxArray = (long *)malloc(hitCount*sizeof(long));
	  *elemArray = (int *)malloc(hitCount*sizeof(int));
	} else {
	  *struxArray = (long *)realloc((char *)*struxArray,
					(*nFound+hitCount)*sizeof(long));
	  *elemArray = (int *)realloc((char *)*elemArray,
				      (*nFound+hitCount)*sizeof(int));
	}

	for (i = *nFound, pps = pickReturn; i < *nFound+(int)hitCount; i++ ){
	  /*
	   * Get the last struxure/element in the pick path
	   printf("depth %d, leaf - sid %x, element %x\n", pps->count, 
	   */ 
	  (*struxArray)[i] = pps->elements[pps->count-1].sid;
	  (*elemArray)[i] = pps->elements[pps->count-1].offset;
	  pps++;
	}
	*nFound += hitCount;
	PEXFreePickPaths(hitCount,pickReturn);
      } else {
	notDone = 0;
      }
      if (more == PEXNoMoreHits) notDone = 0;
    } /* end while notDone */
  } else {
    PEXBeginPickAll(theDisplay, theWindow, theRenderObj, 1,
		    PEXPickLast,  False, /* max hits */42, 
		    PEXPickDeviceNPCHitVolume, (PEXPickRecord *)&hitBox );
    
    for (i = 0; i < rPostCount; i++ )
      PEXExecuteStructure(theDisplay, theRenderObj, PEXOCRender, rPostTable[i]);
    
    pickReturn = PEXEndPickAll(theDisplay, theRenderObj,
			     &statusReturn, &more, &hitCount );


    if (statusReturn == PEXPick) {
      *struxArray = (long *)malloc(hitCount*sizeof(long));
      *elemArray = (int *)malloc(hitCount*sizeof(int));
      for (i = 0, pps = pickReturn; i < (int)hitCount; i++ ){
	/*
	 * Get the last struxure/element in the pick path
	 *  printf("depth %d, leaf - sid %x, element %x\n", pps->count, 
	 */ 
	(*struxArray)[i] = pps->elements[pps->count-1].sid;
	(*elemArray)[i] = pps->elements[pps->count-1].offset;
	pps++;
      }
      *nFound = hitCount;
      PEXFreePickPaths(hitCount,pickReturn);
    } else {
      printf("no luck in pick all\n");
    }
  }
}

int rdrMapXToNPC( count, points)
     int count;
     PEXCoord *points;
{
  int i;
  PEXMatrix XCtoNPC;

  i = PEXXCToNPCTransform( &theVolume, (PEXDeviceCoord *)&theViewport,
			  theWinHeight, XCtoNPC );
  if (i!=0) {printf("rdrPickAll bad XCtoNPC %d\n", i); return (0); }

  PEXTransformPoints(XCtoNPC, count, points, points);
  return (1);
}

int rdrReconfigureWindow( wkid, width, height)
     long wkid;
     int width;
     int height;
{
   if (theWimpyWindow)
     XResizeWindow(theDisplay, theWindow, width, height );

   the3DBuffer = PEXUtDBResize(theDisplay, theWindow);
}

int rdrGetColorFromIndex(cIndex, rgb)
     int cIndex;
     PEXColorRGB *rgb;
{
  PEXRendererAttributes *rAttr;
  int table_type;
  int defined;
  PEXColorSpecifier *entry;

  rAttr = PEXGetRendererAttributes( theDisplay, theRenderObj, PEXRAColorTable);
  if (!rAttr) return (0);
  entry = (PEXColorSpecifier *)PEXGetTableEntry(theDisplay, rAttr->color_table,
						cIndex, PEXSetValue, &defined,
						&table_type);
  if (table_type != PEXLUTColor) {
    printf("rdrGetColorFromIndex fix it!!!\n");
    return (0);
  }
  if (entry->type != PEXColorTypeRGB) printf("RGB NOT %d\n");
  *rgb = entry->value.rgb;

  PEXFreeTableEntries(table_type, 1,(PEXPointer)entry);
  PEXFreeRendererAttributes(rAttr);
  return (1);
}

/*************************************************************************
 * U N P O S T - rdrUnpost
 *
 * remove the struxid from the "to be redrawn" list.
 */
void  rdrUnpost( strux )
long strux;
{
  int i;
/*
 * Check to see if this strux is already in use.
 * This quite inefficient if you have lots of structures. Perhaps
 * keep a pointer to an encoded ROC packet with all of the executes.
 */
  for (i = 0; i < rPostCount; i++ )
    if (rPostTable[i] == strux) {
      if (i < rPostCount-1) {
	bcopy(&rPostTable[i+1], &rPostTable[i], sizeof(long)*(rPostCount-i-1));
      }
      rPostCount--;
      return;
    }
  /* no can do */
  printf("tried to unpost non existent strux = %x\n", strux);
}


/*
 * init the procedure pointer structure
 */
renderProcs rdrProcs = { rdrInit, rdrReDraw, rdrMapXToMC, rdrMapMCToX, 
			   rdrSetView, rdrSetNPCToDC, rdrPost, rdrDeleteAll,
			   rdrPickOne, rdrPickAll, rdrMapXToNPC,
			   rdrReconfigureWindow, rdrGetColorFromIndex, 
			   rdrUnpost };

