CCL Home Page
Up Directory CCL ScianDraw
/*ScianDraw.c
  Drawing routines for various types of objects
  Eric Pepke
  March 28, 1990
*/

/* JEL added PostScript drawing 4/2/92 */

#include "Scian.h"
#include "ScianTypes.h"
#include "ScianArrays.h"
#include "ScianLists.h"
#include "ScianIDs.h"
#include "ScianWindows.h"
#include "ScianDraw.h"
#include "ScianObjWindows.h"
#include "ScianColors.h"
#include "ScianPictures.h"
#include "ScianStyle.h"
#include "ScianFontSystem.h"

extern short LinToGamma[];

DrawingState drawingStates[NDRAWINGSTATES];	/*Stack of drawing states*/
int curDrawingStateIndex = 0;			/*Current drawing state*/

Bool drawMouse = false;				/*True iff draw on next mouse*/
extern int curMouse;				/*Current mouse button*/

int drawingMode = DRAW_SCREEN;			/*Drawing to the screen*/
FILE *drawFile = 0;				/*File in which to draw*/

int imageSubSample = 0;				/*Subsampling offset for image*/

Bool fullScreen = false;			/*True iff drawing to full screen*/

Matrix Identity = {{1.0, 0.0, 0.0, 0.0},
		   {0.0, 1.0, 0.0, 0.0},
		   {0.0, 0.0, 1.0, 0.0},
		   {0.0, 0.0, 0.0, 1.0}};

/* globals used for PostScript drawing */
FILE *psFile;		/* pointer to temp file */
int iconsUsed[32];	/* maximum number of *different* icons in EPS file is 32 */
int numIconsUsed;	/* number used so far = next index to use */
Bool evenOnly = false;
Bool oddOnly = false;

#ifdef PROTO
void BeginTranslucent(void)
#else
void BeginTranslucent()
#endif
/*Begins translucent drawing*/
{
#ifdef GRAPHICS
    if (evenOnly)
    {
	setpattern(EVENGREYPAT);
    }
    else if (oddOnly)
    {
	setpattern(ODDGREYPAT);
    }
    else
    {
	setpattern(GREYPAT);
    }
#endif
}

#ifdef PROTO
void EndTranslucent(void)
#else
void BeginTranslucent()
#endif
/*Begins translucent drawing*/
{
#ifdef GRAPHICS
    if (evenOnly)
    {
	setpattern(EVENPAT);
    }
    else if (oddOnly)
    {
	setpattern(ODDPAT);
    }
    else
    {
	setpattern(SOLIDPAT);
    }
#endif
}

#ifdef PROTO
void BeginEvenOnly(void)
#else
void BeginEvenOnly()
#endif
/*Begins drawing on only even lines*/
{
    evenOnly = true;
#ifdef GRAPHICS
    setpattern(EVENPAT);
#endif
}

#ifdef PROTO
void EndEvenOnly(void)
#else
void EndEvenOnly()
#endif
/*Ends drawing on only even lines*/
{
    evenOnly = false;
#ifdef GRAPHICS
    setpattern(SOLIDPAT);
#endif
}

#ifdef PROTO
void BeginOddOnly(void)
#else
void BeginOddOnly()
#endif
/*Begins drawing on only odd lines*/
{
    oddOnly = true;
#ifdef GRAPHICS
    setpattern(ODDPAT);
#endif
}

#ifdef PROTO
void EndOddOnly(void)
#else
void EndEvenOnly()
#endif
/*Ends drawing on only odd lines*/
{
    oddOnly = false;
#ifdef GRAPHICS
    setpattern(SOLIDPAT);
#endif
}

#if 0
void EchoDraw(s)
char *s;
{
    int k;
    for (k = 0; k < curDrawingStateIndex; ++k) printf("  ");
    printf("%s\n", s);
}
#else
#define EchoDraw(s)
#endif

#ifdef PROTO
void PushTransformation(void)
#else
void PushTransformation()
#endif
/*Pushes the transformation*/
{
#ifdef GRAPHICS
    pushmatrix();
#endif
}

#ifdef PROTO
void PopTransformation(void)
#else
void PopTransformation()
#endif
/*Pushes the transformation*/
{
#ifdef GRAPHICS
    popmatrix();
#endif
}

void PushDrawingState()
/*Pushes the drawing state, producing a copy of the top drawing state*/
{
    int k;

    ++curDrawingStateIndex;
    if (curDrawingStateIndex >= NDRAWINGSTATES)
    {
	fprintf(stderr, "SciAn: Panic, drawing state overflow\n");
	exit(-1);
    }

    CURSTATE . window = LASTSTATE . window;
    CURSTATE . initialWindow = false;
    for (k = 0; k < 4; ++k)
    {
	CURSTATE . screenMask[k] = LASTSTATE . screenMask[k];
	CURSTATE . viewport[k] = LASTSTATE . viewport[k];
    }
    for (k = 0; k < 2; ++k)
    {
	CURSTATE . origin[k] = LASTSTATE . origin[k];
	CURSTATE . translation[k] = LASTSTATE . translation[k];
    }
}

void PopDrawingState()
/*Pops the drawing state and sets everything back to what it was.
  As a side-effect, may set the window*/
{
    Bool setViewport = false;	/*True iff the viewport needs to be set*/

    --curDrawingStateIndex;

    if (curDrawingStateIndex < 0)
    {
	fprintf(stderr, "SciAn: Panic, drawing state underflow\n");
	exit(-1);
    }

    if (!(CURSTATE . window))
    {
	/*No window, do nothing*/
	return;
    }

    if (NEXTSTATE . initialWindow)
    {
	/*New window!  Need to set everything*/
	SelWindow(CURSTATE . window);

#ifdef GRAPHICS
	shademodel(FLAT);
	concave(TRUE);
	backface(FALSE);
	lmcolor(LMC_COLOR);
	{
	    float n[3];
	    n[0] = 0.0;
	    n[1] = 0.0;
	    n[2] = 1.0;
	    N3F(n);
	}
#endif
	setViewport = true;
    }

    if (setViewport ||
	(CURSTATE . viewport[0] != NEXTSTATE . viewport[0]) ||
	(CURSTATE . viewport[1] != NEXTSTATE . viewport[1]) ||
	(CURSTATE . viewport[2] != NEXTSTATE . viewport[2]) ||
	(CURSTATE . viewport[3] != NEXTSTATE . viewport[3]))
    {
	/*New viewport.  Need to set viewport*/
	setViewport = true;

#ifdef GRAPHICS
	if (drawingMode == DRAW_SCREEN)
	{
	    /*Set the viewport in pixel-centered coordinates*/
	    viewport((Screencoord) CURSTATE . viewport[0],
		 (Screencoord) CURSTATE . viewport[1] - 1, 
		 (Screencoord) CURSTATE . viewport[2],
		 (Screencoord) CURSTATE . viewport[3] - 1);

	    /*Set up an orthographic perspective setup to map to this viewport*/
	    MakeOrthoXform();
	}
	else if (drawingMode == DRAW_POSTSCRIPT && psFile)
	{
	    fprintf(psFile, "%%new viewport\n%d %d translate\n",
	    (int) CURSTATE . translation[0], (int) CURSTATE . translation[1]);

	}
#endif
    }

    if (setViewport || 
	(CURSTATE . screenMask[0] != NEXTSTATE . screenMask[0]) ||
	(CURSTATE . screenMask[1] != NEXTSTATE . screenMask[1]) ||
	(CURSTATE . screenMask[2] != NEXTSTATE . screenMask[2]) ||
	(CURSTATE . screenMask[3] != NEXTSTATE . screenMask[3]))
    {
	/*New screen mask.  Need to set it*/

	if (drawingMode == DRAW_SCREEN)
	{
#ifdef GRAPHICS
	    scrmask((Screencoord) CURSTATE . screenMask[0],
		(Screencoord) CURSTATE . screenMask[1] - 1, 
		(Screencoord) CURSTATE . screenMask[2],
		(Screencoord) CURSTATE . screenMask[3] - 1);
#endif
	}
	else if (drawingMode == DRAW_POSTSCRIPT && psFile)
	{
	    int sl, sr, sb, st;
	    sl = CURSTATE . screenMask[0];
	    sr = CURSTATE . screenMask[1];
	    sb = CURSTATE . screenMask[2];
	    st = CURSTATE . screenMask[3];

	    fprintf(psFile,
"resetclip newpath %d %d moveto %d %d lineto %d %d lineto %d %d lineto closepath clip newpath\n",
		sl, st, sr, st, sr, sb, sl, sb);
	}
    }

    if ((setViewport == false) &&
	(CURSTATE . translation[0] != NEXTSTATE . translation[0] ||
	 CURSTATE . translation[1] != NEXTSTATE . translation[1]))
    {
	if (drawingMode == DRAW_SCREEN)
	{
#ifdef GRAPHICS
	    /*Translate back, but only if only the translation is different*/
	    translate(	(Coord) (CURSTATE . translation[0] - NEXTSTATE . translation[0]),
			(Coord) (CURSTATE . translation[1] - NEXTSTATE . translation[1]),
			(Coord) 0.0);
#endif
	}
	else if (drawingMode == DRAW_POSTSCRIPT && psFile)
	{
            fprintf(psFile, "%d %d translate\n",
        	(int) (CURSTATE . translation[0] - NEXTSTATE . translation[0]),
		(int) (CURSTATE . translation[1] - NEXTSTATE . translation[1]));
	}
    }
}

#ifdef PROTO
void SetDrawingWindow(WinInfoPtr window)
#else
void SetDrawingWindow(window)
WinInfoPtr window;
#endif
/*Sets to draw into a new window.  Side effect--selects the window*/
{
    int k;
    int l, r, b, t, ox, oy;

    EchoDraw("SetDrawingWindow");

    /*Save the current window, etc.*/
    PushDrawingState();

    /*Select this window and use it*/
    SelWindow(window);
#ifdef GRAPHICS
    shademodel(FLAT);
    concave(TRUE);
    backface(FALSE);
    lmcolor(LMC_COLOR);
	{
	    float n[3];
	    n[0] = 0.0;
	    n[1] = 0.0;
	    n[2] = 1.0;
	    N3F(n);
	}
#endif

    CURSTATE . window = window;
    CURSTATE . initialWindow = true;

    /*Zero translation*/
    for (k = 0; k < 2; ++k)
    {
	CURSTATE . translation[k] = 0;
    }

    /*Get the bounds of the window, in Mac style coordinates*/
    GetWindowBounds(&l, &r, &b, &t);

    /*Save the bounds as the viewport and mask*/
    CURSTATE . screenMask[0] = CURSTATE . viewport[0] = l;
    CURSTATE . screenMask[1] = CURSTATE . viewport[1] = r;
    CURSTATE . screenMask[2] = CURSTATE . viewport[2] = b;
    CURSTATE . screenMask[3] = CURSTATE . viewport[3] = t;

    /*Get the origin of the window*/
    GetWindowOrigin(&ox, &oy);
    CURSTATE . origin[0] = ox;
    CURSTATE . origin[1] = oy;
    
#ifdef GRAPHICS
    if (drawingMode == DRAW_SCREEN)
    {
	/*Set the viewport in pixel-centered coordinates*/
	viewport((Screencoord) l, (Screencoord) r - 1, 
	 (Screencoord) b, (Screencoord) t - 1);

	/*Set up an orthographic perspective setup to map to this viewport*/
	MakeOrthoXform();
    }
#endif
}

