#include	"defs.h"
#include	"globals.h"

static ScaledPts dviBBlx, dviBBrx;	/* Bounding box of figure in DVI space */
static ScaledPts dviBBby, dviBBty;
static int32    prevfont;
/*
 * to keep track of prev font before the PUSH and expansion of the special
 */
static int32    ourpushdepth = 0;	/* depth of internal pushes */
static int32    origTexfont = -1;	/* number of TeX font in use before tyling */

static void 
IPUSH()
{
	if (ourpushdepth == 0)	/* first push --> start tyling */
		origTexfont = font[curfont].num;
	else
		prevfont = ourfontnum;
	/* store the internal font number in use at this time */
	cmd1byte(NOP);
	cmd1byte(NOP);		/* our greeting */
	cmd1byte(PUSH);
	ourpushdepth++;
}

static void 
IPOP()
{
	cmd1byte(POP);
	cmd1byte(NOP);
	cmd1byte(NOP);		/* our signature */
	ourpushdepth--;
	if (ourpushdepth < 0)
	{
		complain(ERRREALBAD);
		fprintf(logfile, "Error: too many internal pops\n");
	}
	if (ourpushdepth == 0)
	{			/* we are totally done with tyling for now */
		if (nf > 0)	/* only if it is valid */
			isetfont(origTexfont);
	}
	else
	{
		if (prevfont >= 0)	/* restore that internal font previously in use */
			isetfont(prevfont);
	}
}

char           *
xmalloc(size)
	unsigned int    size;
{
	char           *p;
	char           *malloc PP((unsigned));
	void		exit PP((int));

	if ((p = malloc(size)) == 0)
	{
		fprintf(stderr, "Out of memory!\n");
		exit(1);
	}
	return (p);
}

/*---------------------------------------------*/
Item           *
NewItem(what)
	int             what;
{
	Item           *i;
	Figure         *f;

	if ((i = (Item *) xmalloc(sizeof(Item))) == 0)
		i->nextitem = NULL;
	i->BBlx = 0;
	i->BBby = 0;
	i->BBrx = 0;
	i->BBty = 0;
	i->itemthick = LoVThick;
	i->itemvec = (unsigned) VKCirc;
	i->itempatt = (unsigned) solid;
	i->kind = what;
	switch (what)
	{			/* give defaults */

	case Aline:
		/* blank case */
		break;

	case Aspline:
		i->UU.U2.nsplknots = 0;
		i->UU.U2.dosmarks = 0;
		i->UU.U2.sclosed = false;
		i->UU.U2.spltype = (unsigned) BSPL;
		break;

	case Attspline:
		i->UU.U3.nttknots = 0;
		i->UU.U3.dottmarks = 0;
		i->UU.U3.tspltype = (unsigned) BSPL;
		i->UU.U3.tclosed = false;
		break;

	case Abeam:
		/* blank case */
		break;

	case Atieslur:
		i->UU.U5.ntknots = 0;
		break;

	case Aarc:
		i->UU.U6.narcknots = 0;
		break;

	case Alabel:
		i->UU.U7.fontstyle = -1;	/* undefined */
		i->UU.U7.labeltext[0] = '\0';
		break;

	case Afigure:
		i->UU.U8.figtheta = 0.0;
		i->UU.U8.fsx = 1.0;
		i->UU.U8.fsy = 1.0;
		i->UU.U8.fdx = 0;
		i->UU.U8.fdy = 0;
		i->UU.U8.preWid = 0;
		i->UU.U8.preHt = 0;
		i->UU.U8.postWid = 0;
		i->UU.U8.postHt = 0;
		i->UU.U8.depthnumber = 0;	/* for now */
		f = (Figure *) xmalloc(sizeof(Figure));	/* a new figure */
		i->UU.U8.body = f;
		i->UU.U8.body->things = NULL;
		break;
	}			/* case */
	/* with */
	return i;
}				/* NewItem */

/*-----------------------------------------------------*/
static void 
TylBeam(fromx, fromy, tox, toy, staffsize, kind)
	int32           fromx, fromy, tox, toy, staffsize;
	BeamKind        kind;
{
	/*
	 * fromx, fromy, tox, toy: ScaledPts; staffsize : integer; kind : BeamKind
	 */
}				/* TylBeam */


/* Local variables for TylLine: */
struct LOC_TylLine
{
	VThickness      thickness;
};


/*-------------------------------------------------------*/
static void 
TylLine(xl, yb, xr, yt, thickness_, vec, patt)
	int32           xl, yb, xr, yt;
	VThickness      thickness_;
	VectKind        vec;
	LineStyle       patt;
{
	/*
	 * xl, yb, xr, yt: ScaledPoints; thickness: VThickness; vec: VectKind; patt : LineStyle
	 */
	struct LOC_TylLine V;
	VecIndex        findex;

	V.thickness = thickness_;
	/*
	 * p2c: x.p, line 6596: Note: Taking & of possibly promoted param thickness [324]
	 */
	clampthickness(&V.thickness);
	findex = GetVectFont(V.thickness, vec);
	layline(xl, yb, xr, yt, findex, patt, false);
}

/*-----------------------------------------------------*/
static void 
TylThickThinSpline(thetype, isclosed, KnotArray, ThikThinAry,
		   numknots, vec, patt, domarks)
	SplineKind      thetype;
	int		isclosed;
int32(*KnotArray)[2];
	VThickness     *ThikThinAry;
	int32           numknots;
	VectKind        vec;
	LineStyle       patt;
	int32           domarks;
{
	/*
	 * thetype : SplineKind; isclosed : boolean; var KnotArray: ControlPoints; var ThikThinAry: ThickAryType; numknots:
	 * integer; vec: VectKind; patt : LineStyle; domarks : integer
	 */
	layNspline(thetype, isclosed, false, domarks, KnotArray, numknots,
		   ThikThinAry, vec, patt);
}

/*----------------------------------------------------*/
static void 
TylSpline(thetype, isclosed, KnotArray, numknots, thick, vec,
	  patt, domarks)
	SplineKind      thetype;
	int		isclosed;
int32(*KnotArray)[2];
	int32           numknots;
	VThickness      thick;
	VectKind        vec;
	LineStyle       patt;
	int32           domarks;
{
	/*
	 * thetype : SplineKind; isclosed : boolean; var KnotArray: ControlPoints; numknots: integer; thick: VThickness; vec:
	 * VectKind; patt : LineStyle; domarks : integer
	 */
	layAspline(thetype, isclosed, false, domarks, KnotArray, numknots, thick,
		   vec, patt);
}

#define ItsASlur        true
#define NotClosed       false


/* Local variables for TylTieSlur: */
struct LOC_TylTieSlur
{
	VThickness      minthick, maxthick;
};


