[comp.windows.news] NewsDraw 4/5

bvs%carlisle@Sun.COM (Bruce Schwartz) (12/17/88)

#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create:
#	circ.c
#	line.c
#	oval.c
#	rect.c
#	text.c
#	poly.c
# This archive created: Fri Dec 16 15:05:53 1988
export PATH; PATH=/bin:/usr/bin:$PATH
if test -f 'circ.c'
then
	echo shar: "will not over-write existing file 'circ.c'"
else
cat << \SHAR_EOF > 'circ.c'
/* $Header: circ.c,v 1.3 88/12/02 10:43:36 bvs Exp $ */
/* Copyright (C) 1988 by Sun Microsystems. All rights reserved. */
#include <stdio.h>
#include "go.h"
#include "gopvt.h"

/* circ section */
typedef struct {
	ITEMHEADER;
} ICIRC;

static void *CircHolder()
  {
	return((ICIRC *)malloc(sizeof(ICIRC)));
  }

extern double sqrt();
static void *CircNew(x0, y0, x1, y1)
int x0, y0, x1, y1;
  {
	ICIRC *pitem	= (ICIRC *)malloc(sizeof(ICIRC));
	double	xlen	 = (double)((x0 - x1)/2);
	double	ylen	 = (double)((y0 - y1)/2);
	double xcenter	 = (double)((x0 + x1)/2);
	double ycenter	 = (double)((y0 + y1)/2);
	double radius	= (int)sqrt((double)(xlen*xlen + ylen*ylen));
	pitem->type		= CIRC;
	pitem->x0		= xcenter - radius;
	pitem->y0		= ycenter - radius;
	pitem->x1		= xcenter + radius;
	pitem->y1		= ycenter + radius;
	pitem->rotation	= 0;
	pitem->xscale	= 1;
	pitem->yscale	= 1;
	pitem->prop		= PropCopyOf(PropCurrent());
	return(pitem);
  }

static void *CircDraw(pitem)
ICIRC *pitem;
  {
	float stroke	= PropStrokeColor(pitem->prop);
	float fill		= PropFillColor(pitem->prop);
	int   width		= PropLineWidth(pitem->prop);

	ps_gsave();
	if(fill >= 0.0)
	  {
		ps_setgray(fill);
		ps_drawcirc((X0 + X1)/2, (Y0 + Y1)/2, (X1 - X0)/2);
		ps_fill();
	  }
	if(stroke >= 0.0)
	  {
		ps_setlinewidth(width);
		ps_setgray(stroke);
		ps_drawcirc((X0 + X1)/2, (Y0 + Y1)/2, (X1 - X0)/2);
		ps_stroke();
	  }
	ps_grestore();
	return(pitem);
  }

static void *CircPrint(pitem, pfile)
ICIRC *pitem;
FILE *pfile;
  {
	float stroke	= PropStrokeColor(pitem->prop);
	float fill		= PropFillColor(pitem->prop);
	int   width		= PropLineWidth(pitem->prop);

	fprintf(pfile, "%% circle\n");
	if(fill >= 0.0)
	  {
		fprintf(pfile, "%f setgray ", fill);
		fprintf(pfile, "%d %d %d circpath ",
			(X0 + X1)/2, (Y0 + Y1)/2, (X1 - X0)/2);
		fprintf(pfile, "fill\n");
	  }
	if(stroke >= 0.0)
	  {
		fprintf(pfile, "%d setlinewidth ", width);
		fprintf(pfile, "%f setgray ", stroke);
		fprintf(pfile, "%d %d %d circpath ",
			(X0 + X1)/2, (Y0 + Y1)/2, (X1 - X0)/2);
		fprintf(pfile, "stroke\n");
	  }
	return(pitem);
  }

GOCircInit(pgoprocs)
GOPROCS *pgoprocs;
  {
	pgoprocs->holder= CircHolder;	
	pgoprocs->new	= CircNew;	
	pgoprocs->draw	= CircDraw;	
	pgoprocs->print	= CircPrint;	
  }

/************* event handlers *************/

static void *CircSelect(x, y)
int x,y;
  {
	ps_circcreateinteractive(x, y);
  }
static void *CircAdjust(x, y)
int x,y;
  {
	fprintf(stderr, "CircAdjust not implemented\n");
  }