void RestoreDrawingWindow()
/*Restores the window area to what it was before.  Side effect--sets the
  window*/
{
    /*Pop the drawing state*/
    PopDrawingState();
    EchoDraw("RestoreDrawingWIndow");
}

#ifdef PROTO
void SetSubPort(int l, int r, int b, int t)
#else
void SetSubPort(l, r, b, t)
int l, r, b, t;
#endif
/*Sets to draw into a subport.  Side effect--selects the window*/
{
    int k;

    EchoDraw("SetSubPort");

    /*Save the current state.*/
    PushDrawingState();

    /*Pretend its a new window*/
    CURSTATE . initialWindow = true;

    /*Save the bounds as the viewport*/
    CURSTATE . viewport[0] = l;
    CURSTATE . viewport[1] = r;
    CURSTATE . viewport[2] = b;
    CURSTATE . viewport[3] = t;

    /*Shift the mask over by the effective offset*/
    CURSTATE . screenMask[0] -= CURSTATE . translation[0];
    CURSTATE . screenMask[1] -= CURSTATE . translation[0];
    CURSTATE . screenMask[2] -= CURSTATE . translation[1];
    CURSTATE . screenMask[3] -= CURSTATE . translation[1];

    /*Make a screen mask that is the intersection*/
    if (CURSTATE . viewport[0] > CURSTATE . screenMask[0])
	CURSTATE . screenMask[0] = CURSTATE . viewport[0];
    if (CURSTATE . viewport[1] < CURSTATE . screenMask[1])
	CURSTATE . screenMask[1] = CURSTATE . viewport[1];
    if (CURSTATE . viewport[2] > CURSTATE . screenMask[2])
	CURSTATE . screenMask[2] = CURSTATE . viewport[2];
    if (CURSTATE . viewport[3] < CURSTATE . screenMask[3])
	CURSTATE . screenMask[3] = CURSTATE . viewport[3];

    /*Zero translation*/
    for (k = 0; k < 2; ++k)
    {
	CURSTATE . translation[k] = 0;
    }

    /*Bump up origin*/
    CURSTATE . origin[0] += l;
    CURSTATE . origin[1] += b;

    /*Save the bounds as the viewport and mask*/
    CURSTATE . screenMask[0] = CURSTATE . viewport[0] = l;
    CURSTATE . screenMask[1] = CURSTATE . viewport[1] = r;
    CURSTATE . screenMask[2] = CURSTATE . viewport[2] = b;
    CURSTATE . screenMask[3] = CURSTATE . viewport[3] = t;

#ifdef GRAPHICS
    if (drawingMode == DRAW_SCREEN)
    {
	/*Set the viewport in pixel-centered coordinates*/
	viewport((Screencoord) l, (Screencoord) r - 1, 
	     (Screencoord) b, (Screencoord) t - 1);

	/*Set up an orthographic perspective setup to map to this viewport*/
	MakeOrthoXform();

	/*Set the screen mask*/
	scrmask((Screencoord) CURSTATE . screenMask[0],
		(Screencoord) CURSTATE . screenMask[1] - 1, 
		(Screencoord) CURSTATE . screenMask[2],
		(Screencoord) CURSTATE . screenMask[3] - 1);
    }
    else if (drawingMode == DRAW_POSTSCRIPT && psFile)
    {
	fprintf(psFile, "%%Call to SetSubPort!\n");
    }
#endif
}

void RestoreSubPort()
/*Restores the window area to what it was before.  Side effect--sets the
  window*/
{
    /*Pop the drawing state*/
    PopDrawingState();
    EchoDraw("RestoreSubPort");
}

#ifdef PROTO
void SetOrthoPick(void)
#else
void SetOrthoPick()
#endif
/*Sets to do an ortho pick.*/
{
    int k;

    EchoDraw("SetOrthoPick");

    /*Save the current state.*/
    PushDrawingState();

    /*Pretend its a new window*/
    CURSTATE . initialWindow = true;
}

#ifdef PROTO
void RestoreOrthoPick(void)
#else
void RestoreOrthoPick()
#endif
/*Restores the pickiness to what it was before.  Side effect--sets the
  window*/
{
    /*Pop the drawing state*/
    PopDrawingState();
    EchoDraw("RestoreOrthoPick");
}

void SetOrigin(x, y)
int x, y;
/*Sets the origin to x, y WITHIN current translation*/
{
    EchoDraw("SetOrigin");
    /*Save drawing state*/
    PushDrawingState();
  
    CURSTATE . translation[0] += x;
    CURSTATE . translation[1] += y;

    if (drawingMode == DRAW_SCREEN)
    {
#ifdef GRAPHICS
	translate((Coord) x, (Coord) y, (Coord) 0.0);
#endif
    }
    else if (drawingMode == DRAW_POSTSCRIPT && psFile)
    {
        fprintf(psFile, "%d %d translate\n", x, y);
    }
}

void RestoreOrigin()
/*Restores the origin to what it was*/
{
    PopDrawingState();
    EchoDraw("RestoreOrigin");
}

#ifdef PROTO
void FullScreen(Bool whether)
#else
void FullScreen(whether)
Bool whether;
#endif
/*Sets full screen mode to whether*/
{
    if (whether == fullScreen) return;

    fullScreen = whether;

#ifdef GRAPHICS
    if (fullScreen)
    {
	fullscrn();
    }
    else
    {
	endfullscrn();
    }
#endif
}

void MakeOrthoXform()
/*Makes an orthographic transformation based on the current state.*/
{
    if (drawingMode == DRAW_SCREEN)
    {
#ifdef GRAPHICS
	mmode(MPROJECTION);
	ortho2( 0.0,
		(float) (CURSTATE . viewport[1] - CURSTATE . viewport[0]),
		0.0,
		(float) (CURSTATE . viewport[3] - CURSTATE . viewport[2]));
	mmode(MVIEWING);
	loadmatrix(Identity);

	translate((Coord) CURSTATE . translation[0],
		  (Coord) CURSTATE . translation[1], (Coord) 0.0);
#endif
    }
}

void MakePickOrthoXform()
/*Makes an orthographic transformation based on the current state.*/
{
#ifdef GRAPHICS
	ortho2( 0.0,
		(float) (CURSTATE . viewport[1] - CURSTATE . viewport[0]),
		0.0,
		(float) (CURSTATE . viewport[3] - CURSTATE . viewport[2]));
#endif
}

#ifdef PROTO
void SetClipRect(int left, int right, int bottom, int top)
#else
void SetClipRect(left, right, bottom, top)
int left, right, bottom, top;
#endif
/*Sets the current clipping rectangle to left, right, bottom, top*/
{
    int sl, sr, sb, st;

    EchoDraw("SetClipRect");

    /*Save the current state*/
    PushDrawingState();

    left += CURSTATE . translation[0];
    right += CURSTATE . translation[0];
    bottom += CURSTATE . translation[1];
    top += CURSTATE . translation[1];

    sl = CURSTATE . screenMask[0];
    sr = CURSTATE . screenMask[1];
    sb = CURSTATE . screenMask[2];
    st = CURSTATE . screenMask[3];

    if (left > sl) sl = MIN(left, sr);
    if (right < sr) sr = MAX(right, sl);
    if (bottom > sb) sb = MIN(bottom, st);
    if (top < st) st = MAX(top, sb);

    CURSTATE . screenMask[0] = sl;
    CURSTATE . screenMask[1] = sr;
    CURSTATE . screenMask[2] = sb;
    CURSTATE . screenMask[3] = st;

    if (drawingMode == DRAW_SCREEN)
    {
#ifdef GRAPHICS
	scrmask(sl, sr - 1, sb, st - 1);
#endif
    }
    else if (drawingMode == DRAW_POSTSCRIPT && psFile)
    {
        fprintf(psFile,
"resetclip newpath %d %d moveto %d %d lineto %d %d lineto %d %d lineto closepath clip newpath\n",
	    sl, st, sr, st, sr, sb, sl, sb);
    }
}

void RestoreClipRect()
/*Restores the clipping rectangle to what it was before*/
{
    PopDrawingState();
    EchoDraw("RestoreClipRect");
}

void CurOffset(x, y)
int *x, *y;
/*Returns the current offset of the internal mouse coords from global*/
{
    int ox, oy;

    *x = CURSTATE . origin[0] + CURSTATE . translation[0];
    *y = CURSTATE . origin[1] + CURSTATE . translation[1];
}

void UD(void)
/*Updated drawing according to belated DrawMe's*/
{
#ifdef GRAPHICS
    if (drawMouse)
    {
	IdleAllWindows();
	drawMouse = false;
    }
#endif
}

void UpdateDrawing(void)
/*Updates drawing according to belated DrawMe's*/
{
   UD();
}

#ifdef GRAPHICS
void DrawObj2(origObj, obj)
ObjPtr origObj, obj;
/*Draws origObj according to method in obj*/
{
    FuncTyp DrawFunction;			/*Method*/

    if (obj)
    {
	DrawObj2(origObj, ClassOf(obj));
	DrawFunction = Get1Method(obj, DRAW);
	if (DrawFunction)
	{
	    (*DrawFunction)(origObj);
	}
    }
}
#endif

void DrawObject(obj)
ObjPtr obj;
/*Draws obj.*/
{
#ifdef GRAPHICS
    ObjPtr picState;

    if (GetPredicate(obj, INHIBITDRAWING))
    {
	return;
    }

    if (GetPredicate(obj, HIDDEN))
    {
	return;
    }

    if (GetPredicate(obj, MULTIDRAW))
    {
	DrawObj2(obj, obj);
    }
    else
    {
	FuncTyp DrawFunction;			/*Method*/

	DrawFunction = GetMethod(obj, DRAW);
	if (DrawFunction)
	{
	    (*DrawFunction)(obj);
	}
    }
#endif
}