/*-----------------------------------------------------*/
static void 
TylTieSlur(KnotArray, numknots, minthick_, maxthick_)
int32(*KnotArray)[2];
	int32           numknots;
	VThickness      minthick_, maxthick_;
{
	/*
	 * KnotArray: ControlPoints; numknots: integer; minthick, maxthick: VThickness
	 */
	struct LOC_TylTieSlur V;
	ThickAryType    ourttarray;
	double          one7th;
	VThickness      val;

	V.minthick = minthick_;
	V.maxthick = maxthick_;
	/*
	 * p2c: x.p, line 6636: Note: Taking & of possibly promoted param minthick [324]
	 */
	clampthickness(&V.minthick);
	/*
	 * p2c: x.p, line 6637: Note: Taking & of possibly promoted param maxthick [324]
	 */
	clampthickness(&V.maxthick);
	if (numknots != 5)
		fprintf(logfile, "TieSlur needs 5 control points\n");
	one7th = 1.0 / 7.0;
	val = (int32) floor(one7th * (V.maxthick - V.minthick) + 0.5);
	ourttarray[1] = V.minthick;
	ourttarray[2] = V.minthick + val;
	ourttarray[3] = V.maxthick;
	ourttarray[4] = V.minthick + val;
	ourttarray[5] = V.minthick;

	layNspline(CATROM, NotClosed, ItsASlur, 0, KnotArray, numknots, ourttarray,
		   VKCirc, solid);
}

#undef ItsASlur
#undef NotClosed


#define ItsAnArc        true


/*-------------------------------------------------------*/
static void 
doTylArc(iscircle, apts, numknots, thick, vec, patt)
	int		iscircle;
int32(*apts)[2];
	int32           numknots;
	VThickness      thick;
	VectKind        vec;
	LineStyle       patt;
{
	/*
	 * iscircle : boolean; var apts : ControlPoints; numknots : integer; thick : VThickness; vec : VectKind; patt :
	 * LineStyle
	 */
	layAspline(BSPL, iscircle, ItsAnArc, 0, apts, numknots, thick, vec, patt);
}

#undef ItsAnArc


/*-----------------------------------------------------------*/
static void 
TylArc(radius, centx, centy, firstangle, secondangle, thick, vec,
       patt)
	int32           radius, centx, centy, firstangle, secondangle;
	VThickness      thick;
	VectKind        vec;
	LineStyle       patt;
{
	/*
	 * radius : ScaledPts; centx, centy : ScaledPts; firstangle, secondangle : integer; thick : VThickness; vec : VectKind;
	 * patt : LineStyle
	 */
	ControlPoints   apts;
	int32           numknots;
	int		iscircle;

	iscircle = (firstangle == secondangle);
	if (iscircle)
	{
		/*
		 * maxspan := round ((360.0 / 16.0) * DEGTORAD * radius); {
		 */
		defineCircleCpts(radius, centx, centy, apts, &numknots);
	}
	else
	{
		/*
		 * maxspan := round ((abs (secondangle - firstangle) / 16.0) * DEGTORAD * radius); {
		 */
		definearcpts(radius, centx, centy, firstangle, secondangle, apts,
			     &numknots);
	}

	doTylArc(iscircle, apts, numknots, thick, vec, patt);

}


/*-----------------------------------------------------------*/
static void 
TylLabel(xpos, ypos, fontstyle, phrase, phraselen)
	int32           xpos, ypos, fontstyle;
	char           *phrase;
	int32           phraselen;
{
	/*
	 * xpos, ypos : ScaledPts; fontstyle : integer; phrase : charstring; phraselen : integer
	 */
	int32           findex, c, spaceover;

	if (fontstyle < 1 || fontstyle > MAXLABELFONTS)
	{
		complain(ERRREALBAD);
		fprintf(logfile, "Unexpected bad fontstyle in TylLabel: %d?\n",
			fontstyle);
		jumpout();
	}
	findex = GetLabFont(fontstyle);
	isetpos(xpos, ypos);
	IPUSH();
	isetfont(LFontTable[findex - 1]->DVIFontNum);
	spaceover = LFontTable[findex - 1]->spacewidth;
	for (c = 0; c < phraselen; c++)
	{
		if (phrase[c] != ' ')
		{
			cmd1byte(SET1);
			cmd1byte(phrase[c]);
		}
		else
		{		/* move over */
			cmd1byte(RIGHTLEFT + 2);
			/* assume distance is less than 3 bytes */
			cmdSigned(spaceover, 3);
		}
	}
	IPOP();
}

/* &&module TeXtyl */
/*----------------------------------------------------------------*/
/* rotate a (x,y) point about mx, my */
static void 
ptrotate(x, y, mx, my, angle)
	int32          *x, *y, mx, my;
	double          angle;
{
	int32           tmpx, tmpy;
	double          cosa, sina;

	tmpx = *x - mx;
	tmpy = *y - my;
	cosa = cos(angle * DEGTORAD);
	sina = sin(angle * DEGTORAD);
	*x = (int32) floor(tmpx * cosa - tmpy * sina + 0.5) + mx;
	*y = (int32) floor(tmpx * sina + tmpy * cosa + 0.5) + my;
}


/*----------------------------------------------------------------*/
/*
 * transform two line points: scale, rotate and translate
 */
static void 
xfmlinepts(x1, y1, x2, y2, offh, offv, midx, midy, scalefact,
	   theta, dx, dy, sx, sy)
	int32          *x1, *y1, *x2, *y2, offh, offv, midx, midy;
	double          scalefact, theta;
	int32           dx, dy;
	double          sx, sy;
{
	if (sx == 0.0 || sy == 0.0)
	{
		complain(ERRBAD);
		fprintf(logfile, "?? Some scale factor is Zero... continuing anyway\n");
	}
	/* scale about center of item */
	if (sx != 1.0 || sy != 1.0)
	{
		*x1 = (int32) floor((*x1 - midx) * sx + 0.5) + midx;
		*x2 = (int32) floor((*x2 - midx) * sx + 0.5) + midx;
		*y1 = (int32) floor((*y1 - midy) * sy + 0.5) + midy;
		*y2 = (int32) floor((*y2 - midy) * sy + 0.5) + midy;
	}
	/* rotate if necessary */
	if (theta != 0.0)
	{			/* rotate about the midpoint */
		ptrotate(x1, y1, midx, midy, theta);
		ptrotate(x2, y2, midx, midy, theta);
	}
	/* translate */
	*x1 += (int32) floor(dx * scalefact + 0.5) + offh;
	*x2 += (int32) floor(dx * scalefact + 0.5) + offh;
	*y1 += (int32) floor(dy * scalefact + 0.5) + offv;
	*y2 += (int32) floor(dy * scalefact + 0.5) + offv;
}				/* xfmlinepts */


/*----------------------------------------------------------------*/
static void 
xfmcontpts(xpts, xknots, offh, offv, midx, midy, scalefact, theta,
	   dx, dy, sx, sy)
