[comp.windows.news] NewsDraw 5/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:
#	draw.c
#	item.c
#	eh.c
#	font.c
#	go.c
#	file.c
#	prop.c
#	stretch.c
# This archive created: Fri Dec 16 15:05:54 1988
export PATH; PATH=/bin:/usr/bin:$PATH
if test -f 'draw.c'
then
	echo shar: "will not over-write existing file 'draw.c'"
else
cat << \SHAR_EOF > 'draw.c'
/* $Header: draw.c,v 1.6 88/12/02 10:43:13 bvs Exp $ */
/* Copyright (C) 1988 by Sun Microsystems. All rights reserved. */

/*
	%
	% This file is a product of Sun Microsystems, Inc. and is provided for
	% unrestricted use provided that this legend is included on all tape
	% media and as a part of the software program in whole or part.
	% Users may copy, modify or distribute this file at will.
	%
	% THIS FILE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
	% WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
	% PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
	%
	% This file is provided with no support and without any obligation on the
	% part of Sun Microsystems, Inc. to assist in its use, correction,
	% modification or enhancement.
	%
	% SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
	% INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS FILE
	% OR ANY PART THEREOF.
	%
	% In no event will Sun Microsystems, Inc. be liable for any lost revenue
	% or profits or other special, indirect and consequential damages, even
	% if Sun has been advised of the possibility of such damages.
	%
	% Sun Microsystems, Inc.
	% 2550 Garcia Avenue
	% Mountain View, California  94043
	%
	% Copyright (C) 1988 by Sun Microsystems. All rights reserved.
*/
#include <stdio.h>
#include "psio.h"
#include "psint.h"
#include "draw.h"

main()
  {
	int mode, newmode;
	int key;
	int x0, y0, x1, y1;
	int dx0, dy0, dx1, dy1;	/* damage events */
	float angle;
	char buf[256];

    if (ps_open_PostScript() == 0 )
	  {
		fprintf(stderr,"Cannot connect to NeWS server\n");
		exit(1);
      }
	getwd(buf);
	ps_init(buf);

	EHInit();
	GOInit();
	FontInit();
	PropInit();

    mode = STRETCH;
	ps_setcanvas();
    while (!psio_error(PostScriptInput))
	  {

		if(0) ;
		else if(ps_getmode(&newmode))
		  {
			if(mode != newmode)
			  {
				ehprocs[mode].handleend();
				mode = newmode;
				ehprocs[newmode].handlebegin();
			  }
		  }
		else if(ps_getselect(&x0, &y0))
			ehprocs[mode].handleselect(x0, y0);
		else if(ps_getadjust(&x0, &y0))
			ehprocs[mode].handleadjust(x0, y0);
		else if(ps_getkey(&key))
			ehprocs[mode].handlekey(key);
		else if(ps_getcreatepoint(&x1, &y1))
		  {
			ehprocs[mode].handlereply(x0, y0, x1, y1);
		  }
		else if(ps_getcreateangle(&angle))
		  {
				ehprocs[mode].handlereply(angle);
		  }
		else if(ps_getdamage(&dx0, &dy0, &dx1, &dy1))
		  {
			ps_setcanvas();
			ehprocs[mode].handledamage(dx0, dy0, dx1, dy1);
		  }
		else if(ps_getprop(&key))
		  {
			ehprocs[mode].handleprop(key);
		  }
		else
		  {
			fprintf(stderr, "End of program or illegal tag!\n");
			break;
		  }
	  }

    ps_close_PostScript();
	exit(0);
  }
SHAR_EOF
fi
if test -f 'item.c'
then
	echo shar: "will not over-write existing file 'item.c'"
else
cat << \SHAR_EOF > 'item.c'
/* $Header: item.c,v 1.4 88/12/02 10:43:32 bvs Exp $ */
/* Copyright (C) 1988 by Sun Microsystems. All rights reserved. */

#include <stdio.h>
#include <math.h>
#include "go.h"
#include "gopvt.h"

extern PROP *GOItemProp();
extern ITEM *GOItemRotatedBounds();
static ITEM *plist;

int GOItemType(pitem) ITEM *pitem; { return(pitem->type); }

GOItemInit()
  {
	plist = (ITEM *)malloc(sizeof(ITEM));
	plist->pnext = plist;
	plist->pprev = plist;
  }
GOItemReInit()
  {
	GOItemInit();
  }

ITEM *GOItemAddToTop(pitem)
ITEM *pitem;
  {
	pitem->pprev = plist;
	pitem->pnext = plist->pnext; 
	plist->pnext->pprev = pitem; 
	plist->pnext = pitem; 
	return(pitem);
  }