void ClipToMe(object)
ObjPtr object;
/*Sets the clipping rectangle to object*/
{
    int l, r, b, t;

    Get2DIntBounds(object, &l, &r, &b, &t);

    SetClipRect(l, r, b, t);
}

#ifdef INTERACTIVE
ObjPtr PressObject(obj, x, y, flags)
ObjPtr obj;
int x, y;
long flags;
/*Presses in obj at x, y*/
{
    FuncTyp PressFunction;
    PressFunction = GetMethod(obj, PRESS);
    if (PressFunction)
    {
	return (*PressFunction)(obj, x, y, flags);
    }
    else
    {
	return ObjFalse;
    }
}
#endif

ObjPtr DropObjects(obj, dropObj, x, y)
ObjPtr obj, dropObj;
int x, y;
/*Drops objects in list dropObj in obj at x, y*/
{
    FuncTyp method;
    method = GetMethod(obj, DROPOBJECTS);
    if (method)
    {
	return (*method)(obj, dropObj, x, y);
    }
    else
    {
	return ObjFalse;
    }
}

#ifdef PROTO
ObjPtr KeyDownObject(ObjPtr obj, int key, long flags)
#else
ObjPtr KeyDownObject(obj, key, flags)
ObjPtr obj;
int key;
long flags;
#endif
/*Does a keydown in obj*/
{
    FuncTyp method;
    method = GetMethod(obj, KEYDOWN);
    if (method)
    {
	return (*method)(obj, key, flags);
    }
    else
    {
	return ObjFalse;
    }
}

void FrameUIRect(left, right, bottom, top, uiColor)
int left, right, bottom, top, uiColor;
/*Frames a user interface rectangle*/
{
#ifdef GRAPHICS
    SetUIColor(uiColor);
    FrameRect(left, right, bottom, top);
#endif
}

void FrameRect(left, right, bottom, top)
int left, right, bottom, top;
/*Frames a rectangle*/
{
#ifdef GRAPHICS

    if (drawingMode == DRAW_SCREEN)
    {
#ifdef V3FISBUGGED
	move2(left + 0.5, top - 0.5);
	draw2(left + 0.5, bottom + 0.5);
	draw2(right - 0.5, bottom + 0.5);
	draw2(right - 0.5, top - 0.5);
	draw2(left + 0.5, top - 0.5);
#else
	float v[5][2];
	v[0][0] = left + 0.5;
	v[0][1] = top - 0.5;
	v[1][0] = left + 0.5;
	v[1][1] = bottom + 0.5;
	v[2][0] = right - 0.5;
	v[2][1] = bottom + 0.5;
	v[3][0] = right - 0.5;
	v[3][1] = top - 0.5;
	v[4][0] = left + 0.5;
	v[4][1] = top - 0.5;
	bgnline();
	v2f(v[0]);
	v2f(v[1]);
	v2f(v[2]);
	v2f(v[3]);
	v2f(v[4]);
	endline();
#endif
    }
    else if (drawingMode == DRAW_POSTSCRIPT && psFile)
    {
	fprintf(psFile, "%f setgray\n", PSColor());
        fprintf(psFile, "%d %d moveto %d %d lineto %d %d lineto %d %d lineto closepath stroke\n",
            left, top, right, top, right, bottom, left, bottom); 
    }
#endif
}

void FillUIRect(left, right, bottom, top, uiColor)
int left, right, bottom, top, uiColor;
/*Fills a user interface rectangle*/
{
#ifdef GRAPHICS

    SetUIColor(uiColor);
    FillRect(left, right, bottom, top);
#endif
}

void FillRect(left, right, bottom, top)
int left, right, bottom, top;
/*Fills a rectangle*/
{
#ifdef GRAPHICS
    FillIntQuad(left, bottom,
		 (right), bottom,
		 (right), (top),
		 left, (top));
#endif
}

void FillUIGauzeDisc(x, y, radius, uiColor)
int x, y, radius, uiColor;
/*Fills a disc in uiColor with gauze pattern*/
{
#ifdef GRAPHICS
    SetUIColor(uiColor);
    BeginTranslucent();
    circfi(x, y, radius);
    EndTranslucent();
#endif
}

void FillUIDisc(x, y, radius, uiColor)
int x, y, radius, uiColor;
/*Fills a disc in uiColor*/
{
#ifdef GRAPHICS
    SetUIColor(uiColor);
    if (drawingMode == DRAW_SCREEN)
    {
        circfi(x, y, radius);
    }
    else if (drawingMode == DRAW_POSTSCRIPT && psFile)
    {
	fprintf(psFile, "%f setgray\n", PSColor());
        fprintf(psFile, "newpath %d %d %d 0 360 arc fill\n", x, y, radius);
    }
#endif
}

void FillTri(x1, y1, x2, y2, x3, y3)
int x1, y1, x2, y2, x3, y3;
/*Fills a triangle*/
{
#ifdef GRAPHICS

    if (drawingMode == DRAW_SCREEN)
    {
	float v[3][2];
	v[0][0] = x1;
	v[0][1] = y1;
	v[1][0] = x2;
	v[1][1] = y2;
	v[2][0] = x3;
	v[2][1] = y3;
	bgnpolygon();
	v2f(v[0]);
	v2f(v[1]);
	v2f(v[2]);
	endpolygon();
    }
    else if (drawingMode == DRAW_POSTSCRIPT && psFile)
    {
	fprintf(psFile, "%f setgray\n", PSColor());
        fprintf(psFile, "%d %d moveto %d %d lineto %d %d lineto closepath fill\n",
            x1, y1, x2, y2, x3, y3); 
    }
#endif
}

void FillUITri(x1, y1, x2, y2, x3, y3, uiColor)
int x1, y1, x2, y2, x3, y3, uiColor;
/*Fills a triangle in uiColor*/ 
{ 
#ifdef GRAPHICS 
    SetUIColor(uiColor);
    FillTri(x1, y1, x2, y2, x3, y3);
#endif
}

void FillUIGauzeRect(left, right, bottom, top, uiColor)
int left, right, bottom, top, uiColor;
/*Fills a user interface rectangle as if it were gauze*/
{
#ifdef GRAPHICS

    SetUIColor(uiColor);
    BeginTranslucent();
    FillIntQuad(left, (top),
		 left, bottom,
		 (right), bottom,
		 (right), (top));
    EndTranslucent();
#endif
}

void DrawUILine(x1, y1, x2, y2, uiColor)
int x1, y1, x2, y2, uiColor;
{
#ifdef GRAPHICS

    SetUIColor(uiColor);
    DrawLine(x1, y1, x2, y2);
#endif
}

void DrawLine(x1, y1, x2, y2)
int x1, y1, x2, y2;
{
#ifdef GRAPHICS
    if (drawingMode == DRAW_SCREEN)
    {
#ifdef V3FISBUGGED
	move2(x1 + 0.5, y1 + 0.5);
	draw2(x2 + 0.5, y2 + 0.5);
#else
	float v[2][2];
	v[0][0] = x1 + 0.5;
	v[0][1] = y1 + 0.5;
	v[1][0] = x2 + 0.5;
	v[1][1] = y2 + 0.5;
	bgnline();
	v2f(v[0]);
	v2f(v[1]);
	endline();
#endif
    }
    else if (drawingMode == DRAW_POSTSCRIPT && psFile)
    {
	fprintf(psFile, "%f setgray\n", PSColor());
        fprintf(psFile, "%d %d moveto %d %d lineto stroke\n",
            x1, y1, x2, y2);
    }
#endif
}

void FillUIWedge(x, y, radius, start, end, uiColor)
int x, y, radius, start, end, uiColor;
/*Fills a solid wege at x, y with radius from start to end degrees*/
{
#ifdef GRAPHICS
    SetUIColor(uiColor);
    if (drawingMode == DRAW_SCREEN)
    {
	arcfi(x, y, radius, start * 10, end * 10);
    }
    else if (drawingMode == DRAW_POSTSCRIPT && psFile)
    {
	fprintf(psFile, "%f setgray\n", PSColor());
	fprintf(psFile, "newpath %d %d moveto %d %d %d %d %d arc closepath fill\n", 
	    x, y, x, y, radius, start, end);
    }
#endif
}

void DrawArc(x, y, radius, start, end)
int x, y, radius, start, end;
/*Draws an arc in the current color.  start and end are in degrees.*/
{
    if (drawingMode == DRAW_SCREEN)
    {
#ifdef GRAPHICS
	arci(x, y, radius, start * 10, end * 10);
#endif
    }
    else if (drawingMode == DRAW_POSTSCRIPT && psFile)
    {
	fprintf(psFile, "%f setgray\n", PSColor());
	fprintf(psFile, "newpath %d %d %d %d %d arc stroke\n", 
	    x, y, radius, start, end);
    }
}

#ifdef PROTO
void FillSpaceRect(real x1, real y1, real z1,
		   real x2, real y2, real z2,
		   real x3, real y3, real z3,
		   real x4, real y4, real z4,
		   real nx, real ny, real nz)
#else
void FillSpaceRect( x1,  y1,  z1,
		    x2,  y2,  z2,
		    x3,  y3,  z3,
		    x4,  y4,  z4,
		    nx,  ny,  nz)
real x1; real y1; real z1;
real x2; real y2; real z2;
real x3; real y3; real z3;
real x4; real y4; real z4;
real nx; real ny; real nz;
#endif
/*Draws a rectangle in space around [xyz]1 through [xyz]4 using n[xyz]
  as normal.  If n[xyz] is 0, doesn't do a normal*/
{
#ifdef GRAPHICS
    float v[4][3];
    float n[3];

    v[0][0] = x1;
    v[0][1] = y1;
    v[0][2] = z1;
    v[1][0] = x2;
    v[1][1] = y2;
    v[1][2] = z2;
    v[2][0] = x3;
    v[2][1] = y3;
    v[2][2] = z3;
    v[3][0] = x4;
    v[3][1] = y4;
    v[3][2] = z4;

    if (nx != 0.0 || ny != 0.0 || nz != 0.0)
    {
	n[0] = nx;
	n[1] = ny;
	n[2] = nz;
    }
    bgnpolygon();
    N3F(n);
    v3f(v[0]);
    v3f(v[1]);
    v3f(v[2]);
    v3f(v[3]);
    endpolygon();
#endif
}

#ifdef PROTO
void FrameSpaceRect(real x1, real y1, real z1,
		   real x2, real y2, real z2,
		   real x3, real y3, real z3,
		   real x4, real y4, real z4)
#else
void FrameSpaceRect( x1,  y1,  z1,
		    x2,  y2,  z2,
		    x3,  y3,  z3,
		    x4,  y4,  z4)