int32(*xpts)[2];
	int32           xknots, offh, offv, midx, midy;
	double          scalefact, theta;
	int32           dx, dy;
	double          sx, sy;
{
	int32           i;

	/* scale about center of item */
	if (sx != 1.0 || sy != 1.0)
	{
		for (i = 0; i <= xknots; i++)
		{
			xpts[i][0] = (int32) floor((xpts[i][0] - midx) * sx + 0.5) + midx;
			xpts[i][1] = (int32) floor((xpts[i][1] - midy) * sy + 0.5) + midy;
		}
	}

	if (theta != 0.0)
	{			/* rotate about center */
		for (i = 0; i <= xknots; i++)
			ptrotate(xpts[i], &xpts[i][1], midx, midy, theta);
	}
	/* translate */
	for (i = 0; i <= xknots; i++)
	{
		xpts[i][0] += (int32) floor(dx * scalefact + 0.5) + offh;
		xpts[i][1] += (int32) floor(dy * scalefact + 0.5) + offv;
	}
}				/* xfmcontpts */


/*----------------------------------------------------------------*/
/* convert into DVI space and offset by H & V */
static void 
dvilinepts(x1, y1, x2, y2, offh, offv)
	int32          *x1, *y1, *x2, *y2, offh, offv;
{
	*x1 += offh;
	*x2 += offh;
	*y1 = offv - *y1;
	*y2 = offv - *y2;
}


/*----------------------------------------------------------------*/
/* convert into DVI space and offset by H & V */
static void 
dvicontpts(xpts, xknots, offh, offv)
int32(*xpts)[2];
	int32           xknots, offh, offv;
{
	int32           i;

	for (i = 0; i <= xknots; i++)
	{
		xpts[i][0] += offh;
		xpts[i][1] = offv - xpts[i][1];
	}
}


/*----------------------------------------------------------------*/
/*
 * transform all the figure's elements according to the top-level tranformation requirements in 1st Quadrant space. then reset
 * the toplevel's xfms.
 */
static void 
toplevelxfm(toplev, curfig, recurlevel)
	Item           *toplev, *curfig;
	int32           recurlevel;
{
	Item           *pi;
	ScaledPts       null1, null2, old1, old2, midx, midy;

	midy = (toplev->BBty - toplev->BBby) / 2;
	midx = (toplev->BBrx - toplev->BBlx) / 2;
	pi = curfig->UU.U8.body->things;	/* if recur==0, this is same as toplev */
	while (pi != NULL)
	{
		switch (pi->kind)
		{		/* with */

		case Aline:
			xfmlinepts(&pi->UU.U1.lx1, &pi->UU.U1.ly1, &pi->UU.U1.lx2,
				   &pi->UU.U1.ly2, 0, 0, midx, midy, 1.0,
				   toplev->UU.U8.figtheta, toplev->UU.U8.fdx, toplev->UU.U8.fdy,
				   toplev->UU.U8.fsx, toplev->UU.U8.fsy);
			break;

		case Aspline:
			xfmcontpts(pi->UU.U2.spts, pi->UU.U2.nsplknots, 0, 0, midx, midy, 1.0,
				   toplev->UU.U8.figtheta, toplev->UU.U8.fdx, toplev->UU.U8.fdy,
				   toplev->UU.U8.fsx, toplev->UU.U8.fsy);
			break;

		case Attspline:
			xfmcontpts(pi->UU.U3.ttpts, pi->UU.U3.nttknots, 0, 0, midx, midy, 1.0,
				   toplev->UU.U8.figtheta, toplev->UU.U8.fdx, toplev->UU.U8.fdy,
				   toplev->UU.U8.fsx, toplev->UU.U8.fsy);
			break;

		case Aarc:
			null1 = 0;
			null2 = 0;
			old1 = pi->UU.U6.acentx;
			old2 = pi->UU.U6.acenty;
			xfmlinepts(&pi->UU.U6.acentx, &pi->UU.U6.acenty, &null1, &null2, 0, 0,
				   midx, midy, 1.0, toplev->UU.U8.figtheta, toplev->UU.U8.fdx,
				   toplev->UU.U8.fdy, toplev->UU.U8.fsx, toplev->UU.U8.fsy);

			xfmcontpts(pi->UU.U6.arcpts, pi->UU.U6.narcknots + 1, 0, 0, old1,
				   old2, 1.0, toplev->UU.U8.figtheta,
				   toplev->UU.U8.fdx + pi->UU.U6.acentx - old1,
				   toplev->UU.U8.fdy + pi->UU.U6.acenty - old2,
				   toplev->UU.U8.fsx, toplev->UU.U8.fsy);
			break;

		case Alabel:
			null1 = 0;
			null2 = 0;
			xfmlinepts(&pi->UU.U7.labx, &pi->UU.U7.laby, &null1, &null2, 0, 0,
				   midx, midy, 1.0, toplev->UU.U8.figtheta, toplev->UU.U8.fdx,
				   toplev->UU.U8.fdy, toplev->UU.U8.fsx, toplev->UU.U8.fsy);
			break;

		case Abeam:	/* not transformable */
			break;

		case Atieslur:	/* not transformable */
			break;

		case Afigure:
			toplevelxfm(toplev, pi, recurlevel + 1);
			break;
		}		/* case */
		pi = pi->nextitem;
	}			/* while */
	if (recurlevel != 0)	/* reset the toplevel's xfms */
		return;
	toplev->UU.U8.figtheta = 0.0;
	toplev->UU.U8.fsx = 1.0;
	toplev->UU.U8.fsy = 1.0;
	toplev->UU.U8.fdx = 0;
	toplev->UU.U8.fdy = 0;
}


/*----------------------------------------------------------------*/
static double 
scalefitfactor(actualwid, actualht, goalwid, goalht)
	int32           actualwid, actualht, goalwid, goalht;
{
	double          sx, sy;

	sx = (double) goalwid / actualwid;
	sy = (double) goalht / actualht;
	if (sx < sy)
		return sx;
	else
		return sy;
}



/*
 * ---- The handlers for each primitive ---- The result of calling each handler is either immediate output to the buffer of the
 * commands to produce the primitive, OR the primitive gets pushed onto a stack/list that defines a current 'figure' (set of
 * prims) for output at a later time
 * 
 * Look at linehandle for a basic idea of how the handlers work. the others follow pretty closely.
 */