ITEM *GOItemAddToBottom(pitem)
ITEM *pitem;
  {
	pitem->pprev = plist->pprev;
	pitem->pnext = plist; 
	plist->pprev->pnext = pitem; 
	plist->pprev = pitem; 
	return(pitem);
  }
ITEM *GOItemDelete(pitem)
ITEM *pitem;
  {
	pitem->pprev->pnext = pitem->pnext;
	pitem->pnext->pprev = pitem->pprev;
	pitem->pnext = (ITEM *)0;
	pitem->pprev = (ITEM *)0;
	return(pitem);
  }
ITEM *GODrawItem(pitem)
ITEM *pitem;
  {
	int x = (X0 + X1)/2;
	int y = (Y0 + Y1)/2;
	ps_dorotate(x, y, pitem->rotation);
	goprocs[pitem->type].draw(pitem);
	ps_unrotate();
	return(pitem);
  }
int GOPointInItem(pitem, x, y)
ITEM *pitem;
int x;
int y;
  {
	int x0 = X0;
	int x1 = X1;
	int y0 = Y0;
	int y1 = Y1;
	int xpt = x;
	int ypt = y;
	/* make sure we're at least 5 units wide! */
	if((x1 - x0) < 5) { x0--; x1++; }
	if((x1 - x0) < 5) { x0--; x1++; }
	if((x1 - x0) < 5) { x0--; x1++; }
	if((y1 - y0) < 5) { y0--; y1++; }
	if((y1 - y0) < 5) { y0--; y1++; }
	if((y1 - y0) < 5) { y0--; y1++; }
	if(pitem->rotation != 0.0)
	  {
		int xc = (x0 + x1)/2;
		int yc = (y0 + y1)/2;
		double fcos, fsin;

		sincos((double)(-pitem->rotation) / 180.0 *  M_PI, &fsin, &fcos);

		xpt = ((x - xc) * fcos) - ((y - yc) * fsin) + xc;
		ypt = ((x - xc) * fsin) + ((y - yc) * fcos) + yc;
	  }
	if((x0 <= xpt) && (x1 >= xpt) && (y0 <= ypt) && (y1 >= ypt))
		{
		  /* More detailed check... */
		  return(1);
		}
	else
		return(0);
  }

int GOItemInRect(pitem, x0, y0, x1, y1)
ITEM *pitem;
int x0, y0, x1, y1;
  {
	int xmin = MIN(X0, X1);
	int xmax = MAX(X0, X1);
	int ymin = MIN(Y0, Y1);
	int ymax = MAX(Y0, Y1);
	if(pitem->rotation != 0.0)
	  {
		GOItemRotatedBounds(pitem, &xmin, &ymin, &xmax, &ymax);
	  }
	if( (x0 > xmax) || (x1 < xmin) || (y0 > ymax) || (y1 < ymin) )
	  {
		return(0);
	  }
	else
		return(1);
  }
ITEM *GOPrintItem(pitem, pfile)
ITEM *pitem;
FILE *pfile;
  {
	if(pitem->rotation != 0.0)
	  {
		fprintf(pfile, "matrix currentmatrix ");
		fprintf(pfile, "%d %d translate ", X, Y);
		fprintf(pfile, "%f rotate ", pitem->rotation);
		fprintf(pfile, "%d %d translate\n", -X, -Y);
		goprocs[pitem->type].print(pitem, pfile);
		fprintf(pfile, "setmatrix\n");
	  }
	else
		goprocs[pitem->type].print(pitem, pfile);
	return(pitem);
  }
ITEM *GOWriteItem(pitem, pfile)
ITEM *pitem;
FILE *pfile;
  {
	fprintf(pfile, "type %d\n", pitem->type);
	PropWrite(GOItemProp(pitem), pfile);
	fprintf(pfile, "%d %d %d %d %f %d %d\n",
		pitem->x0,
		pitem->y0,
		pitem->x1,
		pitem->y1,
		pitem->rotation,
		pitem->xscale,
		pitem->yscale
		);
	goprocs[pitem->type].write(pitem, pfile);
	return(pitem);
  }
ITEM *GOReadItem(pfile)
FILE *pfile;
  {
	int ret;
	int type;
	ITEM *pitem;

	if(feof(pfile))
		return((ITEM *)0);
	  
	if(1 != fscanf(pfile, "type %d\n", &type))
	  {
		fprintf(stderr, "Bad read of item\n");
		return((ITEM *)0);
	  }

	if(type == -1)
		return((ITEM *)0);

	pitem	= (ITEM *)goprocs[type].holder();
	pitem->type = type;
	pitem->prop = PropRead(pfile);
	if(pitem->prop == 0)
	  {
		return((ITEM *)0);
	  }

	/* fprintf(stderr, "reading item type: %d\n", type); */
	ret = fscanf(pfile, "%d %d %d %d %f %d %d\n",
		&pitem->x0,
		&pitem->y0,
		&pitem->x1,
		&pitem->y1,
		&pitem->rotation,
		&pitem->xscale,
		&pitem->yscale
		);
	if(ret != 7)
	  {
		fprintf(stderr, "Bad item type %d read...\n", type);
		return((ITEM *)0);
	  }
	goprocs[type].read(pitem, pfile);
	return(pitem);
  }