real x1; real y1; real z1;
real x2; real y2; real z2;
real x3; real y3; real z3;
real x4; real y4; real z4;
#endif
/*Frames a rectangle in space around [xyz]1 through [xyz]4*/
{
    DrawSpaceLine(x1, y1, z1, x2, y2, z2);
    DrawSpaceLine(x2, y2, z2, x3, y3, z3);
    DrawSpaceLine(x3, y3, z3, x4, y4, z4);
    DrawSpaceLine(x4, y4, z4, x1, y1, z1);
}

#ifdef PROTO
void DrawSpaceLine(real x1, real y1, real z1, real x2, real y2, real z2)
#else
void DrawSpaceLine(x1, y1, z1, x1, y1, z1)
real x1; real y1; real z1;
real x2; real y2; real z2;
#endif
/*Draws a line in a space*/
{
    float v[2][3];
#ifdef GRAPHICS

#ifdef V3FISBUGGED
    move(x1, y1, z1);
    draw(x2, y2, z2);
#else
    /*Draws a line in a space*/
    v[0][0] = x1;
    v[0][1] = y1;
    v[0][2] = z1;
    v[1][0] = x2;
    v[1][1] = y2;
    v[1][2] = z2;
    bgnline();
    v3f(v[0]);
    v3f(v[1]);
    endline();
#endif
#endif
}

#ifdef PROTO
void DrawSpacePanelLine(real x1, real y1, real x2, real y2, real width, int arrow,
                real arrowParams[4][2])
#else
void DrawSpacePanelLine(x1, y1, x2, y2, width, arrow, arrowParams)
real x1, y1, x2, y2, width;
int arrow;
real arrowParams[4][2];
#endif
/*Draws a space panel line*/
/* DIK need to make PostScript version */
{
#ifdef GRAPHICS
    if (x1 == y1 && x2 == y2)
    {
	/*Just a point*/
	long v[2];

	bgnpoint();
	v[0] = x1;
	v[1] = y1;
	v2i(v);
	endpoint();
    }
    else if (width <= 1 && arrow == AH_NO_ARROW)
    {
	/*Plain line*/
	long v[2][2];

	v[0][0] = x1;
	v[0][1] = y1;
	v[1][0] = x2;
	v[1][1] = y2;
	bgnline();
	v2i(v[0]);
	v2i(v[1]);
	endline();
    }
    else
    {
	/*Solid line*/
	real ax, ay, nx, ny, rr, mx, my;
	float v[10][2];

	/*Calculate the axial unit vector*/
	ax = x2 - x1;
	ay = y2 - y1;
	rr = 1.0 / sqrt(ax * ax + ay * ay);
	ax *= rr;
	ay *= rr;

	/*Now the normal unit vector*/
	nx = -ay;
	ny = ax;

	switch(arrow)
	{
	    case AH_NO_ARROW:
		v[0][0] = x1 - nx * width * 0.5;
		v[0][1] = y1 - ny * width * 0.5; 
		v[1][0] = x2 - nx * width * 0.5;
		v[1][1] = y2 - ny * width * 0.5; 
		v[2][0] = x2 + nx * width * 0.5;
		v[2][1] = y2 + ny * width * 0.5; 
		v[3][0] = x1 + nx * width * 0.5;
		v[3][1] = y1 + ny * width * 0.5; 
	        bgnpolygon();
		v2f(v[0]);
		v2f(v[1]);
		v2f(v[2]);
		v2f(v[3]);
		endpolygon();
		break;
	    case AH_AT_END:

		/*Arrow base*/
		v[0][0] = x1;
		v[0][1] = y1;

		/*Down to fletching*/
		v[1][0] = x1 + ax * width * arrowParams[0][0] -
				 nx * width * arrowParams[0][1];
		v[1][1] = y1 + ay * width * arrowParams[0][0] -
				 ny * width * arrowParams[0][1];

		/*Over to shaft*/
		v[2][0] = x2 + ax * width * arrowParams[1][0] -
				 nx * width * arrowParams[1][1];
		v[2][1] = y2 + ay * width * arrowParams[1][0] -
				 ny * width * arrowParams[1][1];

		/*To first arrowhead tip*/
		v[3][0] = x2 + ax * width * arrowParams[2][0] -
				 nx * width * arrowParams[2][1];
		v[3][1] = y2 + ay * width * arrowParams[2][0] -
				 ny * width * arrowParams[2][1];

		/*To second arrowhead tip*/
		v[4][0] = x2 + ax * width * arrowParams[3][0] -
				 nx * width * arrowParams[3][1];
		v[4][1] = y2 + ay * width * arrowParams[3][0] -
				 ny * width * arrowParams[3][1];

		/*To end of arrow*/
		v[5][0] = x2;
		v[5][1] = y2;

		/*Up to second arrowhead tip*/
		v[6][0] = x2 + ax * width * arrowParams[3][0] +
				 nx * width * arrowParams[3][1];
		v[6][1] = y2 + ay * width * arrowParams[3][0] +
				 ny * width * arrowParams[3][1];

		/*Back to first arrowhead tip*/
		v[7][0] = x2 + ax * width * arrowParams[2][0] +
				 nx * width * arrowParams[2][1];
		v[7][1] = y2 + ay * width * arrowParams[2][0] +
				 ny * width * arrowParams[2][1];

		/*Down to shaft*/
		v[8][0] = x2 + ax * width * arrowParams[1][0] +
				 nx * width * arrowParams[1][1];
		v[8][1] = y2 + ay * width * arrowParams[1][0] +
				 ny * width * arrowParams[1][1];

		/*Back to fletching*/
		v[9][0] = x1 + ax * width * arrowParams[0][0] +
				 nx * width * arrowParams[0][1];
		v[9][1] = y1 + ay * width * arrowParams[0][0] +
				 ny * width * arrowParams[0][1];

	        bgnpolygon();
		v2f(v[0]);
		v2f(v[1]);
		v2f(v[2]);
		v2f(v[3]);
		v2f(v[4]);
		v2f(v[5]);
		v2f(v[6]);
		v2f(v[7]);
		v2f(v[8]);
		v2f(v[9]);
		endpolygon();
		break;
	    case AH_AT_START:

		/*Arrow base*/
		v[0][0] = x2;
		v[0][1] = y2;

		/*Down to fletching*/
		v[1][0] = x2 - ax * width * arrowParams[0][0] +
				 nx * width * arrowParams[0][1];
		v[1][1] = y2 - ay * width * arrowParams[0][0] +
				 ny * width * arrowParams[0][1];

		/*Over to shaft*/
		v[2][0] = x1 - ax * width * arrowParams[1][0] +
				 nx * width * arrowParams[1][1];
		v[2][1] = y1 - ay * width * arrowParams[1][0] +
				 ny * width * arrowParams[1][1];

		/*To first arrowhead tip*/
		v[3][0] = x1 - ax * width * arrowParams[2][0] +
				 nx * width * arrowParams[2][1];
		v[3][1] = y1 - ay * width * arrowParams[2][0] +
				 ny * width * arrowParams[2][1];

		/*To second arrowhead tip*/
		v[4][0] = x1 - ax * width * arrowParams[3][0] +
				 nx * width * arrowParams[3][1];
		v[4][1] = y1 - ay * width * arrowParams[3][0] +
				 ny * width * arrowParams[3][1];

		/*To end of arrow*/
		v[5][0] = x1;
		v[5][1] = y1;

		/*Up to second arrowhead tip*/
		v[6][0] = x1 - ax * width * arrowParams[3][0] -
				 nx * width * arrowParams[3][1];
		v[6][1] = y1 - ay * width * arrowParams[3][0] -
				 ny * width * arrowParams[3][1];

		/*Back to first arrowhead tip*/
		v[7][0] = x1 - ax * width * arrowParams[2][0] -
				 nx * width * arrowParams[2][1];
		v[7][1] = y1 - ay * width * arrowParams[2][0] -
				 ny * width * arrowParams[2][1];

		/*Down to shaft*/
		v[8][0] = x1 - ax * width * arrowParams[1][0] -
				 nx * width * arrowParams[1][1];
		v[8][1] = y1 - ay * width * arrowParams[1][0] -
				 ny * width * arrowParams[1][1];

		/*Back to fletching*/
		v[9][0] = x2 - ax * width * arrowParams[0][0] -
				 nx * width * arrowParams[0][1];
		v[9][1] = y2 - ay * width * arrowParams[0][0] -
				 ny * width * arrowParams[0][1];

	        bgnpolygon();
		v2f(v[0]);
		v2f(v[1]);
		v2f(v[2]);
		v2f(v[3]);
		v2f(v[4]);
		v2f(v[5]);
		v2f(v[6]);
		v2f(v[7]);
		v2f(v[8]);
		v2f(v[9]);
		endpolygon();
		break;

	    case AH_BOTH_ENDS:
		/*Calculate midpoints*/
		mx = (x1 + x2) * 0.5;
		my = (y1 + y2) * 0.5;

		/*Do at end first*/

		/*Arrow base*/
		v[0][0] = mx;
		v[0][1] = my;

		/*Down to fletching*/
		v[1][0] = mx + ax * width * arrowParams[0][0] -
				 nx * width * arrowParams[0][1];
		v[1][1] = my + ay * width * arrowParams[0][0] -
				 ny * width * arrowParams[0][1];

		/*Over to shaft*/
		v[2][0] = x2 + ax * width * arrowParams[1][0] -
				 nx * width * arrowParams[1][1];
		v[2][1] = y2 + ay * width * arrowParams[1][0] -
				 ny * width * arrowParams[1][1];

		/*To first arrowhead tip*/
		v[3][0] = x2 + ax * width * arrowParams[2][0] -
				 nx * width * arrowParams[2][1];
		v[3][1] = y2 + ay * width * arrowParams[2][0] -
				 ny * width * arrowParams[2][1];

		/*To second arrowhead tip*/
		v[4][0] = x2 + ax * width * arrowParams[3][0] -
				 nx * width * arrowParams[3][1];
		v[4][1] = y2 + ay * width * arrowParams[3][0] -
				 ny * width * arrowParams[3][1];

		/*To end of arrow*/
		v[5][0] = x2;
		v[5][1] = y2;

		/*Up to second arrowhead tip*/
		v[6][0] = x2 + ax * width * arrowParams[3][0] +
				 nx * width * arrowParams[3][1];
		v[6][1] = y2 + ay * width * arrowParams[3][0] +
				 ny * width * arrowParams[3][1];

		/*Back to first arrowhead tip*/
		v[7][0] = x2 + ax * width * arrowParams[2][0] +
				 nx * width * arrowParams[2][1];
		v[7][1] = y2 + ay * width * arrowParams[2][0] +
				 ny * width * arrowParams[2][1];

		/*Down to shaft*/
		v[8][0] = x2 + ax * width * arrowParams[1][0] +
				 nx * width * arrowParams[1][1];
		v[8][1] = y2 + ay * width * arrowParams[1][0] +
				 ny * width * arrowParams[1][1];

		/*Back to fletching*/
		v[9][0] = mx + ax * width * arrowParams[0][0] +
				 nx * width * arrowParams[0][1];
		v[9][1] = my + ay * width * arrowParams[0][0] +
				 ny * width * arrowParams[0][1];

	        bgnpolygon();
		v2f(v[0]);
		v2f(v[1]);
		v2f(v[2]);
		v2f(v[3]);
		v2f(v[4]);
		v2f(v[5]);
		v2f(v[6]);
		v2f(v[7]);
		v2f(v[8]);
		v2f(v[9]);
		endpolygon();

		/*Now do at start*/
	        bgnpolygon();

		/*Arrow base*/
		v[0][0] = mx;
		v[0][1] = my;

		/*Down to fletching*/
		v[1][0] = mx - ax * width * arrowParams[0][0] +
				 nx * width * arrowParams[0][1];
		v[1][1] = my - ay * width * arrowParams[0][0] +
				 ny * width * arrowParams[0][1];

		/*Over to shaft*/
		v[2][0] = x1 - ax * width * arrowParams[1][0] +
				 nx * width * arrowParams[1][1];
		v[2][1] = y1 - ay * width * arrowParams[1][0] +
				 ny * width * arrowParams[1][1];

		/*To first arrowhead tip*/
		v[3][0] = x1 - ax * width * arrowParams[2][0] +
				 nx * width * arrowParams[2][1];
		v[3][1] = y1 - ay * width * arrowParams[2][0] +
				 ny * width * arrowParams[2][1];

		/*To second arrowhead tip*/
		v[4][0] = x1 - ax * width * arrowParams[3][0] +
				 nx * width * arrowParams[3][1];
		v[4][1] = y1 - ay * width * arrowParams[3][0] +
				 ny * width * arrowParams[3][1];

		/*To end of arrow*/
		v[5][0] = x1;
		v[5][1] = y1;

		/*Up to second arrowhead tip*/
		v[6][0] = x1 - ax * width * arrowParams[3][0] -
				 nx * width * arrowParams[3][1];
		v[6][1] = y1 - ay * width * arrowParams[3][0] -
				 ny * width * arrowParams[3][1];
		
		/*Back to first arrowhead tip*/
		v[7][0] = x1 - ax * width * arrowParams[2][0] -
				 nx * width * arrowParams[2][1];
		v[7][1] = y1 - ay * width * arrowParams[2][0] -
				 ny * width * arrowParams[2][1];
		
		/*Down to shaft*/
		v[8][0] = x1 - ax * width * arrowParams[1][0] -
				 nx * width * arrowParams[1][1];
		v[8][1] = y1 - ay * width * arrowParams[1][0] -
				 ny * width * arrowParams[1][1];

		/*Back to fletching*/
		v[9][0] = mx - ax * width * arrowParams[0][0] -
				 nx * width * arrowParams[0][1];
		v[9][1] = my - ay * width * arrowParams[0][0] -
				 ny * width * arrowParams[0][1];

	        bgnpolygon();
		v2f(v[0]);
		v2f(v[1]);
		v2f(v[2]);
		v2f(v[3]);
		v2f(v[4]);
		v2f(v[5]);
		v2f(v[6]);
		v2f(v[7]);
		v2f(v[8]);
		v2f(v[9]);
		endpolygon();
		break;
	}	
    }
#endif
}