/*------------------------------------------------------------*/
void 
linehandle(figdepth, scalefact, x1, y1, x2, y2, dvih, dviv, thk,
	   vk, patt, minx, maxx, miny, maxy, tx, ty, sx, sy, r)
	int32           figdepth;
	double          scalefact;
	int32           x1, y1, x2, y2, dvih, dviv;
	VThickness      thk;
	VectKind        vk;
	LineStyle       patt;
	int32           minx, maxx, miny, maxy, tx, ty;
	double          sx, sy, r;
{
	/* possible dvi-offsets */
	ScaledPts       midx, midy;
	Item           *lineitem;

	midx = (minx + maxx) / 2;
	midy = (miny + maxy) / 2;

	/* do local primitive -level transformations */
	xfmlinepts(&x1, &y1, &x2, &y2, dvih, dviv, midx, midy, scalefact, r, tx, ty,
		   sx, sy);

	if (figdepth == 0)
	{			/* ---- do the primitive by itself */
		/* re-transform it to the 4th Quadrant */
		dvilinepts(&x1, &y1, &x2, &y2, h, v);	/* global h and v posit */
		IPUSH();
		TylLine(x1, y1, x2, y2, thk, vk, patt);
		IPOP();
		return;
	}
	if (figdepth <= 0)
	{			/* ---- Pack it and stack it */
		if (figdepth < 0)
		{		/* ---- just do it right away without any PUSH/POP pair */
			/*
			 * this is the case when we are unpacking a figure for immediate output
			 */
			TylLine(x1, y1, x2, y2, thk, vk, patt);
		}
		return;
	}
	lineitem = NewItem(Aline);
	lineitem->BBlx = minx;
	lineitem->BBby = miny;
	lineitem->BBrx = maxx;
	lineitem->BBty = maxy;
	lineitem->UU.U1.lx1 = x1;
	lineitem->UU.U1.ly1 = y1;
	lineitem->UU.U1.lx2 = x2;
	lineitem->UU.U1.ly2 = y2;
	lineitem->itemthick = thk;
	lineitem->itemvec = (unsigned) vk;
	lineitem->itempatt = (unsigned) patt;
	pushItem(figdepth, lineitem);
}				/* linehandle */


/* ---   Simple Splines ----- */
/*-----------------------------------------------------*/
void 
splinehandle(figdepth, scalefact, thetype, isclosed, markdiam,
	     contpts, nknots, dvih, dviv, thk, vec, patt, minx,
	     maxx, miny, maxy, tx, ty, sx, sy, r)
	int32           figdepth;
	double          scalefact;
	SplineKind      thetype;
	int		isclosed;
	int32           markdiam;
int32(*contpts)[2];
	int32           nknots, dvih, dviv;
	VThickness      thk;
	VectKind        vec;
	LineStyle       patt;
	int32           minx, maxx, miny, maxy, tx, ty;
	double          sx, sy, r;
{
	/* possible dvi-offsets */
	ScaledPts       midx, midy;
	Item           *splineitem;
	int32           i;

	midx = (minx + maxx) / 2;
	midy = (miny + maxy) / 2;

	xfmcontpts(contpts, nknots, dvih, dviv, midx, midy, scalefact, r, tx, ty,
		   sx, sy);

	if (figdepth == 0)
	{			/* ----  do the primitive */
		/* transform to 4th quad */
		dvicontpts(contpts, nknots, h, v);
		IPUSH();
		TylSpline(thetype, isclosed, contpts, nknots, thk, vec, patt, markdiam);
		IPOP();
		return;
	}
	if (figdepth <= 0)
	{
		if (figdepth < 0)
			TylSpline(thetype, isclosed, contpts, nknots, thk, vec, patt, markdiam);
		return;
	}
	splineitem = NewItem(Aspline);
	splineitem->BBlx = minx;
	splineitem->BBby = miny;
	splineitem->BBrx = maxx;
	splineitem->BBty = maxy;
	splineitem->itemthick = thk;
	splineitem->itemvec = (unsigned) vec;
	splineitem->itempatt = (unsigned) patt;
	splineitem->UU.U2.nsplknots = nknots;
	splineitem->UU.U2.spltype = (unsigned) thetype;
	splineitem->UU.U2.sclosed = isclosed;
	splineitem->UU.U2.dosmarks = markdiam;
	for (i = 1; i <= nknots; i++)
	{
		splineitem->UU.U2.spts[i][0] = contpts[i][0];
		splineitem->UU.U2.spts[i][1] = contpts[i][1];
	}
	pushItem(figdepth, splineitem);
}				/* splinehandle */


/* --- Variable thickness splines ----- */
/*-----------------------------------------------------*/
void 
ttsplhandle(figdepth, scalefact, thetype, isclosed, markdiam,
	    contpts_, ttks_, nknots, dvih, dviv, vec, patt, minx,
	    maxx, miny, maxy, tx, ty, sx, sy, r)
	int32           figdepth;
	double          scalefact;
	SplineKind      thetype;
	int		isclosed;
	int32           markdiam;
int32(*contpts_)[2];
	VThickness     *ttks_;
	int32           nknots, dvih, dviv;
	VectKind        vec;
	LineStyle       patt;
	int32           minx, maxx, miny, maxy, tx, ty;
	double          sx, sy, r;
{
	/* possible dvi-offsets */
	ControlPoints   contpts;
	ThickAryType    ttks;
	ScaledPts       midx, midy;
	Item           *ttsplitem;
	int32           i;
	char		*memcpy PP((char *, char *, int));

	(void) memcpy((char *)contpts, (char *)contpts_, sizeof(ControlPoints));
	(void) memcpy((char *)ttks, (char *)ttks_, sizeof(ThickAryType));
	midx = (minx + maxx) / 2;
	midy = (miny + maxy) / 2;

	xfmcontpts(contpts, nknots, dvih, dviv, midx, midy, scalefact, r, tx, ty,
		   sx, sy);

	if (figdepth == 0)
	{
		/* transform to 4th quad      */
		dvicontpts(contpts, nknots, h, v);
		IPUSH();
		TylThickThinSpline(thetype, isclosed, contpts, ttks, nknots, vec, patt,
				   markdiam);
		IPOP();
		return;
	}

	if (figdepth <= 0)
	{
		if (figdepth < 0)
			TylThickThinSpline(thetype, isclosed, contpts, ttks, nknots, vec, patt,
					   markdiam);
		return;
	}
	ttsplitem = NewItem(Attspline);
	ttsplitem->BBlx = minx;
	ttsplitem->BBby = miny;
	ttsplitem->BBrx = maxx;
	ttsplitem->BBty = maxy;
	ttsplitem->itemvec = (unsigned) vec;
	ttsplitem->itempatt = (unsigned) patt;
	ttsplitem->UU.U3.nttknots = nknots;
	ttsplitem->UU.U3.tspltype = (unsigned) thetype;
	ttsplitem->UU.U3.dottmarks = markdiam;
	ttsplitem->UU.U3.tclosed = isclosed;
	for (i = 1; i <= nknots; i++)
	{			/* ttsplitem */
		ttsplitem->UU.U3.ttpts[i][0] = contpts[i][0];
		ttsplitem->UU.U3.ttpts[i][1] = contpts[i][1];
		ttsplitem->UU.U3.ttarry[i] = ttks[i];
	}
	pushItem(figdepth, ttsplitem);
}				/* ttsplhandle */


