/*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 "ScianDraw.h"
#include "ScianIDs.h"
#include "ScianWindows.h"
#include "ScianObjWindows.h"
#include "ScianColors.h"
#include "ScianPictures.h"
#include "ScianStyle.h"

Bool drawMouse = false;				/*True iff draw on next mouse*/
extern int curMouse;				/*Current mouse button*/
Bool restrictedDrawing = false;			/*True iff restricted drawing*/
int rLeft, rRight, rBottom, rTop;		/*Restricted bounds*/

int translations[200][2];		/*Translations recorded so far*/
int curTranslation = 0;
#ifdef GRAPHICS
static Screencoord vpl, vpr, vpb, vpt;		/*Current viewport bounds*/
#else
static int vpl, vpr, vpb, vpt;
#endif

static int screenmasks[200][4];			/*Screen masks recorded so far*/
int originX, originY;
static int curScreenmask = 0;
Bool inSpace[200];			/*True iff we're in a space*/
int curInSpace = 0;
#ifdef GRAPHICS
static Matrix savedMatrices[20];
#endif
static int curMatrix = 0;
int drawingMode = DRAW_SCREEN;			/*Drawing to the screen*/
FILE *drawFile = 0;				/*File in which to draw*/
real nffZ = 0.0;				/*Z for NFF file*/

#define XLX(c) ((c) + translations[curTranslation][0])
#define XLY(c) ((c) + translations[curTranslation][1])

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}};

#ifdef PROTO
void RestrictedDrawing(int l, int r, int b, int t)
#else
void RestrictedDrawing(l, r, b, t)
int l; int r; int b; int t;
#endif
/*Sets up subsequent drawing to be restricted*/
{
    restrictedDrawing = true;
    rLeft = l;
    rRight = r;
    rBottom = b;
    rTop = t;
}

#ifdef PROTO
void UnrestrictedDrawing(void)
#else
void UnrestrictedDrawing()
#endif
{
    restrictedDrawing = false;
}

#ifdef PROTO
void RegisterInSpace(Bool whether)
#else
void RegisterInSpace(whether)
Bool whether;
#endif
/*Registers inSpace as whether*/
{
    inSpace[++curInSpace] = whether;
}

void EndRegister()
/*Ends a registration of in space or not*/
{
    --curInSpace;
}

void MyPushMatrix()
{
    if (drawingMode == DRAW_SCREEN)
    {
#ifdef GRAPHICS
	getmatrix(savedMatrices[curMatrix]);
#endif
    }
    ++curMatrix;
}

void MyPopMatrix()
{
    --curMatrix;

    if (drawingMode == DRAW_SCREEN)
    {
#ifdef GRAPHICS
	loadmatrix(savedMatrices[curMatrix]);
#endif
    }
}