static void *CircReply(x0, y0, x1, y1)
int x0, y0, x1, y1;
  {
	/* maybe we should just make this an oval! */
	ITEM *pitem;
	if((x0 == x1) && (y0 == y1)) return;
	pitem = GONewCirc(x0, y0, x1, y1);
	GOItemAddToTop(pitem);
	GODrawItem(pitem);
	return(pitem);
  }
static void *CircBegin()
  {
	ps_xcursor();
  }
EHCircInit(pprocs)
EHPROCS *pprocs;
  {
	pprocs->handleselect	= CircSelect;	
	pprocs->handleadjust	= CircAdjust;	
	pprocs->handlereply		= CircReply;	
	pprocs->handlebegin		= CircBegin;	
  }
SHAR_EOF
fi
if test -f 'line.c'
then
	echo shar: "will not over-write existing file 'line.c'"
else
cat << \SHAR_EOF > 'line.c'
/* $Header: line.c,v 1.3 88/12/02 10:43:37 bvs Exp $ */
/* Copyright (C) 1988 by Sun Microsystems. All rights reserved. */
#include <stdio.h>
#include <math.h>
#include "go.h"
#include "gopvt.h"

/* line section */
typedef struct {
	ITEMHEADER;
} ILINE;

static void *LineHolder()
  {
	return((ILINE *)malloc(sizeof(ILINE)));
  }

#define SQUARE(x) ((x)*(x))

static void *LineNew(x0, y0, x1, y1)
int x0, y0, x1, y1;
  {
	double	length  =  sqrt((double)(SQUARE(x0 - x1) + SQUARE(y0 - y1)));

	ILINE *pitem	= (ILINE *)malloc(sizeof(ILINE));
	pitem->type		= LINE;
	pitem->rotation	=
		atan2((double)(y1 - y0), (double)(x1 - x0)) * 180.0 / M_PI;
	pitem->x0		= (int)(((double)x0 + (double)x1 - length) / 2.0);
	pitem->y0		= (y0 + y1) / 2;
	pitem->x1		= pitem->x0 + length;
	pitem->y1		= pitem->y0;
	pitem->xscale	= 1;
	pitem->yscale	= 1;
	pitem->prop		= PropCopyOf(PropCurrent());
	return(pitem);
  }

static void *LineDraw(pitem)
ILINE *pitem;
  {
	float stroke	= PropStrokeColor(pitem->prop);
	int   width		= PropLineWidth(pitem->prop);

	ps_gsave();
	if(stroke >= 0.0)
	  {
		ps_setlinewidth(width);
		ps_setgray(stroke);
		ps_drawline(X0, Y0, X1, Y1);
		ps_stroke();
	  }
	ps_grestore();
	return(pitem);
  }

static void *LinePrint(pitem, pfile)
ILINE *pitem;
FILE *pfile;
  {
	float stroke	= PropStrokeColor(pitem->prop);
	int   width		= PropLineWidth(pitem->prop);

	fprintf(pfile, "%% line\n");
	if(stroke >= 0.0)
	  {
		fprintf(pfile, "%d setlinewidth ", width);
		fprintf(pfile, "%f setgray ", stroke);
		fprintf(pfile, "%d %d %d %d linepath ", X0, Y0, X1, Y1);
		fprintf(pfile, "stroke\n");
	  }
	return(pitem);
  }

GOLineInit(pgoprocs)
GOPROCS *pgoprocs;
  {
	pgoprocs->holder= LineHolder;	
	pgoprocs->new	= LineNew;	
	pgoprocs->draw	= LineDraw;	
	pgoprocs->print	= LinePrint;	
  }

/************* event handlers *************/

static void *LineSelect(x, y)
int x,y;
  {
	ps_linecreateinteractive(x, y);
  }
static void *LineAdjust(x, y)
int x,y;
  {
	fprintf(stderr, "LineAdjust not implemented\n");
  }
static void *LineReply(x0, y0, x1, y1)
int x0, y0, x1, y1;
  {
	ITEM *pitem;
	if((x0 == x1) && (y0 == y1)) return;
	pitem = GONewLine(x0, y0, x1, y1);
	GOItemAddToTop(pitem);
	GODrawItem(pitem);
	return(pitem);
  }
static void *LineBegin()
  {
	ps_xcursor();
  }
EHLineInit(pprocs)
EHPROCS *pprocs;
  {
	pprocs->handleselect	= LineSelect;	
	pprocs->handleadjust	= LineAdjust;	
	pprocs->handlereply		= LineReply;	
	pprocs->handlebegin		= LineBegin;	
  }