void DrawVCursor(x, yt, yb)
int x, yt, yb;
/*Draws a vertical cursor*/
{
#ifdef GRAPHICS
    DrawUILine(x, yt, x, yb, UIRED);
    DrawUILine(x + 1, yt, x + 1, yb, UIBLACK);
#endif
}

#ifdef GRAPHICS
#ifdef FONTS4D
extern fmfonthandle currentFontHandle;
#endif
#endif

#ifdef PROTO
void DrawSpaceString(real x, real y, real z, char *s)
#else
void DrawSpaceString(x, y, z, s)
real x, y, z;
char *s;
#endif
/*Draws a string beginning at x, y, z in a space*/
/* DIK need PostScript version? */
{
#ifdef GRAPHICS

    cmov((Coord) x, (Coord) y, (Coord) z);
#ifdef FONTS4D
	if (currentFontHandle)
	{
		fmprstr(s);
	}
	else
	{
		charstr(s);
	}
#else
	charstr(s);
#endif
#endif
}

#ifdef PROTO
void DrawWFSphere(real x, real y, real z, real radius)
#else
void DrawWFSphere(x, y, z, radius)
real x, y, z, radius;
#endif
/*Draws a wire frame sphere*/
{
#ifdef GRAPHICS
    pushmatrix();
    translate(x, y, z);
    circ(0.0, 0.0, radius);
    translate(0.0, 0.0, radius * SQ22);
    circ(0.0, 0.0, radius * SQ22);
    translate(0.0, 0.0, -radius * 2.0 * SQ22);
    circ(0.0, 0.0, radius * SQ22);
    translate(0.0, 0.0, radius * SQ22);
    rotate(900, 'y');
    circ(0.0, 0.0, radius);
    rotate(450, 'x');
    circ(0.0, 0.0, radius);
    rotate(450, 'x');
    circ(0.0, 0.0, radius);
    rotate(450, 'x');
    circ(0.0, 0.0, radius);
    popmatrix();
#endif
}

#ifdef PROTO
void FillRealQuad(real x1, real y1, real x2, real y2, real x3, real y3, real x4, real y4)
#else
void FillRealQuad(x1, y1, x2, y2, x3, y3, x4, y4)
real x1, y1, x2, y2, x3, y3, x4, y4;
#endif
/*Fills a quadrilateral given real coordinates*/
{
#ifdef GRAPHICS
    if (drawingMode == DRAW_SCREEN)
    {
	float v[4][2];
	v[0][0] = x1;
	v[0][1] = y1;
	v[1][0] = x2;
	v[1][1] = y2;
	v[2][0] = x3;
	v[2][1] = y3;
	v[3][0] = x4;
	v[3][1] = y4;
	bgnpolygon();
	v2f(v[0]);
	v2f(v[1]);
	v2f(v[2]);
	v2f(v[3]);
	endpolygon();
    }
    else if (drawingMode == DRAW_POSTSCRIPT && psFile)
    {
	fprintf(psFile, "%f setgray\n", PSColor());
        fprintf(psFile, "%g %g moveto %g %g lineto %g %g lineto %g %g lineto closepath fill\n",
            x1, y1, x2, y2, x3, y3, x4, y4); 
    }
#endif
}

#ifdef PROTO
void FillIntQuad(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4)
#else
void FillIntQuad(x1, y1, x2, y2, x3, y3, x4, y4)
int x1, y1, x2, y2, x3, y3, x4, y4;
#endif
/*Fills a quadrilateral given real coordinates*/
{
#ifdef GRAPHICS
    if (drawingMode == DRAW_SCREEN)
    {
	long v[4][2];
	v[0][0] = x1;
	v[0][1] = y1;
	v[1][0] = x2;
	v[1][1] = y2;
	v[2][0] = x3;
	v[2][1] = y3;
	v[3][0] = x4;
	v[3][1] = y4;
	bgnpolygon();
	v2i(v[0]);
	v2i(v[1]);
	v2i(v[2]);
	v2i(v[3]);
	endpolygon();
    }
    else if (drawingMode == DRAW_POSTSCRIPT && psFile)
    {
	fprintf(psFile, "%f setgray\n", PSColor());
        fprintf(psFile, "%d %d moveto %d %d lineto %d %d lineto %d %d lineto closepath fill\n",
            x1, y1, x2, y2, x3, y3, x4, y4); 
    }
#endif
}

#ifdef PROTO
void FillRealQuint(real x1, real y1, real x2, real y2, real x3, real y3, real x4, real y4, real x5, real y5)
#else
void FillRealQuint(x1, y1, x2, y2, x3, y3, x4, y4, x5, y5)
real x1, y1, x2, y2, x3, y3, x4, y4, x5, y5;
#endif
/*Fills a quintalateral given real coordinates*/
{
#ifdef GRAPHICS
    if (drawingMode == DRAW_SCREEN)
    {
	float v[5][2];
	v[0][0] = x1;
	v[0][1] = y1;
	v[1][0] = x2;
	v[1][1] = y2;
	v[2][0] = x3;
	v[2][1] = y3;
	v[3][0] = x4;
	v[3][1] = y4;
	v[4][0] = x5;
	v[4][1] = y5;
	bgnpolygon();
	v2f(v[0]);
	v2f(v[1]);
	v2f(v[2]);
	v2f(v[3]);
	v2f(v[4]);
	endpolygon();
    }
    else if (drawingMode == DRAW_POSTSCRIPT && psFile)
    {
	fprintf(psFile, "%f setgray\n", PSColor());
        fprintf(psFile, "%g %g moveto %g %g lineto %g %g lineto %g %g lineto %g %g lineto closepath fill\n",
            x1, y1, x2, y2, x3, y3, x4, y4, x5, y5); 
    }
#endif
}

#ifdef PROTO
void FillRealHex(real x1, real y1, real x2, real y2, real x3, real y3, real x4, real y4, real x5, real y5, real x6, real y6)
#else
void FillRealHex(x1, y1, x2, y2, x3, y3, x4, y4, x5, y5, x6, y6)
real x1, y1, x2, y2, x3, y3, x4, y4, x5, y5, x6, y6;
#endif
/*Fills a hexalateral given real coordinates*/
{
#ifdef GRAPHICS
    if (drawingMode == DRAW_SCREEN)
    {
	float v[6][2];
	v[0][0] = x1;
	v[0][1] = y1;
	v[1][0] = x2;
	v[1][1] = y2;
	v[2][0] = x3;
	v[2][1] = y3;
	v[3][0] = x4;
	v[3][1] = y4;
	v[4][0] = x5;
	v[4][1] = y5;
	v[5][0] = x6;
	v[5][1] = y6;
	bgnpolygon();
	v2f(v[0]);
	v2f(v[1]);
	v2f(v[2]);
	v2f(v[3]);
	v2f(v[4]);
	v2f(v[5]);
	endpolygon();
    }
    else if (drawingMode == DRAW_POSTSCRIPT && psFile)
    {
	fprintf(psFile, "%f setgray\n", PSColor());
        fprintf(psFile, "%g %g moveto %g %g lineto %g %g lineto %g %g lineto %g %g lineto %g %g lineto closepath fill\n",
            x1, y1, x2, y2, x3, y3, x4, y4, x5, y5, x6, y6); 
    }
#endif
}