/* ---- Musical Beams ---- */
/*-----------------------------------------------------*/
void 
beamhandle(depth, siz, bk, x1, y1, x2, y2)
	int32           depth, siz;
	BeamKind        bk;
	int32           x1, y1, x2, y2;
{
	Item           *bmitem;

	if (depth == 0)
	{
		dvilinepts(&x1, &y1, &x2, &y2, h, v);
		IPUSH();
		TylBeam(x1, y1, x2, y2, siz, bk);
		IPOP();
		return;
	}
	if (depth <= 0)
	{
		if (depth < 0)
		{
			TylBeam(x1, y1, x2, y2, siz, bk);
		}		/* else */
		return;
	}
	bmitem = NewItem(Abeam);
	bmitem->BBlx = min(x1, x2);
	bmitem->BBby = min(y1, y2);
	bmitem->BBrx = max(x1, x2);
	bmitem->BBty = max(y1, y2);
	bmitem->UU.U4.bx1 = x1;
	bmitem->UU.U4.by1 = y1;
	bmitem->UU.U4.bx2 = x2;
	bmitem->UU.U4.by2 = y2;
	bmitem->UU.U4.staf = siz;
	bmitem->UU.U4.bkind = (unsigned) bk;	/* with */
	pushItem(depth, bmitem);
}				/* beamhandle */


/* ---- Musical Ties and Slurs ----- */
/*-----------------------------------------------------*/
void 
tieslurhandle(depth, pts_, numk, minthick, maxthick)
	int32           depth;
int32(*pts_)[2];
	int32           numk;
	VThickness      minthick, maxthick;
{
	ControlPoints   pts;
	Item           *tsitem;
	int32           i;
	char		*memcpy PP((char *, char *, int));

	(void) memcpy((char *)pts, (char *)pts_, sizeof(ControlPoints));
	if (depth == 0)
	{
		dvicontpts(pts, numk, h, v);
		IPUSH();
		TylTieSlur(pts, numk, minthick, maxthick);
		IPOP();
		return;
	}
	if (depth <= 0)
	{
		if (depth < 0)
		{
			TylTieSlur(pts, numk, minthick, maxthick);
		}		/* else */
		return;
	}
	tsitem = NewItem(Atieslur);
	tsitem->UU.U5.ntknots = numk;
	for (i = 1; i <= numk; i++)
	{
		tsitem->UU.U5.tspts[i][0] = pts[i][0];
		tsitem->UU.U5.tspts[i][1] = pts[i][1];
	}
	tsitem->UU.U5.minth = minthick;
	tsitem->UU.U5.maxth = maxthick;	/* with */
	pushItem(depth, tsitem);
}				/* tieslurhandle */


/*---------------------------------------------------------*/
void 
arccirclehandle(figdepth, scalefact, cx, cy, radius, ang1, ang2,
		contpts, nknots, dvih, dviv, thk, vec, patt, minx,
		maxx, miny, maxy, tx, ty, sx, sy, r)
	int32           figdepth;
	double          scalefact;
	int32           cx, cy, radius, ang1, ang2;
int32(*contpts)[2];
	int32           nknots, dvih, dviv;
	VThickness      thk;
	VectKind        vec;
	LineStyle       patt;
	int32           minx, maxx, miny, maxy, tx, ty;
	double          sx, sy, r;
{
	/* IN */
	/* possible dvi-offsets */
	ScaledPts       midx, midy;
	Item           *arcitem;
	int32           i;
	int		isclosedarc;

	midx = cx;
	midy = cy;
	isclosedarc = (ang1 == ang2);
	/*
	 * if (isclosedarc) then maxspanlen := round ((360.0 / 16.0) * DEGTORAD * radius) else maxspanlen := round ((abs(ang2 -
	 * ang1) / 16.0) * DEGTORAD * radius); {
	 */


	xfmcontpts(contpts, nknots + 1, dvih, dviv, midx, midy, scalefact, r, tx,
		   ty, sx, sy);

	if (figdepth == 0)
	{			/* ---- just do the primitive */
		/* transform to 4th quad */
		dvicontpts(contpts, nknots + 1, h, v);
		IPUSH();
		doTylArc(isclosedarc, contpts, nknots, thk, vec, patt);
		IPOP();
		return;
	}
	if (figdepth <= 0)
	{
		if (figdepth < 0)
			doTylArc(isclosedarc, contpts, nknots, thk, vec, patt);
		return;
	}
	arcitem = NewItem(Aarc);
	arcitem->BBlx = minx;
	arcitem->BBby = miny;
	arcitem->BBrx = maxx;
	arcitem->BBty = maxy;
	arcitem->itemthick = thk;
	arcitem->itemvec = (unsigned) vec;
	arcitem->itempatt = (unsigned) patt;
	arcitem->UU.U6.narcknots = nknots;
	arcitem->UU.U6.acentx = cx;
	arcitem->UU.U6.acenty = cy;
	arcitem->UU.U6.aradius = radius;
	arcitem->UU.U6.firstang = ang1;
	arcitem->UU.U6.lastang = ang2;
	for (i = 0; i <= nknots + 1; i++)
	{
		arcitem->UU.U6.arcpts[i][0] = contpts[i][0];
		arcitem->UU.U6.arcpts[i][1] = contpts[i][1];
	}
	pushItem(figdepth, arcitem);
}				/* arccirclehandle */



/*---------------------------------------------------------*/
void 
labelhandle(depth, scalefact, lax, lay, dvih, dviv, style, phrase,
	    tx, ty)
	int32           depth;
	double          scalefact;
	int32           lax, lay, dvih, dviv, style;
	charstring      phrase;
	int32           tx, ty;
{
	/* possible dvi-offsets */
	Item           *labitem;
	ScaledPts       null1, null2;

	/* xfm the label point if necessary */
	lax += (int32) floor(tx * scalefact + 0.5);
	lay += (int32) floor(ty * scalefact + 0.5);

	if (depth == 0)
	{
		null1 = 0;
		null2 = 0;
		dvilinepts(&lax, &lay, &null1, &null2, h, v);
		IPUSH();
		TylLabel(lax, lay, style, phrase, strlen(phrase));
		IPOP();
		return;
	}
	if (depth <= 0)
	{
		if (depth < 0)
			TylLabel(lax, lay, style, phrase, strlen(phrase));
		return;
	}
	labitem = NewItem(Alabel);
	labitem->UU.U7.labx = lax;
	labitem->UU.U7.laby = lay;
	labitem->UU.U7.fontstyle = style;
	strcpy(labitem->UU.U7.labeltext, phrase);
	pushItem(depth, labitem);
}

/*
 * ####   Insert new handlers here for new "primitives" i.e., names callable from the \special[tyl ...]  level
 */