SHAR_EOF
fi
if test -f 'oval.c'
then
	echo shar: "will not over-write existing file 'oval.c'"
else
cat << \SHAR_EOF > 'oval.c'
/* $Header: oval.c,v 1.3 88/12/02 10:43:39 bvs Exp $ */
/* Copyright (C) 1988 by Sun Microsystems. All rights reserved. */
#include <stdio.h>
#include "go.h"
#include "gopvt.h"

/* oval section */
typedef struct {
	ITEMHEADER;
} IOVAL;

static void *OvalHolder()
  {
	return((IOVAL *)malloc(sizeof(IOVAL)));
  }


static void *OvalNew(x0, y0, x1, y1)
int x0, y0, x1, y1;
  {
	IOVAL *pitem	= (IOVAL *)malloc(sizeof(IOVAL));
	pitem->type		= OVAL;
	pitem->x0		= MIN(x0, x1);
	pitem->y0		= MIN(y0, y1);
	pitem->x1		= MAX(x0, x1);
	pitem->y1		= MAX(y0, y1);
	pitem->rotation	= 0;
	pitem->xscale	= 1;
	pitem->yscale	= 1;
	pitem->prop		= PropCopyOf(PropCurrent());
	return(pitem);
  }

static void *OvalDraw(pitem)
IOVAL *pitem;
  {
	float stroke	= PropStrokeColor(pitem->prop);
	float fill		= PropFillColor(pitem->prop);
	int   width		= PropLineWidth(pitem->prop);

	ps_gsave();
	if(fill >= 0.0)
	  {
		ps_setgray(fill);
		ps_drawoval(X0, Y0, X1, Y1);
		ps_fill();
	  }
	if(stroke >= 0.0)
	  {
		ps_setlinewidth(width);
		ps_setgray(stroke);
		ps_drawoval(X0, Y0, X1, Y1);
		ps_stroke();
	  }
	ps_grestore();
	return(pitem);
  }

static void *OvalPrint(pitem, pfile)
IOVAL *pitem;
FILE *pfile;
  {
	float stroke	= PropStrokeColor(pitem->prop);
	float fill		= PropFillColor(pitem->prop);
	int   width		= PropLineWidth(pitem->prop);

	fprintf(pfile, "%% oval\n");
	if(fill >= 0.0)
	  {
		fprintf(pfile, "%f setgray ", fill);
		fprintf(pfile, "%d %d %d %d ovalpath ", X0, Y0, W, H);
		fprintf(pfile, "fill\n");
	  }
	if(stroke >= 0.0)
	  {
		fprintf(pfile, "%d setlinewidth ", width);
		fprintf(pfile, "%f setgray ", stroke);
		fprintf(pfile, "%d %d %d %d ovalpath ", X0, Y0, W, H);
		fprintf(pfile, "stroke\n");
	  }
	return(pitem);
  }

GOOvalInit(pgoprocs)
GOPROCS *pgoprocs;
  {
	pgoprocs->holder= OvalHolder;	
	pgoprocs->new	= OvalNew;	
	pgoprocs->draw	= OvalDraw;	
	pgoprocs->print	= OvalPrint;	
  }

/************* event handlers *************/

static void *OvalSelect(x, y)
int x,y;
  {
	ps_ovalcreateinteractive(x, y);
  }
static void *OvalAdjust(x, y)
int x,y;
  {
	fprintf(stderr, "OvalAdjust not implemented\n");
  }
static void *OvalReply(x0, y0, x1, y1)
int x0, y0, x1, y1;
  {
	ITEM *pitem;
	if((x0 == x1) && (y0 == y1)) return;
	pitem = GONewOval(x0, y0, x1, y1);
	GOItemAddToTop(pitem);
	GODrawItem(pitem);
	return(pitem);
  }
static void *OvalBegin()
  {
	ps_xcursor();
  }
EHOvalInit(pprocs)
EHPROCS *pprocs;
  {
	pprocs->handleselect	= OvalSelect;	
	pprocs->handleadjust	= OvalAdjust;	
	pprocs->handlereply		= OvalReply;	
	pprocs->handlebegin		= OvalBegin;	
  }

SHAR_EOF
fi
if test -f 'rect.c'
then
	echo shar: "will not over-write existing file 'rect.c'"