#ifdef PROTO
void FillRealRect(real left, real right, real bottom, real top)
#else
void FillRealRect(left, right, bottom, top)
real left, right, bottom, top;
#endif
/*Fills a rectangle, taking real coordinates*/
{
#ifdef GRAPHICS
    FillRealQuad(left, top, left, bottom, right, bottom, right, top);
#endif
}


#ifdef PROTO
void FrameRealWideRect(real left, real right, real bottom, real top, real width)
#else
void FrameRealWideRect(left, right, bottom, top, width)
real left, right, bottom, top, width;
#endif
/*Frames a wide rectangle taking real variables*/
{
#ifdef GRAPHICS
    FillRealRect(left, right, top - width, top);
    FillRealRect(left, right, bottom, bottom + width);
    FillRealRect(left, left + width, bottom, top);
    FillRealRect(right - width, right, bottom, top);
#endif
}

#ifdef PROTO
void FrameWideRect(int left, int right, int bottom, int top, int width)
#else
void FrameWideRect(left, right, bottom, top, width)
int left, right, bottom, top, width;
#endif
/*Frames a wide rectangle*/
{
#ifdef GRAPHICS
    FillRect(left, right, top - width + 1, top);
    FillRect(left, right, bottom, bottom + width - 1);
    FillRect(left, left + width - 1, bottom, top);
    FillRect(right - width + 1, right, bottom, top);
#endif
}

#ifdef PROTO
void FrameUIWideRect(int left, int right, int bottom, int top, int width, int color)
#else
void FrameUIWideRect(left, right, bottom, top, width, color)
int left, right, bottom, top, width, color;
#endif
/*Frames a wide rectangle in UI color*/
{
#ifdef GRAPHICS
    SetUIColor(color);
    FrameWideRect(left, right, bottom, top, width);
#endif
}

#ifdef PROTO
void DrawHandle(int x, int y)
#else
void DrawHandle(x, y)
int x, y;
#endif
/* Draws a handle at x,y */
{
#ifdef GRAPHICS
	FillUIRect(x - HANDLESIZE/2, x + HANDLESIZE / 2,
		y - HANDLESIZE/2, y + HANDLESIZE/2, OUTSIDEFRAMECOLOR);
	FillUIRect(x - HANDLESIZE/2 + OUTSIDEFRAMEWEIGHT,
		x + HANDLESIZE/2 - OUTSIDEFRAMEWEIGHT,
		y - HANDLESIZE/2 + OUTSIDEFRAMEWEIGHT,
		y + HANDLESIZE/2 - OUTSIDEFRAMEWEIGHT, INSIDEFRAMECOLOR);
#endif
}

#ifdef PROTO
Bool PointInHandle(int pointX, int pointY, int handleX, int handleY)
#else
Bool PointInHandle(pointX, pointY, handleX, handleY)
int pointX; int pointY; int handleX; int handleY;
#endif
/*Returns true if a point is inside a handle*/
{
#ifdef INTERACTIVE
    return (pointX >= handleX - HANDLESIZE / 2 &&
	    pointX <= handleX + HANDLESIZE / 2 &&
	    pointY >= handleY - HANDLESIZE / 2 &&
	    pointY <= handleY + HANDLESIZE / 2) ? true : false;
#endif
}

#ifdef PROTO
void DrawRaisedEdge(int left, int right, int bottom, int top)
#else
void DrawRaisedEdge(left, right, bottom, top)
int left; int right; int bottom; int top;
#endif
/* draws a rectangular raised edge (JEL) */
{
#ifdef GRAPHICS
    /* bottom */
    SetUIColor(UIBOTTOMEDGE);
    FillIntQuad( left, bottom,
		 right, bottom,
		 right - EDGE, bottom + EDGE,
		 left + EDGE, bottom + EDGE);

    /* left */
    SetUIColor(UILEFTEDGE);
    FillIntQuad( left,  bottom,
		 left + EDGE, bottom + EDGE,
		 left + EDGE, top - EDGE,
		 left, top);

    /* right */
    SetUIColor(UIRIGHTEDGE);
    FillIntQuad( right - EDGE, bottom + EDGE,
		 right, bottom,
		 right, top,
		 right - EDGE, top - EDGE);

    /* top */
    SetUIColor(UITOPEDGE);
    FillIntQuad( left + EDGE, top - EDGE,
		 right - EDGE, top - EDGE,
		 right, top,
		 left, top);
    return;
#endif
}

#ifdef PROTO
void DrawSunkenEdge(int left, int right, int bottom, int top)
#else
void DrawSunkenEdge(left, right, bottom, top)
int left; int right; int bottom; int top;
#endif
/* draws a rectanglar sunken edge (JEL) 
   Fixed to be in CCW order (EMP) */
{
#ifdef GRAPHICS
    /* bottom */
    SetUIColor(UITOPEDGE);
    FillIntQuad( left, bottom,
		 right, bottom,
		 right - EDGE, bottom + EDGE,
		 left + EDGE, bottom + EDGE);

    /* left */
    SetUIColor(UIRIGHTEDGE);
    FillIntQuad( left,  bottom,
		 left + EDGE, bottom + EDGE,
		 left + EDGE, top - EDGE,
		 left, top);

    /* right */
    SetUIColor(UILEFTEDGE);
    FillIntQuad( right - EDGE, bottom + EDGE,
		 right, bottom,
		 right, top,
		 right - EDGE, top - EDGE);

    /* top */
    SetUIColor(UIBOTTOMEDGE);
    FillIntQuad( left + EDGE, top - EDGE,
		 right - EDGE, top - EDGE,
		 right, top,
		 left, top);
    return;
#endif
}

#ifdef PROTO
void DrawInsetRect(int left, int right, int bottom, int top)
#else
void DrawInsetRect(left, right, bottom, top)
int left; int right; int bottom; int top;
#endif
/* draws a rectangle filled with uiColor inset by EDGE from the given bounds */
{
#ifdef GRAPHICS
	FillRect(left + EDGE, right - EDGE, bottom + EDGE,
		top - EDGE);
#endif
}

#ifdef PROTO
void DrawInsetWashedRect(int left, int right, int bottom, int top, int washColor)
#else
void DrawInsetWashedRect(left, right, bottom, top, int washColor)
int left; int right; int bottom; int top; int washColor;
#endif
/* draws a rectangle filled with uiColor inset by EDGE from the given bounds */
{
#ifdef GRAPHICS
	FillUIRect(left + EDGE, right - EDGE, bottom + EDGE,
		top - EDGE, UIGRAY75);
	FillUIGauzeRect(left + EDGE, right - EDGE, bottom + EDGE,
		top - EDGE, washColor);
#endif
}

#ifdef PROTO
void DrawRaisedRect(int left, int right, int bottom, int top, int uiColor)
#else
void DrawRaisedRect(left, right, bottom, top, uiColor)
int left; int right; int bottom; int top; int uiColor;
#endif
/* draws a raised edge with filled rectangle inside */
{
#ifdef GRAPHICS
	SetUIColor(uiColor);
	DrawInsetRect(left, right, bottom, top);
	DrawRaisedEdge(left, right, bottom, top);
#endif
}

#ifdef PROTO
void DrawSunkenRect(int left, int right, int bottom, int top, int uiColor)
#else
void DrawSunkenRect(left, right, bottom, top, uiColor)
int left; int right; int bottom; int top; int uiColor;
#endif
/* draws a sunken edge with filled rectangle inside */
{
#ifdef GRAPHICS
	SetUIColor(uiColor);
	DrawInsetRect(left, right, bottom, top);
	DrawSunkenEdge(left, right, bottom, top);
#endif
}

void SetLineWidth(width)
int width;
/*Sets the line width to width*/
{
#ifdef GRAPHICS
    if (drawingMode == DRAW_SCREEN)
    {
        linewidth(width);
    }
    else if (drawingMode == DRAW_POSTSCRIPT && psFile)
    {
        fprintf(psFile, "%d setlinewidth\n", width);
    }
#endif
}

void SetPointWidth(width)
int width;
/*Sets the line width to width*/
{
#ifdef GRAPHICS
    if (drawingMode == DRAW_SCREEN)
    {
#if MACHINE != RS6000
        pntsize((short) width);
#endif
    }
#endif
}

void	DrawMarkerSplat(left, right, bottom, top)
{

#ifdef GRAPHICS

    SetUIColor(UITEXT);
    if (drawingMode == DRAW_SCREEN)
    {
	float v[4][2];

	/*Draw part of button '*', the left-bottom to top-right part */
	v[0][0] = left + 2.5;
	v[0][1] = bottom + 3.5;
	v[1][0] = left + 3.5;
	v[1][1] = bottom + 2.5;
	v[2][0] = right - 2.5;
	v[2][1] = top - 3.5;
	v[3][0] = right - 3.5;
	v[3][1] = top - 2.5;
	bgnpolygon();
	v2f(v[0]);
	v2f(v[1]);
	v2f(v[2]);
	v2f(v[3]);
	endpolygon();

	/*Draw rest of button '*', the left-top to right-bottom part*/
	v[0][0] = left + 2.5;
	v[0][1] = top - 3.5;
	v[1][0] = left + 3.5;
	v[1][1] = top - 2.5;
	v[2][0] = right - 2.5;
	v[2][1] = bottom + 3.5;
	v[3][0] = right - 3.5;
	v[3][1] = bottom + 2.5;
	bgnpolygon();
	v2f(v[0]);
	v2f(v[1]);
	v2f(v[2]);
	v2f(v[3]);
	endpolygon();

	/*Draw rest of button '*', the left-to-right part*/
	v[0][0] = left + 1.5;
	v[0][1] = (top+bottom)/2.0 - 0.5;
	v[1][0] = left + 1.5;
	v[1][1] = (top+bottom)/2.0 + 0.5;
	v[2][0] = right - 1.5;
	v[2][1] = (top+bottom)/2.0 + 0.5;
	v[3][0] = right - 1.5;
	v[3][1] = (top+bottom)/2.0 - 0.5;
	bgnpolygon();
	v2f(v[0]);
	v2f(v[1]);
	v2f(v[2]);
	v2f(v[3]);
	endpolygon();

	/*Draw rest of button '*', the top-to-bottom part*/
	v[0][0] = (left+right)/2.0 - 0.5;
	v[0][1] = top - 1.5;
	v[1][0] = (left+right)/2.0 + 0.5;
	v[1][1] = top - 1.5;
	v[2][0] = (left+right)/2.0 + 0.5;
	v[2][1] = bottom + 1.5;
	v[3][0] = (left+right)/2.0 - 0.5;
	v[3][1] = bottom + 1.5;
	bgnpolygon();
	v2f(v[0]);
	v2f(v[1]);
	v2f(v[2]);
	v2f(v[3]);
	endpolygon();
    }
    else if (drawingMode == DRAW_POSTSCRIPT && psFile)
    {
	fprintf(psFile, "%f setgray\n", PSColor());
        fprintf(psFile,
		"%.1f %.1f moveto %.1f %.1f lineto %.1f %.1f lineto %.1f %.1f lineto closepath fill\n",
		left + 2.5, bottom + 3.5, left + 3.5, bottom + 2.5,
		right - 2.5, top - 3.5, right - 3.5, top - 2.5); 
        fprintf(psFile,
		"%.1f %.1f moveto %.1f %.1f lineto %.1f %.1f lineto %.1f %.1f lineto closepath fill\n",
		left + 2.5, top - 3.5, left + 3.5, top - 2.5,
		right - 2.5, bottom + 3.5, right - 3.5, bottom + 2.5); 
        fprintf(psFile,
		"%.1f %.1f moveto %.1f %.1f lineto %.1f %.1f lineto %.1f %.1f lineto closepath fill\n",
		left + 1.5, (top+bottom)/2.0 - 0.5, left + 1.5, (top+bottom)/2.0 + 0.5,
		right - 1.5, (top+bottom)/2.0 + 0.5, right - 1.5, (top+bottom)/2.0 - 0.5); 
        fprintf(psFile,
		"%.1f %.1f moveto %.1f %.1f lineto %.1f %.1f lineto %.1f %.1f lineto closepath fill\n",
		(left+right)/2.0 - 0.5, top - 1.5, (left+right)/2.0 + 0.5, top - 1.5,
		(left+right)/2.0 + 0.5, bottom + 1.5, (left+right)/2.0 - 0.5, bottom + 1.5); 
    }
#endif /* GRAPHICS */
}