PROP * GOItemProp(pitem)
ITEM *pitem;
  {
	return(pitem->prop);
  }

ITEM * GOItemSetProp(pitem, prop)
ITEM *pitem;
PROP *prop;
  {
	pitem->prop = prop;
	return(pitem);
  }


ITEM *GOItemMove(pitem, dx, dy)
ITEM *pitem;
int dx, dy;
  {
	pitem->x0 += dx;
	pitem->x1 += dx;
	pitem->y0 += dy;
	pitem->y1 += dy;
	return(pitem);
  }
ITEM *GOItemSetRotation(pitem, angle)
ITEM *pitem;
float angle;
  {
	pitem->rotation = angle;
	return(pitem);
  }
float GOItemGetRotation(pitem)
ITEM *pitem;
  {
	return (float)pitem->rotation;
  }

minmax4(pmin, pmax, in1, in2, in3, in4)
int *pmin, *pmax;
int in1, in2, in3, in4;
  {
	*pmin = MIN( MIN(in1, in2), MIN(in3, in4));
	*pmax = MAX( MAX(in1, in2), MAX(in3, in4));
  }
ITEM *GOItemUnrotatedBounds(pitem, px0, py0, px1, py1)
ITEM *pitem;
int *px0, *py0, *px1, *py1;
  {
	int width = PropLineWidth(pitem->prop);
	*px0 = MIN(X0, X1) - width;
	*py0 = MIN(Y0, Y1) - width;
	*px1 = MAX(X0, X1) + width;
	*py1 = MAX(Y0, Y1) + width;
	return(pitem);
  }
ITEM *GOItemRotatedBounds(pitem, px0, py0, px1, py1)
ITEM *pitem;
int *px0, *py0, *px1, *py1;
  {
	if(pitem->rotation != 0.0)
	  {
		int width = PropLineWidth(pitem->prop);
		int xc = (X0 + X1 + 1)/2;
		int yc = (Y0 + Y1 + 1)/2;
		double fsin, fcos;
		int dx1, dy1, dx2, dy2;
		sincos((double)(pitem->rotation) / 180.0 *  M_PI, &fsin, &fcos);
		dx1 = ((X1 - xc) * fcos) - ((Y0 - yc) * fsin);
		dx2 = ((X1 - xc) * fcos) - ((Y1 - yc) * fsin);
		dy1 = ((X1 - xc) * fsin) + ((Y0 - yc) * fcos);
		dy2 = ((X1 - xc) * fsin) + ((Y1 - yc) * fcos);

		*px0 = xc - MAX( ABS(dx1), ABS(dx2) ) - width;
		*py0 = yc - MAX( ABS(dy1), ABS(dy2) ) - width;

		*px1 = xc + MAX( ABS(dx1), ABS(dx2) ) + width;
		*py1 = yc + MAX( ABS(dy1), ABS(dy2) ) + width;
	  }
	else
		GOItemUnrotatedBounds(pitem, px0, py0, px1, py1);
	return(pitem);
  }
ITEM *GOItemMaxBounds(pitem, px0, py0, px1, py1)
ITEM *pitem;
int *px0, *py0, *px1, *py1;
  {
	/* just do a rough calculation */
	int width = PropLineWidth(pitem->prop);
	int xc = (X0 + X1 + 1)/2;
	int yc = (Y0 + Y1 + 1)/2;
	int radius = (int)((MAX( ABS(X0 - X1), ABS(Y0 - Y1) ) + 1) * .75);
	radius += width;	/* this should really be the linewidth */
	*px0 = xc - radius;
	*px1 = xc + radius;
	*py0 = yc - radius;
	*py1 = yc + radius;
	return(pitem);
  }

ITEM *GOFindItem(x, y)
int x, y;
  {
	ITEM *pitem;
	for(pitem = plist->pnext; pitem != plist; pitem = pitem->pnext)
	  {
		if(GOPointInItem(pitem, x, y))
			  return(pitem);
	  }
  	return((ITEM *)0);
  }

GORepairItems(x0, y0, x1, y1)
  {
	ITEM *pitem;
	ps_pushclip(x0, y0, x1, y1);
	ps_setgray(1.0);
	ps_drawrect(x0, y0, x1, y1);
	ps_fill();
	for(pitem = plist->pprev; pitem != plist; pitem = pitem->pprev)
	  {
		if(GOItemInRect(pitem, x0, y0, x1, y1))
			GODrawItem(pitem);
	  }
	ps_popclip();
  }