/*----------------------------------------------------------------*/
/* transform the current bbox coordinates, and output the new one */
static void 
newbbox(minx, maxx, miny, maxy, midx, midy, sx, sy, rot, tx, ty)
	int32          *minx, *maxx, *miny, *maxy, midx, midy;
	double          sx, sy, rot;
	int32           tx, ty;
{
	/* coords of full bbox for transformation [n/s][e/w][x/y] */
	ScaledPts       nex, ney, sex, sey, swx, swy, nwx, nwy;
	int32           temp1, temp2;

	/* describe  and transform the bbox */
	nwx = (int32) floor(*minx * sx + 0.5);
	nex = (int32) floor(*maxx * sx + 0.5);
	sex = (int32) floor(*maxx * sx + 0.5);
	swx = (int32) floor(*minx * sx + 0.5);
	ney = (int32) floor(*maxy * sy + 0.5);
	nwy = (int32) floor(*maxy * sy + 0.5);
	swy = (int32) floor(*miny * sy + 0.5);
	sey = (int32) floor(*miny * sy + 0.5);

	ptrotate(&nex, &ney, midx, midy, rot);
	ptrotate(&sex, &sey, midx, midy, rot);
	ptrotate(&swx, &swy, midx, midy, rot);
	ptrotate(&nwx, &nwy, midx, midy, rot);

	nex += tx;
	sex += tx;
	swx += tx;
	nwx += tx;
	ney += ty;
	sey += ty;
	swy += ty;
	nwy += ty;
	/* now find the actual extents of the bbox */
	temp1 = min(nex, nwx);
	temp2 = min(swx, sex);
	*minx = min(temp1, temp2);

	temp1 = min(ney, nwy);
	temp2 = min(swy, sey);
	*miny = min(temp1, temp2);

	temp1 = max(nex, nwx);
	temp2 = max(swx, sex);
	*maxx = max(temp1, temp2);

	temp1 = max(ney, nwy);
	temp2 = max(swy, sey);
	*maxy = max(temp1, temp2);
}


/*-----------------------------------------------*/
/*
 * find the bounding box of the list of primitives and/or sub-figures in this Item
 */

static void 
findBBox(blot, mnx, mxx, mny, mxy)
	Item           *blot;
	int32          *mnx, *mxx, *mny, *mxy;
{
	Item           *pi;
	ScaledPts       bmnx, bmxx, bmny, bmxy, midx, midy;	/* bbox [min/max][x/y] */
	ScaledPts       tmnx, tmxx, tmny, tmxy;	/* temporary, in case of recursion */
	ScaledPts       null1, null2, old1, old2;
	double          prescale, postscale;

	bmnx = TWO24;
	bmny = TWO24;
	bmxx = -TWO24;
	bmxy = -TWO24;
	if (blot->kind == Afigure)
	{			/* afigure */
		pi = blot->UU.U8.body->things;
		while (pi != NULL)
		{
			/* find the current bbox of the list of items here */
			if (pi->kind == Afigure)
			{	/* recur */
				findBBox(pi, &tmnx, &tmxx, &tmny, &tmxy);
				bmnx = min(bmnx, tmnx);
				bmny = min(bmny, tmny);
				bmxx = max(bmxx, tmxx);
				bmxy = max(bmxy, tmxy);
			}
			else
			{
				bmnx = min(bmnx, pi->BBlx);
				bmny = min(bmny, pi->BBby);
				bmxx = max(bmxx, pi->BBrx);
				bmxy = max(bmxy, pi->BBty);
			}
			pi = pi->nextitem;
		}		/* while */
		/* now transform the items inside, AND the bbox */
		pi = blot->UU.U8.body->things;
		midx = (bmnx + bmxx) / 2;
		midy = (bmny + bmxy) / 2;
		/* now take care of any pre and post size requirements */
		/* see also the "figurehandle" proc. */
		/* #### Keep this scaling biz here, too, for now. May blast it later */
		if (blot->UU.U8.preWid != 0 && blot->UU.U8.preHt != 0)
		{
			prescale = scalefitfactor(bmxx - bmnx, bmxy - bmny, blot->UU.U8.preWid,
						  blot->UU.U8.preHt);
			blot->UU.U8.fsx *= prescale;
			blot->UU.U8.fsy *= prescale;
		}
		if (blot->UU.U8.postWid != 0 && blot->UU.U8.postHt != 0)
		{		/* with */
			postscale = scalefitfactor(bmxx - bmnx, bmxy - bmny,
						   blot->UU.U8.postWid, blot->UU.U8.postHt);
			blot->UU.U8.fsx *= postscale;
			blot->UU.U8.fsy *= postscale;
		}

		/* the actual scale-up is taken care of later in this proc. */
		while (pi != NULL)
		{
			switch (pi->kind)
			{	/* with */

			case Aline:
				xfmlinepts(&pi->UU.U1.lx1, &pi->UU.U1.ly1, &pi->UU.U1.lx2,
					   &pi->UU.U1.ly2, 0, 0, midx, midy, 1.0,
					   blot->UU.U8.figtheta, blot->UU.U8.fdx, blot->UU.U8.fdy,
					   blot->UU.U8.fsx, blot->UU.U8.fsy);
				break;

			case Aspline:
				xfmcontpts(pi->UU.U2.spts, pi->UU.U2.nsplknots, 0, 0, midx, midy,
					   1.0, blot->UU.U8.figtheta, blot->UU.U8.fdx,
					   blot->UU.U8.fdy, blot->UU.U8.fsx, blot->UU.U8.fsy);
				break;

			case Attspline:
				xfmcontpts(pi->UU.U3.ttpts, pi->UU.U3.nttknots, 0, 0, midx, midy,
					   1.0, blot->UU.U8.figtheta, blot->UU.U8.fdx,
					   blot->UU.U8.fdy, blot->UU.U8.fsx, blot->UU.U8.fsy);
				break;

			case Aarc:
				null1 = 0;
				null2 = 0;
				old1 = pi->UU.U6.acentx;
				old2 = pi->UU.U6.acenty;
				xfmlinepts(&pi->UU.U6.acentx, &pi->UU.U6.acenty, &null1, &null2, 0,
					   0, midx, midy, 1.0, blot->UU.U8.figtheta, blot->UU.U8.fdx,
					   blot->UU.U8.fdy, blot->UU.U8.fsx, blot->UU.U8.fsy);
				xfmcontpts(pi->UU.U6.arcpts, pi->UU.U6.narcknots + 1, 0, 0, old1,
					   old2, 1.0, blot->UU.U8.figtheta,
					   blot->UU.U8.fdx + pi->UU.U6.acentx - old1,
					   blot->UU.U8.fdy + pi->UU.U6.acenty - old2, blot->UU.U8.fsx,
					   blot->UU.U8.fsy);
				break;

			case Alabel:
				null1 = 0;
				null2 = 0;
				xfmlinepts(&pi->UU.U7.labx, &pi->UU.U7.laby, &null1, &null2, 0, 0,
					   midx, midy, 1.0, blot->UU.U8.figtheta, blot->UU.U8.fdx,
					   blot->UU.U8.fdy, blot->UU.U8.fsx, blot->UU.U8.fsy);
				break;

			case Abeam:	/* not transformable */
				break;

			case Atieslur:	/* not transformable */
				break;

			case Afigure:	/* do not need to re-transform */
				break;
			}	/* case */
			pi = pi->nextitem;
		}		/* while */
		/* transform the bbox, and re-find the new bbox */
		newbbox(&bmnx, &bmxx, &bmny, &bmxy, midx, midy, blot->UU.U8.fsx,
			blot->UU.U8.fsy, blot->UU.U8.figtheta, blot->UU.U8.fdx,
			blot->UU.U8.fdy);
		*mnx = bmnx;
		*mny = bmny;
		*mxx = bmxx;
		*mxy = bmxy;
		return;
	}			/* if */
	*mnx = blot->BBlx;
	*mny = blot->BBby;
	*mxx = blot->BBrx;
	*mxy = blot->BBty;

	/* some other primitive */
	/* else */
}				/* findBBox */