else
cat << \SHAR_EOF > 'rect.c'
/* $Header: rect.c,v 1.4 88/12/02 10:43:24 bvs Exp $ */
/* Copyright (C) 1988 by Sun Microsystems. All rights reserved. */
#include <stdio.h>
#include "go.h"
#include "gopvt.h"

/* rect section */
typedef struct {
	ITEMHEADER;
} IRECT;

static void *RectHolder()
  {
	return((IRECT *)malloc(sizeof(IRECT)));
  }

static void *RectNew(x0, y0, x1, y1)
int x0, y0, x1, y1;
  {
	IRECT *pitem	= (IRECT *)RectHolder();
	pitem->type		= RECT;
	pitem->x0		= MIN(x0, x1);
	pitem->y0		= MIN(y0, y1);
	pitem->x1		= MAX(x0, x1);
	pitem->y1		= MAX(y0, y1);
	pitem->rotation	= 0;
	pitem->xscale	= 1;
	pitem->yscale	= 1;
	pitem->prop		= PropCopyOf(PropCurrent());
	return(pitem);
  }

static void *RectDraw(pitem)
IRECT *pitem;
  {
	float stroke	= PropStrokeColor(pitem->prop);
	float fill		= PropFillColor(pitem->prop);
	int   width		= PropLineWidth(pitem->prop);

	ps_gsave();
	if(fill >= 0.0)
	  {
		ps_setgray(fill);
		ps_drawrect(X0, Y0, X1, Y1);
		ps_fill();
	  }
	if(stroke >= 0.0)
	  {
		ps_setlinewidth(width);
		ps_setgray(stroke);
		ps_drawrect(X0, Y0, X1, Y1);
		ps_stroke();
	  }
	ps_grestore();
	return(pitem);
  }

static void *RectPrint(pitem, pfile)
IRECT *pitem;
FILE *pfile;
  {
	float stroke	= PropStrokeColor(pitem->prop);
	float fill		= PropFillColor(pitem->prop);
	int   width		= PropLineWidth(pitem->prop);

	fprintf(pfile, "%% rectangle\n");
	if(fill >= 0.0)
	  {
		fprintf(pfile, "%f setgray ", fill);
		fprintf(pfile, "%d %d %d %d rectpath ", X0, Y0, W, H);
		fprintf(pfile, "fill\n");
	  }
	if(stroke >= 0.0)
	  {
		fprintf(pfile, "%d setlinewidth ", width);
		fprintf(pfile, "%f setgray ", stroke);
		fprintf(pfile, "%d %d %d %d rectpath ", X0, Y0, W, H);
		fprintf(pfile, "stroke\n");
	  }
	return(pitem);
  }

GORectInit(pgoprocs)
GOPROCS *pgoprocs;
  {
	pgoprocs->holder= RectHolder;	
	pgoprocs->new	= RectNew;	
	pgoprocs->draw	= RectDraw;	
	pgoprocs->print	= RectPrint;	
  }

/************* event handlers *************/

static void *RectSelect(x, y)
int x,y;
  {
	ps_rectcreateinteractive(x, y);
  }
static void *RectAdjust(x, y)
int x,y;
  {
	fprintf(stderr, "RectAdjust not implemented\n");
  }
static void *RectReply(x0, y0, x1, y1)
int x0, y0, x1, y1;
  {
	ITEM *pitem;
	if((x0 == x1) && (y0 == y1)) return;
	pitem = GONewRect(x0, y0, x1, y1);
	GOItemAddToTop(pitem);
	GODrawItem(pitem);
	return(pitem);
  }
static void *RectBegin()
  {
	ps_xcursor();
  }
EHRectInit(pprocs)
EHPROCS *pprocs;
  {
	pprocs->handleselect	= RectSelect;	
	pprocs->handleadjust	= RectAdjust;	
	pprocs->handlereply		= RectReply;	
	pprocs->handlebegin		= RectBegin;	
  }

SHAR_EOF
fi
if test -f 'text.c'
then
	echo shar: "will not over-write existing file 'text.c'"
else
cat << \SHAR_EOF > 'text.c'
/* $Header: text.c,v 1.3 88/12/02 10:43:41 bvs Exp $ */
/* Copyright (C) 1988 by Sun Microsystems. All rights reserved. */
 
#include <stdio.h>
#include "go.h"
#include "gopvt.h"