void CurOffset(x, y)
int *x, *y;
/*Returns the current offset of the internal mouse coords from global*/
{
    if (inSpace[curInSpace])
    {
	*x = 0;
	*y = 0;
    }
    else
    {
	*x = originX + translations[curTranslation][0];
	*y = originY + translations[curTranslation][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();
}


void SetOrigin(x, y)
int x, y;
/*Sets the origin to x, y WITHIN current translation*/
{
    ++curTranslation;
    translations[curTranslation][0] = translations[curTranslation - 1][0] + x;
    translations[curTranslation][1] = translations[curTranslation - 1][1] + y;
    if (drawingMode == DRAW_SCREEN)
    {
#ifdef GRAPHICS
	translate((Coord) x, (Coord) y, (Coord) 0.0);
	/*DIKEO do something when it's not in DRAW_SCREEN*/
#endif
    }
    else if (drawingMode == DRAW_POSTSCRIPT && drawFile)
    {
        fprintf(drawFile, "%d %d translate\n", x, y);
    }
}

void MakeOrthoXform()
/*Makes an orthographic transformation based on the current state.  This
  is only really neccessary after doing a pick*/
{
    if (drawingMode == DRAW_SCREEN)
    {
#ifdef GRAPHICS
	Screencoord l, r, b, t;
	getviewport(&l, &r, &b, &t);

	ortho2(0, (Coord) r - l, 0, (Coord) t - b);
	translate((Coord) translations[curTranslation][0],
		(Coord) translations[curTranslation][1], (Coord) 0.0);
#endif
    }
}

void GetOrigin(x, y)
int *x, *y;
/*Gets the current origin*/
{
    *x = originX;
    *y = originY;
}

void RestoreOrigin()
/*Restores the origin to what it was*/
{
    if (drawingMode == DRAW_SCREEN)
    {
#ifdef GRAPHICS
	translate((Coord)  (translations[curTranslation - 1][0] -
				translations[curTranslation][0]),
		  (Coord)  (translations[curTranslation - 1][1] -
				translations[curTranslation][1]), 0.0);
#endif
    }
    else if (drawingMode == DRAW_POSTSCRIPT && drawFile)
    {
        fprintf(drawFile, "%d %d translate\n",
            (int)  (translations[curTranslation - 1][0] -
				translations[curTranslation][0]),
	    (int)  (translations[curTranslation - 1][1] -
				translations[curTranslation][1]));
    }
    --curTranslation;
}

#ifdef PROTO
void SetWindowArea(int left, int right, int bottom, int top)
#else
void SetWindowArea(left, right, bottom, top)
int left;
int right;
int bottom;
int top;
#endif
/*Sets to draw into a window area*/
{
#ifdef GRAPHICS
    pushviewport();
    viewport(left, right, bottom, top);
    ortho2(0, (Coord) right - left, 0, (Coord) top - bottom);
#endif

    vpl = left;
    vpr = right;
    vpb = bottom;
    vpt = top;

    /*First translation is the offset within the current viewport*/
    ++curTranslation;
    translations[curTranslation][0] = 0;
    translations[curTranslation][1] = 0;

    /*First screenmask*/
    ++curScreenmask;
    screenmasks[curScreenmask][0] = vpl;
    screenmasks[curScreenmask][1] = vpr;
    screenmasks[curScreenmask][2] = vpb;
    screenmasks[curScreenmask][3] = vpt;

    originX = vpl;
    originY = vpb;
}

void RestoreWindowArea()
/*Resets the window area to what it was before*/
{
    int sl, sr, sb, st;

#ifdef GRAPHICS
    popviewport();
#endif

    sl = screenmasks[curScreenmask][0];
    sr = screenmasks[curScreenmask][1];
    sb = screenmasks[curScreenmask][2];
    st = screenmasks[curScreenmask][3];

    if (drawingMode == DRAW_SCREEN)
    {
#ifdef GRAPHICS
	getviewport(&vpl, &vpr, &vpb, &vpt);
	ortho2(0, (Coord) vpr - vpl + 1, 0, (Coord) vpt - vpb + 1);

	scrmask(sl, sr, sb, st);
	/*DIKEO do something for not drawing to screen*/
#endif
    }
    
    originX = vpl;
    originY = vpb;

    --curScreenmask;
    --curTranslation;
}

#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;

    left += translations[curTranslation][0];
    right += translations[curTranslation][0];
    bottom += translations[curTranslation][1];
    top += translations[curTranslation][1];

    left += originX;
    right += originX;
    bottom += originY;
    top += originY;

    sl = screenmasks[curScreenmask][0];
    sr = screenmasks[curScreenmask][1];
    sb = screenmasks[curScreenmask][2];
    st = screenmasks[curScreenmask][3];

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

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

    screenmasks[curScreenmask][0] = sl;
    screenmasks[curScreenmask][1] = sr;
    screenmasks[curScreenmask][2] = sb;
    screenmasks[curScreenmask][3] = st;
}

void RestoreClipRect()
/*Restores the clipping rectangle to what it was before*/
{
    int sl, sr, sb, st;

    --curScreenmask;
    sl = screenmasks[curScreenmask][0];
    sr = screenmasks[curScreenmask][1];
    sb = screenmasks[curScreenmask][2];
    st = screenmasks[curScreenmask][3];

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

#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);
	}
    }
}

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

    picState = GetVar(obj, PICSTATE);
    if (picState)
    {
	if (hasDouble && (selWinInfo -> flags & WINDBUF))
	{
	    SetVar(obj, PICSTATE, 
		   NewInt(GetInt(picState) & FG ? FGBG : FGBB));
	}
	else
	{
	    SetVar(obj, PICSTATE, NewInt(FGBG));
	}
    }

    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 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);
    if (drawingMode == DRAW_SCREEN)
    {
	recti(left, bottom, right, top);
    }
    else if (drawingMode == DRAW_POSTSCRIPT && drawFile)
    {
	fprintf(drawFile, "%f setgray\n", PSColor());
        fprintf(drawFile, "%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 FrameRect(left, right, bottom, top)
int left, right, bottom, top;
/*Frames a rectangle*/
{
#ifdef GRAPHICS

    if (drawingMode == DRAW_SCREEN)
    {
        recti(left, bottom, right, top);
    }
    else if (drawingMode == DRAW_POSTSCRIPT && drawFile)
    {
	fprintf(drawFile, "%f setgray\n", PSColor());
        fprintf(drawFile, "%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
    FillRealQuad((real) left, (real) (top + 1),
		 (real) left, (real) bottom,
		 (real) (right + 1), (real) bottom,
		 (real) (right + 1), (real) (top + 1));
#endif
}

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

void FillUIDisc(x, y, radius, uiColor)
int x, y, radius, uiColor;
/*Fills a disc in uiColor*/
{
#ifdef GRAPHICS
    SetUIColor(uiColor);
    circfi(x, y, radius);
#endif
}

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

    long vertices[3][2];

    vertices[0][0] = x1;
    vertices[0][1] = y1;
    vertices[1][0] = x2;
    vertices[1][1] = y2;
    vertices[2][0] = x3;
    vertices[2][1] = y3;
    polf2i(3, vertices);
#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);
    setpattern(GREYPAT);
    rectfi(left, bottom, right, top);
    setpattern(SOLIDPAT);
#endif
}

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

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

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

    move2i(x1, y1);
    draw2i(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);
    arcfi(x, y, radius, start * 10, end * 10);
#endif
}

#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*/
{
#ifdef GRAPHICS

    /*Draws a line in a space*/
    move((Coord) x1, (Coord) y1, (Coord) z1);
    draw((Coord) x2, (Coord) y2, (Coord) z2);
#endif
}

#ifdef GRAPHICS
void DrawVCursor(x, yt, yb)
int x, yt, yb;
/*Draws a vertical cursor*/
{
    SetUIColor(UIORANGE);
    move2i(x, yt);
    draw2i(x, yb);
    SetUIColor(UIBLACK);
    move2i(x + 1, yt);
    draw2i(x + 1, yb);
}

#ifdef FONTS4D
extern fmfonthandle currentFontHandle;
#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*/
{

    cmov((Coord) x, (Coord) y, (Coord) z);
#ifdef FONTS4D
	if (currentFontHandle)
	{
		fmprstr(s);
	}
	else
	{
		charstr(s);
	}
#else
	charstr(s);
#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*/
{
    pushmatrix();
    circ(x, y, radius);
    translate(0.0, 0.0, radius * SQ22);
    circ(x, y, radius * SQ22);
    translate(0.0, 0.0, -radius * 2.0 * SQ22);
    circ(x, y, radius * SQ22);
    translate(0.0, 0.0, radius * SQ22);
    rotate(900, 'y');
    circ(x, y, radius);
    rotate(450, 'x');
    circ(x, y, radius);
    rotate(450, 'x');
    circ(x, y, radius);
    rotate(450, 'x');
    circ(x, y, 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[2];
	bgnpolygon();
	v[0] = x1;
	v[1] = y1;
	v2f(v);
	v[0] = x2;
	v[1] = y2;
	v2f(v);
	v[0] = x3;
	v[1] = y3;
	v2f(v);
	v[0] = x4;
	v[1] = y4;
	v2f(v);
	endpolygon();
    }
    else if (drawingMode == DRAW_POSTSCRIPT && drawFile)
    {
	fprintf(drawFile, "%f setgray\n", PSColor());
        fprintf(drawFile, "%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 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);
    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 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
    if (drawingMode == DRAW_SCREEN)
    {
	Coord v[4][2];

	/* bottom */
	v[0][0] = left + EDGE - 1;
	v[0][1] = bottom + EDGE - 1;
	v[1][0] = right - EDGE + 1;
	v[1][1] = bottom + EDGE - 1;
	v[2][0] = right;
	v[2][1] = bottom;
	v[3][0] = left;
	v[3][1] = bottom;
	SetUIColor(UIBOTTOMEDGE);
	polf2(4, v);

	/* left */
	v[0][0] = left;
	v[0][1] = top;
	v[1][0] = left + EDGE - 1;
	v[1][1] = top - EDGE + 1;
	v[2][0] = left + EDGE - 1;
	v[2][1] = bottom + EDGE - 1;
	v[3][0] = left;
	v[3][1] = bottom;
	SetUIColor(UILEFTEDGE);
	polf2(4,v);

	/* right */
	v[0][0] = right - EDGE + 1;
	v[0][1] = top - EDGE + 1;
	v[1][0] = right;
	v[1][1] = top;
	v[2][0] = right;
	v[2][1] = bottom;
	v[3][0] = right - EDGE + 1;
	v[3][1] = bottom + EDGE - 1;
	SetUIColor(UIRIGHTEDGE);
	polf2(4,v);

	/* top */
	v[0][0] = left;
	v[0][1] = top;
	v[1][0] = right;
	v[1][1] = top;
	v[2][0] = right - EDGE + 1;
	v[2][1] = top - EDGE + 1;
	v[3][0] = left + EDGE - 1;
	v[3][1] = top - EDGE + 1;
	SetUIColor(UITOPEDGE);
	polf2(4,v);
    }
    else if (drawingMode == DRAW_POSTSCRIPT && drawFile)
    {
 	/* bottom */
	fprintf(drawFile, "0.125 setgray\n");
        fprintf(drawFile, "%d %d moveto %d %d lineto %d %d lineto %d %d lineto closepath fill\n",
	    left + EDGE, bottom + EDGE,
            right - EDGE, bottom + EDGE,
	    right, bottom, left, bottom); 

	/* left */
	fprintf(drawFile, "0.75 setgray\n");
        fprintf(drawFile, "%d %d moveto %d %d lineto %d %d lineto %d %d lineto closepath fill\n",
	    left, top, left + EDGE, top - EDGE, left + EDGE,
	    bottom + EDGE, left, bottom);

	/* right */
	fprintf(drawFile, "0.25 setgray\n");
        fprintf(drawFile, "%d %d moveto %d %d lineto %d %d lineto %d %d lineto closepath fill\n",
	    right - EDGE, top - EDGE, right, top, right, bottom,
	    right - EDGE, bottom + EDGE);

	/* top */
	fprintf(drawFile, "1.0 setgray\n");
        fprintf(drawFile, "%d %d moveto %d %d lineto %d %d lineto %d %d lineto closepath fill\n",
	    left, top, right, top, right - EDGE, top - EDGE,
	    left + EDGE, top - EDGE);
    }
    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) */
{
#ifdef GRAPHICS
    if (drawingMode == DRAW_SCREEN)
    {
	Coord v[4][2];

	/* bottom */
	v[0][0] = left + EDGE - 1;
	v[0][1] = bottom + EDGE - 1;
	v[1][0] = right - EDGE + 1;
	v[1][1] = bottom + EDGE - 1;
	v[2][0] = right;
	v[2][1] = bottom;
	v[3][0] = left;
	v[3][1] = bottom;
	SetUIColor(UITOPEDGE);
	polf2(4, v);

	/* left */
	v[0][0] = left;
	v[0][1] = top;
	v[1][0] = left + EDGE - 1;
	v[1][1] = top - EDGE + 1;
	v[2][0] = left + EDGE - 1;
	v[2][1] = bottom + EDGE - 1;
	v[3][0] = left;
	v[3][1] = bottom;
	SetUIColor(UIRIGHTEDGE);
	polf2(4,v);

	/* right */
	v[0][0] = right - EDGE + 1;
	v[0][1] = top - EDGE + 1;
	v[1][0] = right;
	v[1][1] = top;
	v[2][0] = right;
	v[2][1] = bottom;
	v[3][0] = right - EDGE + 1;
	v[3][1] = bottom + EDGE - 1;
	SetUIColor(UILEFTEDGE);
	polf2(4,v);

	/* top */
	v[0][0] = left;
	v[0][1] = top;
	v[1][0] = right;
	v[1][1] = top;
	v[2][0] = right - EDGE + 1;
	v[2][1] = top - EDGE + 1;
	v[3][0] = left + EDGE - 1;
	v[3][1] = top - EDGE + 1;
	SetUIColor(UIBOTTOMEDGE);
	polf2(4,v);
    }
    else if (drawingMode == DRAW_POSTSCRIPT && drawFile)
    {
 	/* bottom */
	fprintf(drawFile, "1.0 setgray\n");
        fprintf(drawFile, "%d %d moveto %d %d lineto %d %d lineto %d %d lineto closepath fill\n",
	    left + EDGE, bottom + EDGE,
            right - EDGE, bottom + EDGE,
	    right, bottom, left, bottom); 

	/* left */
	fprintf(drawFile, "0.25 setgray\n");
        fprintf(drawFile, "%d %d moveto %d %d lineto %d %d lineto %d %d lineto closepath fill\n",
	    left, top, left + EDGE, top - EDGE, left + EDGE,
	    bottom + EDGE, left, bottom);

	/* right */
	fprintf(drawFile, "0.75 setgray\n");
        fprintf(drawFile, "%d %d moveto %d %d lineto %d %d lineto %d %d lineto closepath fill\n",
	    right - EDGE, top - EDGE, right, top, right, bottom,
	    right - EDGE, bottom + EDGE);

	/* top */
	fprintf(drawFile, "0.125 setgray\n");
        fprintf(drawFile, "%d %d moveto %d %d lineto %d %d lineto %d %d lineto closepath fill\n",
	    left, top, right, top, right - EDGE, top - EDGE,
	    left + EDGE, top - EDGE);
    }
    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 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
	DrawRaisedEdge(left, right, bottom, top);
	SetUIColor(uiColor);
	DrawInsetRect(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
	DrawSunkenEdge(left, right, bottom, top);
	SetUIColor(uiColor);
	DrawInsetRect(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 && drawFile)
    {
        fprintf(drawFile, "%d setlinewidth\n", width);
    }
#endif
}

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

#ifdef GRAPHICS
    Coord v[4][2];

    SetUIColor(UITEXT);
    /*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;
    polf2(4, v);

    /*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;
    polf2(4, v);

    /*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;
    polf2(4, v);

    /*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;
    polf2(4, v);

#endif /* GRAPHICS */
}

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

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

    SetUIColor(UITEXT);
    /*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;
    polf2(4, v);

    /*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;
    polf2(3, v);
#endif /*GRAPHICS */
}

void	DrawMarkerX(left, right, bottom, top)
int	left, right, bottom, top;
{
#ifdef GRAPHICS
    Coord 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;
    polf2(4, v);

    /*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;
    polf2(4, v);
#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
    Coord a, b, c, v[6][2];

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

	/* bottom */
	v[0][0] = right;
	v[0][1] = bottom;
	v[1][0] = left + (top - bottom)/2;
	v[1][1] = bottom;
	v[2][0] = left;
	v[2][1] = c;
	v[3][0] = a;
	v[3][1] = c;
	v[4][0] = b;
	v[4][1] = bottom + EDGE;
	v[5][0] = right - EDGE;
	v[5][1] = bottom + EDGE;
	SetUIColor(UIBOTTOMEDGE);
	polf2(6, v);

	/* top */
	v[0][0] = a;
	v[0][1] = c;
	v[1][0] = left;
	v[1][1] = c;
	v[2][0] = left + (top - bottom)/2;
	v[2][1] = top;
	v[3][0] = right;
	v[3][1] = top;
	v[4][0] = right - EDGE;
	v[4][1] = top - EDGE;
	v[5][0] = b;
	v[5][1] = top - EDGE;
	SetUIColor(UITOPEDGE);
	polf2(6,v);

	/* right */
	v[0][0] = right;
	v[0][1] = top;
	v[1][0] = right - EDGE;
	v[1][1] = top - EDGE;
	v[2][0] = right - EDGE;
	v[2][1] = bottom + EDGE;
	v[3][0] = right;
	v[3][1] = bottom;
	SetUIColor(UIRIGHTEDGE);
	polf2(4, v);

	/* surface */
	v[0][0] = right - EDGE;
	v[0][1] = bottom + EDGE;
	v[1][0] = b;
	v[1][1] = bottom + EDGE;
	v[2][0] = a;
	v[2][1] = c;
	v[3][0] = b;
	v[3][1] = top - EDGE;
	v[4][0] = right - EDGE;
	v[4][1] = top - EDGE;
	SetUIColor(uiColor);
	polf2(5, v);
#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
    Coord a, b, c, v[6][2];

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

	/* bottom */
	v[0][0] = right;
	v[0][1] = c;
	v[1][0] = right - (top - bottom) /2;
	v[1][1] = bottom;
	v[2][0] = left;
	v[2][1] = bottom;
	v[3][0] = left + EDGE;
	v[3][1] = bottom + EDGE;
	v[4][0] = b;
	v[4][1] = bottom + EDGE;
	v[5][0] = a;
	v[5][1] = c;
	SetUIColor(UIBOTTOMEDGE);
	polf2(6, v);

	/* top */
	v[0][0] = right;
	v[0][1] = c;
	v[1][0] = a;
	v[1][1] = c;
	v[2][0] = b;
	v[2][1] = top - EDGE;
	v[3][0] = left + EDGE;
	v[3][1] = top - EDGE;
	v[4][0] = left;
	v[4][1] = top;
	v[5][0] = right - (top - bottom) / 2;
	v[5][1] = top;
	SetUIColor(UITOPEDGE);
	polf2(6,v);

	/* left */
	v[0][0] = left;
	v[0][1] = bottom;
	v[1][0] = left;
	v[1][1] = top;
	v[2][0] = left + EDGE;
	v[2][1] = top - EDGE;
	v[3][0] = left + EDGE;
	v[3][1] = bottom + EDGE;
	SetUIColor(UILEFTEDGE);
	polf2(4, v);

	/* surface */
	v[0][0] = a;
	v[0][1] = c;
	v[1][0] = b;
	v[1][1] = bottom + EDGE;
	v[2][0] = left + EDGE;
	v[2][1] = bottom + EDGE;
	v[3][0] = left + EDGE;
	v[3][1] = top - EDGE;
	v[4][0] = b;
	v[4][1] = top - EDGE;
	SetUIColor(uiColor);
	polf2(5, v);
#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
    Coord a, b, c, v[6][2];

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

	/* left */
	v[0][0] = c;
	v[0][1] = top;
	v[1][0] = c;
	v[1][1] = a;
	v[2][0] = left + EDGE;
	v[2][1] = b;
	v[3][0] = left + EDGE;
	v[3][1] = bottom + EDGE;
	v[4][0] = left;
	v[4][1] = bottom;
	v[5][0] = left;
	v[5][1] = top - (right - left) /2;
	SetUIColor(UILEFTEDGE);
	polf2(6, v);

	/* right */
	v[0][0] = c;
	v[0][1] = top;
	v[1][0] = right;
	v[1][1] = top - (right - left) / 2;
	v[2][0] = right;
	v[2][1] = bottom;
	v[3][0] = right - EDGE;
	v[3][1] = bottom + EDGE;
	v[4][0] = right - EDGE;
	v[4][1] = b;
	v[5][0] = c;
	v[5][1] = a;
	SetUIColor(UIRIGHTEDGE);
	polf2(6,v);

	/* bottom */
	v[0][0] = right;
	v[0][1] = bottom;
	v[1][0] = left;
	v[1][1] = bottom;
	v[2][0] = left + EDGE;
	v[2][1] = bottom + EDGE;
	v[3][0] = right - EDGE;
	v[3][1] = bottom + EDGE;
	SetUIColor(UIBOTTOMEDGE);
	polf2(4, v);

	/* surface */
	v[0][0] = c;
	v[0][1] = a;
	v[1][0] = right - EDGE;
	v[1][1] = b;
	v[2][0] = right - EDGE;
	v[2][1] = bottom + EDGE;
	v[3][0] = left + EDGE;
	v[3][1] = bottom + EDGE;
	v[4][0] = left + EDGE;
	v[4][1] = b;
	SetUIColor(uiColor);
	polf2(5, v);
#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
    Coord a, b, c, v[6][2];

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

	/* left */
	v[0][0] = c;
	v[0][1] = bottom;
	v[1][0] = left;
	v[1][1] = bottom + (right - left) / 2;
	v[2][0] = left;
	v[2][1] = top;
	v[3][0] = left + EDGE;
	v[3][1] = top - EDGE;
	v[4][0] = left + EDGE;
	v[4][1] = b;
	v[5][0] = c;
	v[5][1] = a;
	SetUIColor(UILEFTEDGE);
	polf2(6, v);

	/* right */
	v[0][0] = c;
	v[0][1] = bottom;
	v[1][0] = c;
	v[1][1] = a;
	v[2][0] = right - EDGE;
	v[2][1] = b;
	v[3][0] = right - EDGE;
	v[3][1] = top - EDGE;
	v[4][0] = right;
	v[4][1] = top;
	v[5][0] = right;
	v[5][1] = bottom + (right - left) / 2;
	SetUIColor(UIRIGHTEDGE);
	polf2(6,v);

	/* top */
	v[0][0] = right;
	v[0][1] = top;
	v[1][0] = right - EDGE;
	v[1][1] = top - EDGE;
	v[2][0] = left + EDGE;
	v[2][1] = top - EDGE;
	v[3][0] = left;
	v[3][1] = top;
	SetUIColor(UITOPEDGE);
	polf2(4, v);

	/* surface */
	v[0][0] = c;
	v[0][1] = a;
	v[1][0] = left + EDGE;
	v[1][1] = b;
	v[2][0] = left + EDGE;
	v[2][1] = top - EDGE;
	v[3][0] = right - EDGE;
	v[3][1] = top - EDGE;
	v[4][0] = right - EDGE;
	v[4][1] = b;
	SetUIColor(uiColor);
	polf2(5, v);
#endif
}

#define WINFRAMEWID 8

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

        gettimeofday(&date, (struct timezone *)0);

        /* write EPS header */
        fprintf(drawFile,
"\
%%!PS-Adobe-2.0 EPSF-2.0\n\
%%%%Title: %s\n\
%%%%Creator: SciAn\n\
%%%%CreationDate: %s\
%%%%For: %s\n\
%%%%DocumentFonts: (atend)\n\
%%%%BoundingBox: %d %d %d %d\n\
%%%%EndComments\n\
\nsave\n\n",
            name, ctime(&date.tv_sec), getenv("USER"),
            left - WINFRAMEWID, bottom - WINFRAMEWID,
            right + WINFRAMEWID, top + WINFRAMEWID);
    }
#endif
}

extern char *fontsUsed[];
extern int numFontsUsed;  /* number used so far = next index to use */

void EndDrawing()
{
#ifdef GRAPHICS
    if (drawingMode == DRAW_POSTSCRIPT && drawFile)
    {
        int i;

        /* write PostScript trailer -- list fonts used */
        fprintf(drawFile, "\nrestore\n\n%%%%Trailer\n%%%%DocumentFonts:");
	for (i=0; i<numFontsUsed; ++i)
        {
            fprintf(drawFile, " %s", fontsUsed[i]);

	    /* free the fontsUsed string space */
            free(fontsUsed[i]);
            fontsUsed[i] = NIL;
        }
        fprintf(drawFile, "\n");
        numFontsUsed = 0;
    }
#endif
}