/*---------------------------------------------------------*/
/*
 * traverse the list, determining the current bounding box for the items. We need this to find the mid-point for doing any
 * remaining rotations
 */
static void 
traverse(thefig, theitem)
	Item           *thefig, *theitem;
{
	ScaledPts       minx, maxx, miny, maxy, curminx, curmaxx, curminy, curmaxy;

	minx = TWO24;
	maxx = -TWO24;
	miny = TWO24;
	maxy = -TWO24;

	while (theitem != NULL)
	{			/* set the bounding box for this upper-level symbol defn */
		if (theitem->kind == Afigure)
		{		/* recur */
			findBBox(theitem, &curminx, &curmaxx, &curminy, &curmaxy);
			theitem->BBlx = curminx;
			theitem->BBby = curminy;
			theitem->BBrx = curmaxx;
			theitem->BBty = curmaxy;
			/*
			 * reset the symbol's parameters since all the primitives in it have now been transformed according to
			 * the previous specifications
			 */
			theitem->UU.U8.figtheta = 0.0;
			theitem->UU.U8.fsx = 1.0;
			theitem->UU.U8.fsy = 1.0;
			theitem->UU.U8.fdx = 0;
			theitem->UU.U8.fdy = 0;
			theitem->UU.U8.preWid = 0;
			theitem->UU.U8.preHt = 0;
			theitem->UU.U8.postWid = 0;
			theitem->UU.U8.postHt = 0;	/* with */
			minx = min(minx, curminx);
			miny = min(miny, curminy);
			maxx = max(maxx, curmaxx);
			maxy = max(maxy, curmaxy);
		}		/* if a figure/symbol */
		else
		{		/* a primitive */
			minx = min(minx, theitem->BBlx);
			miny = min(miny, theitem->BBby);
			maxx = max(maxx, theitem->BBrx);
			maxy = max(maxy, theitem->BBty);	/* with */
		}		/* else */
		theitem = theitem->nextitem;
	}			/* while */

	thefig->BBlx = minx;
	thefig->BBby = miny;
	thefig->BBrx = maxx;
	thefig->BBty = maxy;	/* with */
}				/* traverse */


#define DoItNow         (-1)
#define NoScale         1