/* text section */
typedef struct {
	ITEMHEADER;
	char *ptext;
} ITEXT;

static void *TextHolder()
  {
	return((ITEXT *)malloc(sizeof(ITEXT)));
  }


extern double sqrt();
static void *TextNew(x0, y0, ptext)
int x0, y0;
char *ptext;
  {
	ITEXT *pitem	= (ITEXT *)malloc(sizeof(ITEXT));

	pitem->prop		= PropCopyOf(PropCurrent());

	pitem->type		= TEXT;
	pitem->rotation	= 0;
	pitem->xscale	= 1;
	pitem->yscale	= 1;
	pitem->ptext	= (char *)malloc(strlen(ptext));
	strcpy(pitem->ptext, ptext);

	pitem->y0		= y0 - FontDescent(PropFont(pitem->prop));
	pitem->y1		= y0 + FontAscent(PropFont(pitem->prop));
	pitem->x0		= x0;
	pitem->x1		= x0 + FontTextWidth(PropFont(pitem->prop), ptext);
	return(pitem);
  }

static void *TextDraw(pitem)
ITEXT *pitem;
  {
	float text		= PropTextColor(pitem->prop);
	FONT *pfont		= PropFont(pitem->prop);

	ps_gsave();
	if(text >= 0.0)
	  {
		ps_setgray(text);
		ps_moveto(pitem->x0, pitem->y0 + FontDescent(pfont));
		ps_show(pitem->ptext);
	  }
	ps_grestore();
	return(pitem);
  }

static void *TextPrint(pitem, pfile)
ITEXT *pitem;
FILE *pfile;
  {
	float text		= PropTextColor(pitem->prop);
	FONT *pfont		= PropFont(pitem->prop);
	if(text >= 0.0)
	  {
		fprintf(pfile, "%f setgray ", text);
		fprintf(pfile, "%d %d moveto ",
			pitem->x0, pitem->y0 + FontDescent(pfont));
		fprintf(pfile, "(%s) show\n", pitem->ptext);
	  }
	return(pitem);
  }

static void *TextWrite(pitem, pfile)
ITEXT *pitem;
FILE *pfile;
  {
	char *pc;
	pc = pitem->ptext;
	while((*pc != 0) && (*pc != '\n') && (*pc != 10))
	  {
		fputc(*pc, pfile);
		pc++;
	  }
	fputc('\n', pfile);
	/* fprintf(pfile, "%s\n", pitem->ptext); */
  }

static void *TextRead(pitem, pfile)
ITEXT *pitem;
FILE *pfile;
  {
	char buf[256];
	fgets(buf, 256, pfile);
	pitem->ptext	= (char *)malloc(strlen(buf));
	strcpy(pitem->ptext, buf);
  }

GOTextInit(pgoprocs)
GOPROCS *pgoprocs;
  {
	pgoprocs->holder= TextHolder;	
	pgoprocs->new	= TextNew;	
	pgoprocs->draw	= TextDraw;	
	pgoprocs->print	= TextPrint;	
	pgoprocs->write	= TextWrite;	
	pgoprocs->read	= TextRead;	
  }

/************* event handlers *************/

static int iText = 0;
static char aText[255];
static int textx, texty;
static int bSaved = 0;
static void *TextBegin()
  {
	ps_xcursor();
  }
static void *TextSelect(x, y)
int x,y;
  {
	int ascent = FontAscent(FontDefault());
	int descent = FontDescent(FontDefault());
	if(iText != 0)
	  {
		TextComplete();
	  }
	iText = 0;
	aText[0] = 0;
	textx = x;
	texty = y;

	if(bSaved) ps_restorearea();
	ps_savearea(textx - 6, texty - descent - 1, 1000, texty + ascent + 1);
	/* ps_savearea(0, 0, 1000, 1000); */
	bSaved = 1;
	ps_setgray(1.0);
	ps_drawrect(textx - 4, texty - descent - 1, textx + 4, texty + ascent + 1);
	ps_fill();
	ps_setgray(0.0);
	ps_drawline(textx, texty - descent, textx, texty + ascent);
	ps_drawline(textx - 3, texty, textx + 3, texty);
	ps_stroke();
  }
static void *TextAdjust(x, y)
int x,y;
  {
	fprintf(stderr, "TextAdjust not implemented\n");
  }