void    DrawMarkerBlot(left, right, bottom, top)
int     left, right, bottom, top;
{
#ifdef GRAPHICS
    SetUIColor(UITEXT);
    FillRect(left+2.5, right-2.5, bottom+2.5, top-2.5);
#endif /*GRAPHICS*/
}

void	DrawMarkerCheck(left, right, bottom, top)
int	left, right, bottom, top;
{
#ifdef GRAPHICS
    float v[4][2];

    SetUIColor(UITEXT);
    if (drawingMode == DRAW_SCREEN)
    {
	/*Draw part of checkmark*/
	v[0][0] = left + 1.5;
	v[0][1] = (top + bottom) / 2 - 0.5;
	v[1][0] = left + 2.5;
	v[1][1] = (top + bottom) / 2 + 1.5;
	v[2][0] = left + (right - left) / 3 + 1.5;
	v[2][1] = bottom + 1.5;
	v[3][0] = left + (right - left) / 3 - 0.5;
	v[3][1] = bottom + 1.5;
	bgnpolygon();
	v2f(v[0]);
	v2f(v[1]);
	v2f(v[2]);
	v2f(v[3]);
	endpolygon();
    
	/*Draw rest of checkmark*/
	v[0][0] = left + (right - left) / 3 + 1.5;
	v[0][1] = bottom + 1.5;
	v[1][0] = left + (right - left) / 3 - 0.5;
	v[1][1] = bottom + 1.5;
	v[2][0] = right - 1.5;
	v[2][1] = top - 1.5;
	bgnpolygon();
	v2f(v[0]);
	v2f(v[1]);
	v2f(v[2]);
	endpolygon();
    }
    else if (drawingMode == DRAW_POSTSCRIPT && psFile)
    {
	fprintf(psFile, "%f setgray\n", PSColor());
	fprintf(psFile,
		"%.1f %.1f moveto %.1f %.1f lineto %.1f %.1f lineto %.1f %.1f lineto closepath fill\n",
		left + 1.5, (top + bottom) / 2 - 0.5, left + 2.5, (top + bottom) / 2 + 1.5, 
		left + (right - left) / 3 + 1.5, bottom + 1.5, left + (right - left) / 3 - 0.5, 
		bottom + 1.5);
	fprintf(psFile, "%.1f %.1f moveto %.1f %.1f lineto %.1f %.1f lineto closepath fill\n", 
		left + (right - left) / 3 + 1.5, bottom + 1.5, left + (right - left) / 3 - 0.5, 
		bottom + 1.5, right - 1.5, top - 1.5);
    }
#endif /*GRAPHICS */
}

void	DrawMarkerX(left, right, bottom, top)
int	left, right, bottom, top;
{
#ifdef GRAPHICS
    float v[4][2];

    SetUIColor(UITEXT);
    /*Draw part of button 'X'*/
    v[0][0] = left + 1.5;
    v[0][1] = bottom + 2.5;
    v[1][0] = left + 2.5;
    v[1][1] = bottom + 1.5;
    v[2][0] = right - 1.5;
    v[2][1] = top - 2.5;
    v[3][0] = right - 2.5;
    v[3][1] = top - 1.5;
	bgnpolygon();
	v2f(v[0]);
	v2f(v[1]);
	v2f(v[2]);
	v2f(v[3]);
	endpolygon();

    /*Draw rest of button 'X'*/
    v[0][0] = left + 1.5;
    v[0][1] = top - 2.5;
    v[1][0] = left + 2.5;
    v[1][1] = top - 1.5;
    v[2][0] = right - 1.5;
    v[2][1] = bottom + 2.5;
    v[3][0] = right - 2.5;
    v[3][1] = bottom + 1.5;
	bgnpolygon();
	v2f(v[0]);
	v2f(v[1]);
	v2f(v[2]);
	v2f(v[3]);
	endpolygon();
#endif /*GRAPHICS */
}

#ifdef PROTO
void DrawCtlLeft(int left, int right, int bottom, int top, int uiColor)
#else
void DrawCtlLeft(left, right, bottom, top, uiColor)
int left, right, bottom, top;
Bool highlight;
#endif
{
#ifdef GRAPHICS
    float a, b, c, d;

    a = left - 0.5 + 1.4142 * EDGE;
    b = left - 0.5 + 0.4142 * EDGE + (top - bottom) / 2;
    c = (top + bottom) / 2;
    d = (top - bottom) / 2;

    /* bottom */
    SetUIColor(UIBOTTOMEDGE);
    FillRealHex(right, bottom, left + d, bottom, left, c, a, c, b, bottom + EDGE, right - EDGE, bottom + EDGE);

    /* top */
    SetUIColor(UITOPEDGE);
    FillRealHex(a, c, left, c, left + d, top, right, top, right - EDGE, top - EDGE, b, top - EDGE);

    /* right */
    SetUIColor(UIRIGHTEDGE);
    FillRealQuad(right, top, right - EDGE, top - EDGE, right - EDGE, bottom + EDGE, right, bottom);

    /* surface */
    SetUIColor(uiColor);
    FillRealQuint(right - EDGE, bottom + EDGE, b, bottom + EDGE, a, c, b, top - EDGE, right - EDGE, top - EDGE);
#endif
}

#ifdef PROTO
void DrawCtlRight(int left, int right, int bottom, int top, int uiColor)
#else
void DrawCtlRight(left, right, bottom, top, uiColor)
int left, right, bottom, top;
Bool highlight;
#endif
{
#ifdef GRAPHICS
    float a, b, c, d;

    a = right + 0.5 - 1.4142 * EDGE;
    b = right + 0.5 - 0.4142 * EDGE - (top - bottom) / 2;
    c = (top + bottom) / 2;
    d = (top - bottom) / 2;

    /* bottom */
    SetUIColor(UIBOTTOMEDGE);
    FillRealHex(right, c, right - d, bottom, left, bottom, left + EDGE, bottom + EDGE, b, bottom + EDGE, a, c);

    /* top */
    SetUIColor(UITOPEDGE);
    FillRealHex(right, c, a, c, b, top - EDGE, left + EDGE, top - EDGE, left, top, right - d, top);

    /* left */
    SetUIColor(UILEFTEDGE);
    FillRealQuad(left, bottom, left, top, left + EDGE, top - EDGE, left + EDGE, bottom + EDGE);

    /* surface */
    SetUIColor(uiColor);
    FillRealQuint(a, c, b, bottom + EDGE, left + EDGE, bottom + EDGE, left + EDGE, top - EDGE, b, top - EDGE);
#endif
}

#ifdef PROTO
void DrawCtlUp(int left, int right, int bottom, int top, int uiColor)
#else
void DrawCtlUp(left, right, bottom, top, uiColor)
int left, right, bottom, top;
Bool highlight;
#endif
{
#ifdef GRAPHICS
    float a, b, c, d;

    a = top - 1.4142 * EDGE + 0.5;
    b = top - 0.4142 * EDGE - (right - left) /2;
    c = (right + left) / 2;
    d = (right - left) / 2;

    /* left */
    SetUIColor(UILEFTEDGE);
    FillRealHex(c, top, c, a, left + EDGE, b, left + EDGE, bottom + EDGE, left, bottom, left, top - d);

    /* right */
    SetUIColor(UIRIGHTEDGE);
    FillRealHex(c, top, right, top - d, right, bottom, right - EDGE, bottom + EDGE, right - EDGE, b, c, a);

    /* bottom */
    SetUIColor(UIBOTTOMEDGE);
    FillRealQuad(right, bottom, left, bottom, left + EDGE, bottom + EDGE, right - EDGE, bottom + EDGE);

    /* surface */
    SetUIColor(uiColor);
    FillRealQuint(c, a, right - EDGE, b, right - EDGE, bottom + EDGE, left + EDGE, bottom + EDGE, left + EDGE, b);
#endif
}

#ifdef PROTO
void DrawCtlDown(int left, int right, int bottom, int top, int uiColor)
#else
void DrawCtlDown(left, right, bottom, top, uiColor)
int left, right, bottom, top;
Bool highlight;
#endif
{
#ifdef GRAPHICS
    float a, b, c, d;

    a = bottom + 1.4142 * EDGE - 0.5;
    b = bottom + 0.4142 * EDGE - (right - left) /2;
    c = (right + left) / 2;
    d = (right - left) / 2;

    /* left */
    SetUIColor(UILEFTEDGE);
    FillRealHex(c, bottom, left, bottom + d, left, top, left + EDGE, top - EDGE, left + EDGE, b, c, a);

    /* right */
    SetUIColor(UIRIGHTEDGE);
    FillRealHex(c, bottom, c, a, right - EDGE, b, right - EDGE, top - EDGE, right, top, right, bottom + d);

    /* top */
    SetUIColor(UITOPEDGE);
    FillRealQuad(right, top, right - EDGE, top - EDGE, left + EDGE, top - EDGE, left, top);

    /* surface */
    SetUIColor(uiColor);
    FillRealQuint(c, a, left + EDGE, b, left + EDGE, top - EDGE, right - EDGE, top - EDGE, right - EDGE, b);
#endif
}