GODrawItems()
  {
	ITEM *pitem;
	for(pitem = plist->pprev; pitem != plist; pitem = pitem->pprev)
		GODrawItem(pitem);
  }
GOBoundsItems(px0, py0, px1, py1)
int *px0, *py0, *px1, *py1;
  {
	ITEM *pitem = plist->pprev;
	int x0 = X0;
	int y0 = Y0;
	int x1 = X1;
	int y1 = Y1;
	for(pitem = plist->pprev; pitem != plist; pitem = pitem->pprev)
	  {
		x0 = MIN(x0, X0);
		y0 = MIN(y0, Y0);
		x1 = MAX(x1, X1);
		y1 = MAX(y1, Y1);
	  }
	*px0 = x0;		
	*py0 = y0;		
	*px1 = x1;		
	*py1 = y1;		
  }
GOPrintItems(pfile)
FILE *pfile;
  {
	ITEM *pitem;
	for(pitem = plist->pprev; pitem != plist; pitem = pitem->pprev)
		GOPrintItem(pitem, pfile);
  }
GOWriteItems(pfile)
FILE *pfile;
  {
	ITEM *pitem;
	for(pitem = plist->pprev; pitem != plist; pitem = pitem->pprev)
	  {
		GOWriteItem(pitem, pfile);
	  }
	fprintf(pfile, "type %d\n", -1);
  }
GOReadItems(pfile)
FILE *pfile;
  {
	ITEM *pitem;
	GOItemReInit();
	while(pitem = GOReadItem(pfile))
	  {
	 	GOItemAddToTop(pitem);
	  }
	GORepairItems(-1000, -1000, 1000, 1000);
  }

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

static void *nullproc()
  {
  }
static void *nullselect(x, y)
int x, y;
  {
	fprintf(stderr, "Select not implemented for current mode\n");
  }
static void *nulladjust(x, y)
int x, y;
  {
	fprintf(stderr, "Adjust not implemented for current mode\n");
  }
static void *nullkey(c)
int c;
  {
	fprintf(stderr, "Keystroke not implemented for current mode\n");
  }
static void *nullreply(c)
int c;
  {
	fprintf(stderr, "Reply not implemented for current mode\n");
  }
static void *handleprop(c)
int c;
  {
	if(PropHandle(c) == FALSE)
		fprintf(stderr, "Unable to handle action/property %d\n", c);
  }
static void *handledamage(x0, y0, x1, y1)
int x0, y0, x1, y1;
  {
	GORepairItems(x0, y0, x1, y1);
  }
static void *nullbegin() { }
static void *nullend() { }

EHInit()
  {
	int k;
	for(k=0; k < MODEMAX; k++)
	  {
		ehprocs[k].handleselect	= nullselect;	
		ehprocs[k].handleadjust	= nulladjust;	
		ehprocs[k].handlekey	= nullkey;	
		ehprocs[k].handlereply	= nullreply;	
		ehprocs[k].handledamage = handledamage;	
		ehprocs[k].handlebegin	= nullbegin;	
		ehprocs[k].handleend	= nullend;	
		ehprocs[k].handleprop	= handleprop;	
	  }
	EHLineInit(&ehprocs[LINE]);
	EHPolyInit(&ehprocs[POLY]);
	EHBrushInit(&ehprocs[BRUSH]);
	EHRectInit(&ehprocs[RECT]);
	EHOvalInit(&ehprocs[OVAL]);
	EHCircInit(&ehprocs[CIRC]);
	EHTextInit(&ehprocs[TEXT]);
	EHStretchInit(&ehprocs[STRETCH]);
	EHRotateInit(&ehprocs[ROTATE]);
  }
SHAR_EOF
fi
if test -f 'font.c'
then
	echo shar: "will not over-write existing file 'font.c'"
else
cat << \SHAR_EOF > 'font.c'
/* $Header: font.c,v 1.2 88/12/02 10:43:43 bvs Exp $ */
/* Copyright (C) 1988 by Sun Microsystems. All rights reserved. */
#include <stdio.h>
#include "psint.h"

typedef struct {
	char *name;		/* family name */
	int id;			/* id token */
	int size;		/* point size  */
	int height;		/* heighest ascender to lowest descender */
	int descent;	/* lowest descender to baseline */
	int count;		/* chars in font */
	int *awidths;	/* array of char width info */
} FONT;

FONT *SetFont();

static FONT font;

FontInit()
  {
	SetFont("Times-Roman", 48);
  }