static void *TextKey(key)
int key;
  {
	int ascent = FontAscent(FontDefault());
	int descent = FontDescent(FontDefault());
	/* fprintf(stderr, "TextKey %c (0x%x)\n", key, key); */
	switch(key)
	  {
		default:
			aText[iText] = key;
			iText++;
			aText[iText] = 0;
			break;
	    case 0177:
	    case '\b':
			if(iText)
			  {
				iText--;
				aText[iText] = 0;
			  }
			break;
	  }
	ps_restorearea();

	ps_setgray(PropTextColor(PropCurrent()));
	ps_moveto(textx, texty);
	ps_show(aText);
	ps_rlineto(0, ascent);
	ps_rlineto(0, -ascent - descent);
	ps_rmoveto(0, descent);
	ps_rmoveto(-3, 0);
	ps_rlineto(6, 0);
	ps_stroke();
  }
static TextComplete()
  {
	ITEM *pitem;

	ps_restorearea();
	bSaved = 0;

	pitem = GONewText(textx, texty, aText, FontDefault());
	GOItemAddToTop(pitem);
	GODrawItem(pitem);
	/*
	ps_moveto(textx, texty);
	ps_show(aText);
	*/

	iText = 0;
	aText[0] = 0;
  }
static void *TextEnd()
  {
	if(iText)
		TextComplete();
	else if(bSaved)
		ps_restorearea();
  }

static void *TextProp(c)
int c;
  {
	PropHandle(c);
	if(iText != 0)
	  {
		ps_setgray(PropTextColor(PropCurrent()));
		ps_moveto(textx, texty);
		ps_show(aText);
	  }
  }
EHTextInit(pprocs)
EHPROCS *pprocs;
  {
	pprocs->handleselect	= TextSelect;	
	pprocs->handleadjust	= TextAdjust;	
	pprocs->handlekey		= TextKey;	
	pprocs->handlebegin		= TextBegin;	
	pprocs->handleend		= TextEnd;	
	pprocs->handleprop		= TextProp;	
  }

SHAR_EOF
fi
if test -f 'poly.c'
then
	echo shar: "will not over-write existing file 'poly.c'"
else
cat << \SHAR_EOF > 'poly.c'
/* $Header: poly.c,v 1.2 88/12/02 10:43:49 bvs Exp $ */
/* Copyright (C) 1988 by Sun Microsystems. All rights reserved. */
#include <stdio.h>
#include <math.h>
#include "go.h"
#include "gopvt.h"

/* poly section */
typedef struct {
	int x;
	int y;
} POINT;

typedef struct {
	ITEMHEADER;
	POINT *apoint;
	int length;
	int closepath;
} IPOLY;

static void *PolyHolder()
  {
	return((IPOLY *)malloc(sizeof(IPOLY)));
  }

static PolyMinMax(pitem, apoint, length)
IPOLY *pitem;
POINT apoint[];
int length;
  {
	int i;
	int x0 = apoint[0].x;
	int y0 = apoint[0].y;
	int x1 = x0;
	int y1 = y0;

	/* find bounds */
	for(i = 1; i < length; i++)
	  {
		x0 = MIN(x0, apoint[i].x);
		y0 = MIN(y0, apoint[i].y);
		x1 = MAX(x1, apoint[i].x);
		y1 = MAX(y1, apoint[i].y);
	  }

	/* make relative */
	for(i = length - 1; i > 0; i--)
	  {
		apoint[i].x -= apoint[i - 1].x;
		apoint[i].y -= apoint[i - 1].y;
	  }
	apoint[0].x -= x0;
	apoint[0].y -= y0;

	pitem->x0 = x0;
	pitem->y0 = y0;
	pitem->x1 = x1;
	pitem->y1 = y1;
	pitem->apoint = apoint;
	pitem->length = length;
  }

static void *PolyNew(apoint, length, closepath)
POINT apoint[];	/* apoint will not be copied by this proc! */
int length;
int closepath;
  {
	IPOLY *pitem	= (IPOLY *)PolyHolder();
	pitem->type		= POLY;
	pitem->rotation	= 0;
	pitem->closepath= closepath;

	/* take care of x0,y0,x1,y1 */
	PolyMinMax(pitem, apoint, length);
	pitem->xscale	= 1;
	pitem->yscale	= 1;
	pitem->prop		= PropCopyOf(PropCurrent());
	return(pitem);
  }