#ifdef PROTO
void SavePSImage(FILE *psFile, Pixel *imageBuffer, int left, int right, int bottom, int top)
#else
void SavePSImage(psFile, imageBuffer, left, right, bottom, top)
FILE *psFile;
Pixel *imageBuffer;
int left;
int right;
int bottom;
int top;
#endif
/*Saves an image in imageBuffer within left, right, bottom, top into psFile*/
{
    real y, dummy;
    int iVal;
    long k;
    int pixWrap;
    long nPixels;
    long i, j, ip, jp;
    long width, height;
    int subSample;

    subSample = imageSubSample + 1;


    width = right - left;
    height = top - bottom;

#define PIXPERLINE	10

#ifdef COLORPOST
    /*Color image.  Do stuff before pixels*/
    fprintf(psFile, "%% Color Space image within %d %d %d %d\n",
		left, right, bottom, top);
    fprintf(psFile, "%d %d moveto\n", left, bottom);
    fprintf(psFile, "/imgstr %d string def\n", 3 * width);
    fprintf(psFile, "%d %d %d matrix \n", right - left, top - bottom, 8);

    /*Do pixels*/
    nPixels = width * height;
    pixWrap = 0;
    fprintf(psFile, "{currentfile imgstr readhexstring pop} false 3 colorimage\n");
    for (k = 0; k < nPixels; ++k)
    {
	fprintf(psFile, "%02X%02X%02X%s",
		LinToGamma[imageBuffer[k] . red],
		LinToGamma[imageBuffer[k] . green],
		LinToGamma[imageBuffer[k] . blue],
		(++pixWrap) % PIXPERLINE ? " " : "\n");
    }
    fprintf(psFile, "\n\n");
#else
    /*B/W image.  Do stuff before pixels*/
    fprintf(psFile, "%% B/W Space image within %d %d %d %d\n",
		left, right, bottom, top);
    fprintf(psFile, "/imgstr %d string def\n", width / subSample);
    fprintf(psFile, "%d %d %d\n", width / subSample, height / subSample, 8);
    fprintf(psFile, "%d %d matrix translate\n",
		-left, -bottom);
    fprintf(psFile, "%lg %lg matrix scale\n",
		1.0 / (double) subSample, 1.0 / (double) subSample);
    fprintf(psFile, " matrix concatmatrix\n");

    /*Do pixels*/
    nPixels = (right - left) * (top - bottom);
    pixWrap = 0;
    fprintf(psFile, "{currentfile imgstr readhexstring pop} image\n");


    for (j = 0; j < height; j += subSample)
    {
	for (i = 0; i < width; i += subSample)
	{
	    real avgPixel;

	    avgPixel = 0.0;

	    /*Calculate an average pixel*/
	    for (jp = j; jp < j + subSample; ++jp)
	    {
		for (ip = i; ip < i + subSample; ++ip)
		{
		    k = ip + jp * width;

		    RGB2YIQ(&y, &dummy, &dummy,
			imageBuffer[k] . red / 255.0,
			imageBuffer[k] . green / 255.0,
			imageBuffer[k] . blue / 255.0);

		    avgPixel += y;
		}
	    }
	    avgPixel /= (real) subSample;
	    avgPixel /= (real) subSample;

	    iVal = avgPixel * 255.0;
	    if (iVal < 0) iVal = 0;
	    if (iVal > 255) iVal = 255;
	    fprintf(psFile, "%02X%s", LinToGamma[iVal],
		(++pixWrap) % PIXPERLINE ? " " : "\n");
	}
    }

    fprintf(psFile, "\n\n");

#endif

#undef PIXPERLINE

}

/*
 * Icons in eps files 10/28/92
 * In order to make the eps file of a window self contained, a bit-mapped
 * font of just the icons used in that window is defined in the file. In PS
 * drawing mode, RegisterIconUsed keeps a list of the icon numbers used.
 * It returns the index of the icon in the list. EndDrawing uses the list
 * to create the font definition. If there are any icons in the window, the
 * file must be rewritten with the font definition in the header. The font
 * definition is generated by GenIconDef() in ScianIcons.c.
 */

#ifdef PROTO
void DrawPSFrame(char *name, int left, int right, int bottom, int top)
#else
void DrawPSFrame(name, left, right, bottom, top)
char *name;
int left;
int right;
int bottom;
int top;
#endif
/*Draws a PostScript frame around left, right, bottom, top*/
{
    left -= WINFRAMEWID;
    right -= WINFRAMEWID;
    bottom -= WINFRAMEWID;
    top -= WINFRAMEWID;
	{
	    /* draw a generic window frame with title only */
	    fprintf(psFile,
"newpath 0 0 moveto 0 %d lineto %d %d lineto %d 0 lineto closepath stroke\n", 
		top, right, top, right);
	    fprintf(psFile, 
"newpath %d %d moveto %d %d lineto %d %d lineto %d %d lineto closepath stroke\n", 
		WINFRAMEWID - 1, WINFRAMEWID - 1,
		WINFRAMEWID - 1, top - WINFRAMEWID + 1,
		right - WINFRAMEWID + 1, top - WINFRAMEWID + 1,
		right - WINFRAMEWID + 1, WINFRAMEWID - 1);
	    fprintf(psFile, "newpath %d %d moveto %d %d lineto stroke\n", 
		WINFRAMEWID - 1, top - WINFRAMEWID - WINTITLEHT + 1, 
		right - WINFRAMEWID + 1, top - WINFRAMEWID - WINTITLEHT + 1);
	    SetupFont(WINTITLEFONT, 12);
	    fprintf(psFile, "%d %d moveto (%s) show\n", 
		WINFRAMEWID + 20, top - WINFRAMEWID - WINTITLEHT + 5, show(name));
	    RegisterFontUsed(WINTITLEFONT);
	}
}

#ifdef PROTO
void BeginDrawSubscreen(int ox, int oy)
#else
void BeginDrawSubscreen(ox, oy)
int ox, oy;
#endif
/*Begins a drawing segment offset by ox, oy*/
{
    if (drawingMode == DRAW_POSTSCRIPT && psFile)
    {
	fprintf(psFile, "%d %d translate\n", ox, oy);
    }
}

#ifdef PROTO
void EndDrawSubscreen(int ox, int oy)
#else
void EndDrawSubscreen(ox, oy)
int ox, oy;
#endif
/*Begins a drawing segment offset by ox, oy*/
{
    if (drawingMode == DRAW_POSTSCRIPT && psFile)
    {
	fprintf(psFile, "%d %d translate\n", -ox,  -oy);
    }
}

#ifdef PROTO
void BeginDrawing(char *name, int left, int right, int bottom, int top, real scale)
#else
void BeginDrawing(name, left, right, bottom, top, scale)
char *name;			/*Window title*/
int left, right, bottom, top;	/*Coordinates of window INTERIOR*/
real scale;
#endif
{
#ifdef GRAPHICS
    psFile = tmpfile();
    if (drawingMode == DRAW_POSTSCRIPT && psFile)
    {
	struct timeval date;

        gettimeofday(&date, (struct timezone *)0);
	
	/* "normalize" bounds */
	right -= left;
	top -= bottom;

	/* initialize counters */
	numFontsUsed = 0;
	numIconsUsed = 0;

        /* write EPS header */
        fprintf(psFile,
"\
%%!PS-Adobe-2.0 EPSF-2.0\n\
%%%%Title: %s\n\
%%%%Creator: SciAn\n\
%%%%CreationDate: %s\
%%%%For: %s\n\
%%%%DocumentFonts: (atend)\n\
%%%%BoundingBox: 0 0 %d %d\n\
%%%%EndComments\n\
save\n\n",	/* NOTE: icon font def is inserted after first blank line of file */
	    name, ctime(&date.tv_sec), getenv("USER"),
	    (int) (scale * (real) (right + 1)), (int) (scale * (real) (top + 1)));
    
	fprintf(psFile, 
"/resetclip {matrix currentmatrix currentfont currentlinewidth\n\
grestore gsave setlinewidth setfont setmatrix } def\n\
\n\
currentscreen 3 1 roll pop pop 75 0 3 -1 roll setscreen\n\
gsave\n\
1 setlinewidth\n\
%g %g scale\n\n\n", scale, scale);

    }
#endif
}

#ifdef PROTO
void EndDrawing(Bool showpagep)
#else
void EndDrawing(showpagep)
Bool showpagep;
#endif
{
#ifdef GRAPHICS
    if (drawingMode == DRAW_POSTSCRIPT && psFile && drawFile)
    {
	char buf[256];
        int i;
	
	/* copy header from temp file (copies to first blank line) */
	rewind(psFile);
	while (fgets(buf, 256, psFile))
	{
	    fputs(buf, drawFile);
	    if (*buf == '\n') break;
	}
	
	/* generate font of icons used, if needed */
	GenIconDef(drawFile);
	
	/* copy the rest of the temp file */
	while (fgets(buf, 256, psFile))
	{
	    fputs(buf, drawFile);
	}
	fclose(psFile);

	if (showpagep)
	{
	    fprintf(drawFile, "\nshowpage\n");
	}

        /* write PostScript trailer -- list fonts used */
        fprintf(drawFile, "\nrestore\n\n%%%%Trailer\n%%%%DocumentFonts:");
	for (i=0; i= 32)
    {
        ReportError("RegisterIconUsed","Too many different icons!");
        return -1;
    }
    iconsUsed[numIconsUsed] = icon;
    return numIconsUsed++;
#else
    return 0;
#endif
}

void EraseAll()
/*Erases everything*/
{
    SetUIColor(UIBLACK);
    clear();
}

void InitDraw()
/*Initializes the drawing system*/
{
    int k;

    /*No window at the beginning*/
    curDrawingStateIndex = 0;
    CURSTATE . window = 0;
    CURSTATE . initialWindow = false;
    for (k = 0; k < 4; ++k)
    {
	CURSTATE . screenMask[k] = 0;
	CURSTATE . viewport[k] = 0;
    }
    for (k = 0; k < 2; ++k)
    {
	CURSTATE . origin[k] = 0;
	CURSTATE . translation[k] = 0;
    }
}

void KillDraw()
{
}
Modified: Sun Nov 17 17:00:00 1996 GMT
Page accessed 2427 times since Sat Apr 17 21:54:58 1999 GMT