FONT *FontDefault() { return(&font); }
FONT *SetFont(name, size)
char *name;
int	size;
{
	int count, height, descent;
    int index = ps_next_user_token++;
    int i;
	FONT *pf = &font;
    ps_fontsetup(name, size, index, &count, &height, &descent);

    pf->size = size;
    pf->id = index;
    pf->count = count >> 1;
    pf->height = height;
    pf->descent = descent < 0 ? -descent : descent;
    pf->name = (char *)malloc(strlen(name));
    strcpy(pf->name, name);

	printf("font %s: id %d, count %d, height %d, descent %d\n",
		pf->name, pf->id, pf->count, pf->height, pf->descent);
	pf->awidths = (int *)malloc(pf->count * sizeof(int));
    for(i = pf->count - 1; i >= 0; --i)
	  {
		ps_getint(&pf->awidths[i]);
		/* printf("char %c (%x), width %d\n", i, i, pf->awidths[i]); */
	  }
    return pf;
}

FontDescent(pfont) FONT *pfont; { return(pfont->descent); }
FontHeight(pfont) FONT *pfont; { return(pfont->height); }
FontAscent(pfont) FONT *pfont; { return(pfont->height - pfont->descent); }

int FontTextWidth(pfont, ptext)
FONT *pfont;
char *ptext;
  {
	int w = 0;
	char *pc;
	for(pc = ptext; *pc; pc++)
	  {
		w += pfont->awidths[*pc];
	  }
	return(w);
  }
SHAR_EOF
fi
if test -f 'go.c'
then
	echo shar: "will not over-write existing file 'go.c'"
else
cat << \SHAR_EOF > 'go.c'
/* $Header: go.c,v 1.3 88/12/02 10:43:21 bvs Exp $ */
/* Copyright (C) 1988 by Sun Microsystems. All rights reserved. */
#include <stdio.h>
#include "draw.h"
#include "go.h"
#include "psio.h"
#include "psint.h"

static void *nullreadwrite(pitem, pfile)
ITEM *pitem;
FILE *pfile;
  {
  }
static void *nullproc()
  {
  }
static void *errorproc()
  {
	fprintf(stderr, "No object/method for current mode\n");
  }

GOInit()
  {
	int k;
	for(k=0; k < MODEMAX; k++)
	  {
		goprocs[k].holder	= errorproc;	
		goprocs[k].new		= errorproc;	
		goprocs[k].move		= errorproc;	
		goprocs[k].rotate	= errorproc;	
		goprocs[k].scale	= errorproc;	
		goprocs[k].setpath	= errorproc;	
		goprocs[k].draw		= errorproc;	
		goprocs[k].print	= errorproc;	
		goprocs[k].write	= nullreadwrite;	
		goprocs[k].read		= nullreadwrite;	
	  }
	GOItemInit();
	GOLineInit(&goprocs[LINE]);
	GORectInit(&goprocs[RECT]);
	GOOvalInit(&goprocs[OVAL]);
	GOCircInit(&goprocs[CIRC]);
	GOTextInit(&goprocs[TEXT]);
	GOPolyInit(&goprocs[POLY]);
	GOBrushInit(&goprocs[BRUSH]);
  }
SHAR_EOF
fi
if test -f 'file.c'
then
	echo shar: "will not over-write existing file 'file.c'"
else
cat << \SHAR_EOF > 'file.c'
/* $Header: file.c,v 1.4 88/12/02 10:43:11 bvs Exp $ */
/* Copyright (C) 1988 by Sun Microsystems. All rights reserved. */
#include <stdio.h>

#define PRINTFILE "file.ps"
Print()
  {
	FILE *pfile = fopen("newsdraw.ps", "w");

	fprintf(pfile, "%%!\n");
	fprintf(pfile, "%%%%!PS-Adobe-1.0\n");
	fprintf(pfile, "%%%%Creator: NewsDraw\n");
	fprintf(pfile, "%%%%Title: \n");
	fprintf(pfile, "%%%%CreationDate: \n");
	fprintf(pfile, "%%%%DocumentFonts: Times-Roman\n");
	fprintf(pfile, "%%%%Pages: (atend)\n");
	fprintf(pfile, "%%%%EndComments\n");
	fprintf(pfile, "%%\n%%\n%%\n");

	fprintf(pfile, "/Times-Roman findfont 36 scalefont setfont\n");
	fprintf(pfile, "/rect {dup 0 exch rlineto exch 0 rlineto neg 0 exch rlineto closepath } def\n");
	fprintf(pfile, "/rectpath { 4 2 roll moveto rect } def\n");
	fprintf(pfile, "/linepath { moveto lineto } def\n");
	fprintf(pfile, "/circpath { 0 360 arc } def\n");
	fprintf(pfile, "/ovalpath {  matrix currentmatrix 5 1 roll 4 2 roll translate scale .5 .5 translate 0 0 .5 0 360 arc closepath setmatrix } def\n");
	fprintf(pfile, "%%%%EndProlog\n");
	fprintf(pfile, "%%%%Page: ? 1\n");

	GOPrintItems(pfile);
	fprintf(pfile, "showpage\n");

	fprintf(pfile, "%%%%Pages: 1\n");

	fclose(pfile);

	/* system("lpr .drawprint"); */
  }