static void *PolyDraw(pitem)
IPOLY *pitem;
  {
	float stroke	= PropStrokeColor(pitem->prop);
	float fill		= PropFillColor(pitem->prop);
	int   width		= PropLineWidth(pitem->prop);
	int	i;

	ps_gsave();
	if(fill >= 0.0)
	  {
		ps_setgray(fill);
		ps_moveto(pitem->x0, pitem->y0);
		ps_rmoveto(pitem->apoint[0].x, pitem->apoint[0].y);
		for(i = 1; i < pitem->length; i++)
			ps_rlineto(pitem->apoint[i].x, pitem->apoint[i].y);
		ps_closepath();
		ps_fill();
	  }
	if(stroke >= 0.0)
	  {
		ps_setlinewidth(width);
		ps_setgray(stroke);
		ps_moveto(pitem->x0, pitem->y0);
		ps_rmoveto(pitem->apoint[0].x, pitem->apoint[0].y);
		for(i = 1; i < pitem->length; i++)
			ps_rlineto(pitem->apoint[i].x, pitem->apoint[i].y);
		if(pitem->closepath) ps_closepath();
		ps_stroke();
	  }
	ps_grestore();
	return(pitem);
  }

static void *PolyPrint(pitem, pfile)
IPOLY *pitem;
FILE *pfile;
  {
	float stroke	= PropStrokeColor(pitem->prop);
	float fill		= PropFillColor(pitem->prop);
	int   width		= PropLineWidth(pitem->prop);
	int   i;

	fprintf(pfile, "%% poly\n");
	if(fill >= 0.0)
	  {
		fprintf(pfile, "%f setgray ", fill);
		fprintf(pfile, "%d %d moveto ", pitem->x0, pitem->y0);
		fprintf(pfile, "%d %d rmoveto ",
			pitem->apoint[0].x, pitem->apoint[0].y);
		fprintf(pfile, "\n");

		for(i = 1; i < pitem->length; i++)
		  {
			fprintf(pfile, "%d %d rlineto \n",
				pitem->apoint[i].x, pitem->apoint[i].y);
		  }
		fprintf(pfile, "closepath fill\n");
	  }
	if(stroke >= 0.0)
	  {
		fprintf(pfile, "%d setlinewidth ", width);
		fprintf(pfile, "%f setgray ", stroke);
		fprintf(pfile, "%d %d moveto ", pitem->x0, pitem->y0);
		fprintf(pfile, "%d %d rmoveto ",
			pitem->apoint[0].x, pitem->apoint[0].y);
		fprintf(pfile, "\n");

		for(i = 1; i < pitem->length; i++)
		  {
			fprintf(pfile, "%d %d rlineto ",
				pitem->apoint[i].x, pitem->apoint[i].y);
		  }
		if(pitem->closepath) fprintf(pfile, "closepath ");
		fprintf(pfile, "stroke\n");
	  }
	return(pitem);
  }

static void *PolyWrite(pitem, pfile)
IPOLY *pitem;
FILE *pfile;
  {
	int i;
	fprintf(pfile, "%d ", pitem->closepath);
	fprintf(pfile, "%d\n", pitem->length);
	for(i = 0; i < pitem->length; i++)
		fprintf(pfile, "%d %d\n", pitem->apoint[i].x, pitem->apoint[i].y);
  }

static void *PolyRead(pitem, pfile)
IPOLY *pitem;
FILE *pfile;
  {
	int i;
	if(1 != fscanf(pfile, "%d", &pitem->closepath))
	  {
		fprintf(stderr, "Error reading poly...exiting");
		exit(1);
	  }
	if(1 != fscanf(pfile, "%d", &pitem->length))
	  {
		fprintf(stderr, "Error reading poly...exiting");
		exit(1);
	  }
	pitem->apoint = (POINT *)malloc(pitem->length * sizeof(POINT));
	for(i = 0; i < pitem->length; i++)
	  {
		if(2 != fscanf(pfile, "%d %d",
			&pitem->apoint[i].x, &pitem->apoint[i].y))
		  {
			fprintf(stderr, "Error reading poly...exiting");
			exit(1);
		  }
	  }
	
	while(getc(pfile) != '\n') ;
  }