/* ----- Figure symbols ----- */
/*---------------------------------------------------*/
void 
figurehandle(globalsymlist, symbollist, dopush)
	Item           *globalsymlist, *symbollist;
	int32           dopush;
{
	Item           *pi, *curfig;
	ScaledPts       midx, midy, null1, null2, tmnx, tmny, tmxx, tmxy;
	double          prescale, postscale;

	/*
	 * PUSH. traverse the lists (recursively if necessary) and compute the transformed points. Convert to 4th quadrant and
	 * offset by H & V. We can do this destructively here since we're going to output them right away anyhow. Then call
	 * each respective primitive handler with a level of -1 to indicate  to do its job immediately. POP.
	 */
	curfig = symbollist;
	pi = curfig->UU.U8.body->things;
	/*
	 * find and set the bounding box for the figure's sub-symbols and primitives
	 */
	if (dopush > 0)
		traverse(curfig, pi);

	/*
	 * We eventually transform the items to 4th Quadrant DVI space and output them!
	 */

	pi = curfig->UU.U8.body->things;

	midy = (globalsymlist->BBby + globalsymlist->BBty) / 2;
	midx = (globalsymlist->BBlx + globalsymlist->BBrx) / 2;

	if (dopush > 0)
	{			/* the top-level figure for outputting */
		/*
		 * convert the bounding box because we are about to enter into DVI space, and all calls to handlers hereafter
		 * are in terms of DVI coordinates
		 */


		/*
		 * Since there were external specifications about this figure, fit the current figure's actual size to the
		 * "pre" size (specified by W marker) and/or to the "post" size (specified by the F marker). We do this by
		 * simple scaling, *without* changing the midpoint of the bounding box, just its extents
		 */
		if (globalsymlist->UU.U8.preWid != 0 && globalsymlist->UU.U8.preHt != 0)
		{
			prescale = scalefitfactor(globalsymlist->BBrx - globalsymlist->BBlx,
						  globalsymlist->BBty - globalsymlist->BBby,
						  globalsymlist->UU.U8.preWid, globalsymlist->UU.U8.preHt);
			globalsymlist->UU.U8.fsx *= prescale;
			globalsymlist->UU.U8.fsy *= prescale;
		}
		if (globalsymlist->UU.U8.postWid != 0 && globalsymlist->UU.U8.postHt != 0)
		{
			postscale = scalefitfactor(globalsymlist->BBrx - globalsymlist->BBlx,
						   globalsymlist->BBty - globalsymlist->BBby,
						   globalsymlist->UU.U8.postWid, globalsymlist->UU.U8.postHt);
			globalsymlist->UU.U8.fsx *= postscale;
			globalsymlist->UU.U8.fsy *= postscale;
		}
		tmnx = globalsymlist->BBlx;
		tmny = globalsymlist->BBby;
		tmxx = globalsymlist->BBrx;
		tmxy = globalsymlist->BBty;
		xfmlinepts(&tmnx, &tmny, &tmxx, &tmxy, 0, 0, midx, midy, 1.0, 0.0, 0,
			   0, globalsymlist->UU.U8.fsx, globalsymlist->UU.U8.fsy);

		toplevelxfm(globalsymlist, globalsymlist, 0);

		dviBBlx = tmnx;
		dviBBrx = tmxx;
		dviBBby = tmny;
		dviBBty = tmxy;

		xfmlinepts(&dviBBlx, &dviBBby, &dviBBrx, &dviBBty, 0, 0, midx, midy,
			   1.0, 0.0, globalsymlist->BBlx - tmnx,
			   globalsymlist->BBby - tmny, 1.0, 1.0);

		globalsymlist->UU.U8.fdx += globalsymlist->BBlx - tmnx;
		globalsymlist->UU.U8.fdy += globalsymlist->BBby - tmny;

		dvilinepts(&dviBBlx, &dviBBby, &dviBBrx, &dviBBty, h, v);
		pgfigurenum++;

		/* We are ready to output the figure to the page */
		fprintf(logfile, "\nFigure #%ld on page %ld is approx. ",
			pgfigurenum, currpagenum);
		/*
		 * write(logfile,((globalsymlist^.BBty - globalsymlist^.BBby) div SPPERPT):0,' pts high and ');
		 * writeln(logfile,((globalsymlist^.BBrx - globalsymlist^.BBlx) div SPPERPT):0,' pts wide (actual size)');
		 */
		fprintf(logfile, "%ld pts high and ", (tmxy - tmny) / SPPERPT);
		fprintf(logfile, "%ld pts wide (actual size)\n", (tmxx - tmnx) / SPPERPT);
		IPUSH();

	}


	while (pi != NULL)
	{
		switch (pi->kind)
		{		/* with */

		case Aline:
			dvilinepts(&pi->UU.U1.lx1, &pi->UU.U1.ly1, &pi->UU.U1.lx2,
				   &pi->UU.U1.ly2, h, v);
			/* DVI h and v posit */
			linehandle((int32) DoItNow, (double) NoScale, pi->UU.U1.lx1, pi->UU.U1.ly1,
				   pi->UU.U1.lx2, pi->UU.U1.ly2, 0, 0, pi->itemthick,
				   (VectKind) pi->itemvec, (LineStyle) pi->itempatt, dviBBlx,
				   dviBBrx, dviBBby, dviBBty, globalsymlist->UU.U8.fdx,
				   -globalsymlist->UU.U8.fdy, globalsymlist->UU.U8.fsx,
				   globalsymlist->UU.U8.fsy, -globalsymlist->UU.U8.figtheta);
			/*
			 * p2c: x.p, line 4681: Internal error in checkvarchangedexpr: Too few arguments for EK_FUNCTION [267]
			 */
			break;
			/* Aline */

		case Aspline:
			dvicontpts(pi->UU.U2.spts, pi->UU.U2.nsplknots, h, v);
			splinehandle((int32) DoItNow, (double) NoScale,
				     (SplineKind) pi->UU.U2.spltype, pi->UU.U2.sclosed,
				     pi->UU.U2.dosmarks, pi->UU.U2.spts, pi->UU.U2.nsplknots,
				     0, 0, pi->itemthick, (VectKind) pi->itemvec,
				     (LineStyle) pi->itempatt, dviBBlx, dviBBrx, dviBBby,
				     dviBBty, globalsymlist->UU.U8.fdx,
				     -globalsymlist->UU.U8.fdy, globalsymlist->UU.U8.fsx,
				     globalsymlist->UU.U8.fsy, -globalsymlist->UU.U8.figtheta);
			/*
			 * p2c: x.p, line 4693: Internal error in checkvarchangedexpr: Too few arguments for EK_FUNCTION [267]
			 */
			break;
			/* Aspline */

		case Attspline:
			dvicontpts(pi->UU.U3.ttpts, pi->UU.U3.nttknots, h, v);
			ttsplhandle((int32) DoItNow, (double) NoScale,
				    (SplineKind) pi->UU.U3.tspltype, pi->UU.U3.tclosed,
				    pi->UU.U3.dottmarks, pi->UU.U3.ttpts, pi->UU.U3.ttarry,
				    pi->UU.U3.nttknots, 0, 0, (VectKind) pi->itemvec,
				    (LineStyle) pi->itempatt, dviBBlx, dviBBrx, dviBBby, dviBBty,
				    globalsymlist->UU.U8.fdx, -globalsymlist->UU.U8.fdy,
				    globalsymlist->UU.U8.fsx, globalsymlist->UU.U8.fsy,
				    -globalsymlist->UU.U8.figtheta);
			/*
			 * p2c: x.p, line 4705: Internal error in checkvarchangedexpr: Too few arguments for EK_FUNCTION [267]
			 */
			break;
			/* Attspline */

		case Abeam:
			dvilinepts(&pi->UU.U4.bx1, &pi->UU.U4.by1, &pi->UU.U4.bx2,
				   &pi->UU.U4.by2, h, v);
			beamhandle((int32) DoItNow, pi->UU.U4.staf, (BeamKind) pi->UU.U4.bkind,
				   pi->UU.U4.bx1, pi->UU.U4.by1, pi->UU.U4.bx2, pi->UU.U4.by2);
			break;
			/* Abeam */

		case Atieslur:
			dvicontpts(pi->UU.U5.tspts, pi->UU.U5.ntknots, h, v);
			tieslurhandle((int32) DoItNow, pi->UU.U5.tspts, pi->UU.U5.ntknots,
				      pi->UU.U5.minth, pi->UU.U5.maxth);
			break;
			/* a tie or slur */

		case Aarc:
			dvicontpts(pi->UU.U6.arcpts, pi->UU.U6.narcknots + 1, h, v);
			arccirclehandle((int32) DoItNow, (double) NoScale, pi->UU.U6.acentx,
					pi->UU.U6.acenty, pi->UU.U6.aradius, pi->UU.U6.firstang,
					pi->UU.U6.lastang, pi->UU.U6.arcpts,
					pi->UU.U6.narcknots, 0, 0, pi->itemthick,
					(VectKind) pi->itemvec, (LineStyle) pi->itempatt, dviBBlx,
					dviBBrx, dviBBby, dviBBty, globalsymlist->UU.U8.fdx,
					-globalsymlist->UU.U8.fdy, globalsymlist->UU.U8.fsx,
					globalsymlist->UU.U8.fsy,
					-globalsymlist->UU.U8.figtheta);
			/*
			 * p2c: x.p, line 4729: Internal error in checkvarchangedexpr: Too few arguments for EK_FUNCTION [267]
			 */
			break;
			/* arc */

		case Alabel:
			null1 = 0;
			null2 = 0;
			dvilinepts(&pi->UU.U7.labx, &pi->UU.U7.laby, &null1, &null2, h, v);
			labelhandle((int32) DoItNow, (double) NoScale, pi->UU.U7.labx,
				    pi->UU.U7.laby, 0, 0, pi->UU.U7.fontstyle,
				    pi->UU.U7.labeltext, globalsymlist->UU.U8.fdx,
				    -globalsymlist->UU.U8.fdy);
			break;
			/* label */

		case Afigure:	/* recur */
			figurehandle(globalsymlist, pi, 0);
			break;
			/* another symbol */

		}		/* case */
		/*
		 * p2c: x.p, line 4747: Internal error in checkvarchangedexpr: Too few arguments for EK_FUNCTION [267]
		 */
		/*
		 * p2c: x.p, line 4747: Internal error in checkvarchangedexpr: Too few arguments for EK_FUNCTION [267]
		 */
		/*
		 * p2c: x.p, line 4747: Internal error in checkvarchangedexpr: Too few arguments for EK_FUNCTION [267]
		 */
		/*
		 * p2c: x.p, line 4747: Internal error in checkvarchangedexpr: Too few arguments for EK_FUNCTION [267]
		 */
		pi = pi->nextitem;
	}			/* while */
	if (dopush > 0)
		IPOP();
}				/* figurehandle */

#undef DoItNow
#undef NoScale