#define WRITEFILE "file.nd"
Write()
  {
	FILE *pfile = fopen(WRITEFILE, "w");
	GOWriteItems(pfile);
	fclose(pfile);
  }

Read()
  {
	FILE *pfile = fopen(WRITEFILE, "r");

	GOReadItems(pfile);
	fclose(pfile);
  }

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

typedef struct prop {
	int		linewidth;
	float	strokecolor;
	float	fillcolor;
	float	textcolor;
	FONT	*pfont;
};

static PROP *propcurrent;
static PROP *proplast;

PROP *PropNew();

PropInit()
  {
	proplast	= (PROP *)0;
	propcurrent	= PropNew();
	propcurrent->linewidth		= 1;
	propcurrent->strokecolor	= 0.0;
	propcurrent->fillcolor		= .75;
	propcurrent->textcolor		= 0.0;
	propcurrent->pfont			= FontDefault();
  }

PROP *PropCopyOf(prop)
PROP *prop;
  {
	PROP *propNew = PropNew();
	*propNew = *prop;
	return(propNew);
  }

PROP *PropNew()
  {
	return((PROP *)malloc(sizeof(PROP)));
  }

PROP *PropSetCurrent(prop)
PROP *prop;
  {
	*propcurrent = *prop;
	return(prop);
  }

PROP *PropCurrent()
  {
	return(propcurrent);
  }

int PropHandle(id) /* actually returns boolean */
int id;
  {
	int handled = TRUE;
	switch(id)
	  {
		default:
			handled = FALSE;
			break;

		/* properties */
		case FILL_KEY:
			ps_getfloat(&propcurrent->fillcolor);
			break;
		case STROKE_KEY:
			ps_getfloat(&propcurrent->strokecolor);
			break;
		case TEXT_KEY:
			ps_getfloat(&propcurrent->textcolor);
			break;
		case WIDTH_KEY:
			ps_getint(&propcurrent->linewidth);
			break;

		case PRINT_KEY:
			Print();
			break;
		case WRITE_KEY:
			Write();
			break;
		case READ_KEY:
			Read();
			break;
		case REDRAW_KEY:
			GODrawItems();
			break;
	  }
	return(handled);
  }

float PropStrokeColor(prop) PROP *prop; { return(prop->strokecolor); }
float PropFillColor(prop) PROP *prop; { return(prop->fillcolor); }
float PropTextColor(prop) PROP *prop; { return(prop->textcolor); }
int   PropLineWidth(prop) PROP *prop; { return(prop->linewidth); }
FONT *PropFont(prop) PROP *prop; { return(prop->pfont); }

PropWrite(prop, pfile)
PROP *prop;
FILE *pfile;
  {
	fprintf(pfile, "PROPS %d %f %f %f\n",
		prop->linewidth,
		prop->strokecolor,
		prop->fillcolor,
		prop->textcolor);
  }

PROP *PropRead(pfile)
FILE *pfile;
  {
	PROP *prop = PropNew();
	int ret = fscanf(pfile, "PROPS %d %f %f %f\n",
		&prop->linewidth,
		&prop->strokecolor,
		&prop->fillcolor,
		&prop->textcolor);
	prop->pfont			= FontDefault();
	if(ret != 4)
	  {
		fprintf("bad prop read...\n");
	  }
	return(prop);
  }

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

#include <stdio.h>
#include "draw.h"
#include "go.h"
#include "psio.h"
#include "psint.h"
#include "comm.h"

static ITEM  *pcurrent = (ITEM *)0;

static ITEM *SRSelectItem();
static ITEM *SRDeselectItem();
static void *StretchMoveReply();

#define B 3		/* selection border */
#define B1 2	/* selection border inner */

/* shared stretch/rotate stuff */
static void *SRBegin()
  {
	ps_stdcursor();
  }
static void *SREnd()
  {
	if(pcurrent)
		SRDeselectItem(pcurrent);
	pcurrent = (ITEM *)0;
  }
static void *SRProp(c)
int c;
  {
	ITEM *pitem = pcurrent;
	if(pitem)
		SRDeselectItem(pitem);

	PropHandle(c);

	/* this should be in action handle! */
	if(pitem)
	  {
		if(c == TOTOP_KEY)
		  {
			GOItemDelete(pitem);
			GOItemAddToTop(pitem);
		  }
		if(c == TOBOT_KEY)
		  {
			GOItemDelete(pitem);
			GOItemAddToBottom(pitem);
		  }
	  }

	/* set property on selected item */
	if(pitem)
	  {
		int x0, x1, y0, y1;
		GOItemSetProp(pitem, PropCopyOf(PropCurrent()));
		GOItemRotatedBounds(pitem, &x0, &y0, &x1, &y1);
		GORepairItems(x0 - 10, y0 - 10, x1 + 10, y1 + 10);	/* 10 hack */
		SRSelectItem(pitem);
	  }
  }