GOPolyInit(pgoprocs)
GOPROCS *pgoprocs;
  {
	pgoprocs->holder= PolyHolder;	
	pgoprocs->new	= PolyNew;	
	pgoprocs->draw	= PolyDraw;	
	pgoprocs->print	= PolyPrint;	
	pgoprocs->read	= PolyRead;	
	pgoprocs->write	= PolyWrite;	
  }

/* Brushes and polygons draw the same! */
GOBrushInit(pgoprocs)
GOPROCS *pgoprocs;
  {
	GOPolyInit(pgoprocs);
  }

/************* event handlers *************/

static POINT *pbuf = (POINT *)0;
static POINT *pcurrent;
static int lcurrent;
#define MAXPOINTS 100
static polyBeginCurrent(x, y)
int x, y;
  {
	lcurrent = 1;
	pbuf = pcurrent = (POINT *)malloc(MAXPOINTS * sizeof(POINT));
	pcurrent->x = x;
	pcurrent->y = y;
  }
static polyAddPoint(x, y)
int x, y;
  {
	lcurrent++;
	if(lcurrent >= MAXPOINTS)
	  {
		fprintf(stderr, "too many points in polygon\n");
		return;
	  }
	ps_drawline(pcurrent->x, pcurrent->y, x, y);
	ps_stroke();

	pcurrent++;
	pcurrent->x = x;
	pcurrent->y = y;
  }
static polyEndCurrent()
  {
	ITEM *pitem;
	POINT *ppoint;

	if(lcurrent == 1)
	  {
		free(pbuf);
		return;
	  }

	/* polyAddPoint(pbuf->x, pbuf->y); */
	ppoint = (POINT *)malloc(lcurrent * sizeof(POINT));
	bcopy(pbuf, ppoint, lcurrent * sizeof(POINT));
	pitem = PolyNew(ppoint, lcurrent, 1);
	GOItemAddToTop(pitem);
	GODrawItem(pitem);

	free(pbuf);
	pbuf = 0;
	lcurrent = 1;
  }
static void *PolySelect(x, y)
int x,y;
  {
	if(pbuf)
		return;

	polyBeginCurrent(x, y);
	ps_linecreateinteractive(x, y);
  }
static void *PolyAdjust(x, y)
int x,y;
  {
  }
static void *PolyReply(x0, y0, x1, y1)
int x0, y0, x1, y1;
  {
	if((lcurrent != 1) && (pcurrent->x == x1) && (pcurrent->y == y1))
	  {
		polyAddPoint(x1, y1);
		polyEndCurrent();
		return;
	  }
	polyAddPoint(x1, y1);
	ps_linecreateinteractive(x1, y1);
  }
static void *PolyEnd()
  {
	if(pbuf)
	  {
		polyEndCurrent();
	  }
  }
static void *PolyBegin()
  {
	ps_xcursor();
  }
EHPolyInit(pprocs)
EHPROCS *pprocs;
  {
	pprocs->handleselect	= PolySelect;	
	pprocs->handleadjust	= PolyAdjust;	
	pprocs->handlereply		= PolyReply;	
	pprocs->handlebegin		= PolyBegin;	
	pprocs->handlebegin		= PolyEnd;	
  }

/************* event handlers *************/

static void *BrushSelect(x, y)
int x,y;
  {
	ps_pencilCreateinteractive(x, y);
  }
static void *BrushAdjust(x, y)
int x,y;
  {
  }
static void *BrushReply(x0, y0, x1, y1)
int x0, y0, x1, y1;
  {
	ITEM *pitem;
	int length;
	int i;
	POINT *ppoint;

	ps_getint(&length);
	ppoint = (POINT *)malloc(length * sizeof(POINT));
	for(i = 0; i < length; i++)
	  {
		ps_getint(&ppoint[i].x);
		ps_getint(&ppoint[i].y);
	  }
	
	pitem = PolyNew(ppoint, length, 0);
	GOItemAddToTop(pitem);
	GODrawItem(pitem);
	return(pitem);
  }
static void *BrushEnd()
  {
  }
static void *BrushBegin()
  {
	ps_xcursor();
  }
EHBrushInit(pprocs)
EHPROCS *pprocs;
  {
	pprocs->handleselect	= BrushSelect;	
	pprocs->handleadjust	= BrushAdjust;	
	pprocs->handlereply		= BrushReply;	
	pprocs->handlebegin		= BrushBegin;	
	pprocs->handlebegin		= BrushEnd;	
  }

SHAR_EOF
fi
exit 0
#	End of shell archive