static void *SRAdjust(x, y)
int x,y;
  {
  }
static void *SRKey(key)
int key;
  {
	int x0, x1, y0, y1;

	if(pcurrent)
	  {
		if((key == 0177) || (key = 10)) /* delete or BS key */
		  {
			GOItemDelete(pcurrent);
			GOItemRotatedBounds(pcurrent, &x0, &y0, &x1, &y1);
			GORepairItems(x0 - B, y0 - B, x1 + B, y1 + B);
			/* GOFreeItem(pcurrent); */
			pcurrent = (ITEM *)0;
		  }
	  }
  }

/* stretch selection */
static void *StretchSelect(x, y)
int x,y;
  {
	ITEM *pfound = (ITEM *)GOFindItem(x, y);
	if((pcurrent) && (pcurrent == pfound))
	  {
		/* move or stretch */
		int x0, y0, x1, y1;
		int bL, bT, bB, bR;
		int type = GOItemType(pcurrent);
		GOItemUnrotatedBounds(pcurrent, &x0, &y0, &x1, &y1);

		bT = bB = bL = bR = 0;
		if(x < (x0 + B)) bL = 1;
		if(y < (y0 + B)) bB = 1;
		if(x > (x1 - B)) bR = 1;
		if(y > (y1 - B)) bT = 1;

		if     (bL && bT)
			ehprocs[type].handleselect(x1, y0);
		else if(bL && bB)
			ehprocs[type].handleselect(x1, y1);
		else if(bR && bT)
			ehprocs[type].handleselect(x0, y0);
		else if(bR && bB)
			ehprocs[type].handleselect(x0, y1);
		else
		  {
			ehprocs[STRETCH].handlereply	= StretchMoveReply;	
			ps_moveinteractive(x, y,
				GOItemGetRotation(pcurrent), x0, y0, x1, y1);
		  }
	  }
	else
	  {
		if(pcurrent)
			SRDeselectItem(pcurrent);

		pcurrent = pfound;
		if(pcurrent)
			SRSelectItem(pcurrent);
	  }
  }
static void *StretchMoveReply(xstart, ystart, xend, yend)
int xstart, ystart, xend, yend;
  {
	int x0, y0, x1, y1;
	int s0, t0, s1, t1;
	GOItemRotatedBounds(pcurrent, &x0, &y0, &x1, &y1);
	GOItemMove(pcurrent, xend - xstart, yend - ystart);
	GOItemRotatedBounds(pcurrent, &s0, &t0, &s1, &t1);

	if((x0 > s1) || (x1 < s0) || (y0 > t1) || (y1 < t0)) 
	  {
		/* no intersection */
		/* printf("no intersect\n"); */
		GORepairItems(x0 - B, y0 - B, x1 + B, y1 + B);
		GORepairItems(s0, t0, s1, t1);
	  }
	else
	  {
		/* the regions intersect */
		/* printf("intersection\n"); */
		GORepairItems(  MIN(s0, x0 - B), MIN(t0, y0 - B),
						MAX(s1, x1 + B), MAX(t1, y1 + B)	);
	  }

	saveareaunderitem(pcurrent);
	GOItemUnrotatedBounds(pcurrent, &x0, &y0, &x1, &y1);
	drawselection(GOItemGetRotation(pcurrent), x0, y0, x1, y1);
  }
EHStretchInit(pprocs)
EHPROCS *pprocs;
  {
	pprocs->handlebegin		= SRBegin;	
	pprocs->handleend		= SREnd;	
	pprocs->handleprop		= SRProp;	
	pprocs->handleselect	= StretchSelect;	
	pprocs->handleadjust	= SRAdjust;	
	pprocs->handlekey		= SRKey;	
  }

/* rotate selection */
static void *RotateSelect(x, y)
int x,y;
  {
	ITEM *pfound = (ITEM *)GOFindItem(x, y);
	if(pcurrent == pfound)
	  {
		/* rotate */
		int x0, y0, x1, y1;
		GOItemUnrotatedBounds(pcurrent, &x0, &y0, &x1, &y1);
		ps_rotateInteractive(
			GOItemGetRotation(pcurrent),
			x, y, (x0 + x1)/2, (y0 + y1)/2, x0, y0, x1, y1);
	  }
	else
	  {
		if(pcurrent)
			SRDeselectItem(pcurrent);

		pcurrent = pfound;
		if(pcurrent)
			SRSelectItem(pcurrent);
	  }
  }
static void *RotateReply(angle)
float angle;
  {
	int x0, y0, x1, y1;
	int s0, t0, s1, t1;
	GOItemRotatedBounds(pcurrent, &x0, &y0, &x1, &y1);
	GOItemSetRotation(pcurrent, angle);
	GOItemRotatedBounds(pcurrent, &s0, &t0, &s1, &t1);
	GORepairItems(
		MIN(x0, s0) - B, MIN(y0, t0) - B,
	 	MAX(x1, s1) + B, MAX(y1, t1) + B);
	saveareaunderitem(pcurrent);
	GOItemUnrotatedBounds(pcurrent, &x0, &y0, &x1, &y1);
	drawselection(angle, x0, y0, x1, y1);
  }
EHRotateInit(pprocs)
EHPROCS *pprocs;
  {
	pprocs->handlebegin		= SRBegin;	
	pprocs->handleend		= SREnd;	
	pprocs->handleprop		= SRProp;	
	pprocs->handlekey		= SRKey;	
	pprocs->handleselect	= RotateSelect;	
	pprocs->handleadjust	= SRAdjust;	
	pprocs->handlereply		= RotateReply;	
  }

/* private stuff */
static ITEM *SRSelectItem(pitem)
ITEM *pitem;
  {
	if(pcurrent)
	  {
		fprintf("GOSelectItem:  Internal error\n");
	  }
	if(pitem)
	  {
		int x0, y0, x1, y1;
		float angle;

		pcurrent = pitem;
		saveareaunderitem(pitem);

		angle = GOItemGetRotation(pitem);
		GOItemUnrotatedBounds(pitem, &x0, &y0, &x1, &y1);
		drawselection(angle, x0, y0, x1, y1);

		PropSetCurrent(GOItemProp(pitem));
	  }
	return(pitem);
  }

static ITEM *SRDeselectItem(pitem)
ITEM *pitem;
  {
	if(!pcurrent)
	  {
		fprintf(stderr, "SRDeselectItem: Internal error\n");
		return(pitem);
	  }
	else
	  {
		ps_restorearea();
	  }
	pcurrent = (ITEM *)0;
	return(pitem);
  }

static drawselection(angle, x0, y0, x1, y1)
float angle;
int x0, y0, x1, y1;
  {
	int x2 = (x0 + x1)/2;
	int y2 = (y0 + y1)/2;

	ps_flush_PostScript();
	ps_dorotate(x2, y2, angle);

	ps_setgray(1.0);
	ps_drawrect(x0 - B, y0 - B, x0 + B, y0 + B);
	ps_drawrect(x1 - B, y0 - B, x1 + B, y0 + B);
	ps_drawrect(x1 - B, y1 - B, x1 + B, y1 + B);
	ps_drawrect(x0 - B, y1 - B, x0 + B, y1 + B);
	ps_drawrect(x0 - B, y2 - B, x0 + B, y2 + B);
	ps_drawrect(x1 - B, y2 - B, x1 + B, y2 + B);
	ps_drawrect(x2 - B, y0 - B, x2 + B, y0 + B);
	ps_drawrect(x2 - B, y1 - B, x2 + B, y1 + B);
	ps_drawrect(x2 - B, y2 - B, x2 + B, y2 + B);
	ps_fill();

	ps_setgray(0.0);
	ps_drawrect(x0 - B1, y0 - B1, x0 + B1, y0 + B1);
	ps_drawrect(x1 - B1, y0 - B1, x1 + B1, y0 + B1);
	ps_drawrect(x1 - B1, y1 - B1, x1 + B1, y1 + B1);
	ps_drawrect(x0 - B1, y1 - B1, x0 + B1, y1 + B1);
	ps_drawrect(x0 - B1, y2 - B1, x0 + B1, y2 + B1);
	ps_drawrect(x1 - B1, y2 - B1, x1 + B1, y2 + B1);
	ps_drawrect(x2 - B1, y0 - B1, x2 + B1, y0 + B1);
	ps_drawrect(x2 - B1, y1 - B1, x2 + B1, y1 + B1);
	ps_drawrect(x2 - B1, y2 - B1, x2 + B1, y2 + B1);
	ps_fill();

	ps_unrotate();
	ps_flush_PostScript();
  }

saveareaunderitem(pitem)
ITEM *pitem;
  {
	int x0, y0, x1, y1;
	GOItemRotatedBounds(pitem, &x0, &y0, &x1, &y1);
	ps_savearea(x0 - B, y0 - B, x1 + B, y1 + B);
	/*printf("save area (%d,%d), (%d,%d)\n", x0 - B, y0 - B, x1 + B, y1 + B);*/
  }
SHAR_EOF
fi
exit 0
#	End of shell archive