v04i059: xtroff -- troff previewer for X11, Part14/18

Dan Heller argv at island.uu.net
Wed Jul 19 19:12:40 AEST 1989


Submitted-by: Mark Moraes <moraes at ai.toronto.edu>
Posting-number: Volume 4, Issue 59
Archive-name: xtroff/part14



#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 14 (of 18)."
# Contents:  xtroff/curves.c xtroff/suntroff.c
# Wrapped by moraes at neat.ai on Thu Jul 13 20:55:21 1989
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'xtroff/curves.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'xtroff/curves.c'\"
else
echo shar: Extracting \"'xtroff/curves.c'\" \(28272 characters\)
sed "s/^X//" >'xtroff/curves.c' <<'END_OF_FILE'
X/*
X *	SunTroff -  A program to display the output of Device Independent
X *		Troff as a window on a Sun Workstation.
X *
X *	Troff_curves.c - Code to draw the fancy curves needed in the
X *		ditroff spec.  Code written at Berkeley and cleaned up
X *		just a bit at SPAR.
X *
X *	Authors - The original version of this program was written by
X *			Richard L. Hyde (Purdue)
X *			David Slattengren (Berkeley)
X *		It was nearly all rewritten, cleaned up and a more elegant
X *		user interface installed by
X *			Malcolm Slaney (Schlumberger Palo Alto Research)
X *
X *	Legalese -  This command was developed as an independent project
X *		to satisfy a need of the author.  This program may contain
X *		bugs and the user is cautioned to independently verify that
X *		the program is suitable for the user's intended purpose.
X *		The program is made available on an ``as is'' basis with
X *		all faults and without any implied or expressed warranties
X *		or support from either the author, Malcolm Slaney, or
X *		Schlumberger Palo Alto Research Laboratory.
X *
X *		I am putting this program in the public domain.  You are
X *		free to use it as you wish.  In return I ask two things.
X *		First, that you do not remove the names of the authors
X *		from this work.  Secondly, if you make changes or
X *		improvements to this program that you pass these back to
X *		the author so that everybody can benefit from the
X *		improvements.
X *
X *					Malcolm Slaney  (December 1986)
X *					Schlumberger Palo Alto Research
X *					3340 Hillview Avenue
X *					Palo Alto, CA 94304
X *					(415) 496-4669
X *					spar!malcolm at decwrl.dec.com
X *					malcolm at ecn.purdue.edu
X *					malcolm at spar.slb.com (Someday)
X */
X
X/*
X *
X *	This file contains the functions for producing the graphics
X *   images in the sun driver for ditroff.
X */
X
X
X#include <stdio.h>
X#include <ctype.h>
X#include <math.h>
X#include "fixpoint.h"
X
X
X#define TRUE	1
X#define FALSE	0
X				/* imports from dver.c */
X#define  hmot(n)	HorizontalMove(n)
X#define  vmot(n)	VerticalMove(n)
X#define  vgoto(n)	VerticalGoto(n)
X
Xextern int HorizontalPosition;
Xextern int VerticalPosition;
Xextern int DisplayOutput;
Xextern point();
Xextern int scale();
X
X#define MAXPOINTS 200	/* number of points legal for a curve */
X
X#define SOLID -1	/* line styles:  these are used as bit masks to */
X#define DOTTED 004	/* create the right style lines. */
X#define DASHED 020
X#define DOTDASHED 024
X#define LONGDASHED 074
X				/* constants... */
X#define  pi		3.14159265358979324
X
X
Xint	linethickness = 1;	/* number of pixels wide to make lines */
Xint	linmod = SOLID;		/* type of line (SOLID, DOTTED, DASHED...) */
X
X
Xvoid
Xsetstip(n)
X    int n;
X{
X}
X
X/*----------------------------------------------------------------------------
X * Routine:	drawline (horizontal_motion, vertical_motion)
X *
X * Results:	Draws a line of "linethickness" width and "linmod" style
X *		from current (HorizontalPosition, VerticalPosition) to
X *		(HorizontalPosition + dh, VerticalPosition + dv).
X *
X * Side Efct:	Resulting position is at end of line (HorizontalPosition + dh,
X *							VerticalPosition + dv)
X *----------------------------------------------------------------------------*/
X
Xdrawline(dh, dv)
Xregister int dh;
Xregister int dv;
X{
X    if (DisplayOutput) {
X	    HGtline (HorizontalPosition, VerticalPosition,
X		     HorizontalPosition + dh, VerticalPosition + dv);
X    }
X    hmot (dh);					/* new position is at */
X    vmot (dv);					/* the end of the line */
X}
X
X
X/*----------------------------------------------------------------------------
X * Routine:	DrawCircle (diameter)
X *
X * Results:	Draws a circle with leftmost point at current
X *		(HorizontalPosition, VerticalPosition)
X *		with the given diameter d.  Does a thick line by calling
X *		RoundEnd many times with varying radii.
X *
X * Side Efct:	Resulting position is at (HorizontalPosition + diameter,
X *						VerticalPosition)
X *----------------------------------------------------------------------------*/
X
XDrawCircle(d)
Xint d;
X{
X    register int delta_rad;
X    register int limit;
X    register int radius;
X
X
X    if (DisplayOutput) {
X	radius = Scale(d) / 2;
X	delta_rad = radius - linethickness / 2;
X	limit = radius + (linethickness - 1) / 2;
X	while (delta_rad <= limit) {
X	    RoundEnd (Scale(HorizontalPosition)+radius,
X		      Scale(VerticalPosition), delta_rad, FALSE);
X	    delta_rad++;
X	}
X    }
X
X    hmot (d);
X}
X
X
X/*----------------------------------------------------------------------------
X * Routine:	DrawEllipse(horizontal_diameter, vertical_diameter)
X *
X * Results:	Draws regular ellipses given the major "diameters."  It does
X *		so using a modified circle algorithm (see RoundEnd) that
X *		increments x and y proportionally to their axes.
X *
X * Side Efct:	Resulting position is at (HorizontalPosition + hd,
X *						VerticalPosition).
X *---------------------------------------------------------------------------*/
X
XDrawEllipse(hd, vd)
Xint hd;
Xint vd;
X{
X    fixed xs, ys, xepsilon, yepsilon;
X    int thick;
X    register int basex;
X    register int basey;
X    register int x;
X    register int y;
X
X    					/* bases == coordinates of center */
X    basex = Scale(HorizontalPosition + (hd >> 1));	
X    hmot(hd);				/* horizontal motion */
X    					/*   (HorizontalPosition should */
X					/*   NOT be used after this) */
X    basey = Scale(VerticalPosition);	
X					/* hd and vd are radii, not diameters*/
X    if ((hd=Scale(hd >> 1)) < 1) hd++;	/* neither diameter can be zero. */
X    if ((vd=Scale(vd >> 1)) < 1) vd++;	/*   hd changed!! no hmot after this */
X    ys = ffix(vd);			/* start at top of the ellipse */
X    xs = ffix(0);			/*   (y = 1/2 diameter, x = 0) */
X
X    if ((thick = vd) > hd) thick = hd;
X    xepsilon = ffixd((double) thick / (double) (vd * vd));
X    yepsilon = ffixd((double) thick / (double) (hd * hd));
X
X		/* Calculate trajectory of the ellipse for 1/4	*/
X		/* the circumference (while ys is non-negative)	*/
X		/* and mirror to get the other three quadrants.	*/
X
X    thick = linethickness / 2;
X    if (thick) {		/* more than one pixel thick */
X	RoundEnd(basex, fintr(ys) + basey, thick, 0);
X	RoundEnd(basex, basey - fintr(ys), thick, 0);
X	while (ys >= 0) {
X	    xs += fmult(xepsilon, ys);	/* generate circumference */
X	    ys -= fmult(yepsilon, xs);
X	    x = fintr(xs);
X	    y = fintr(ys);
X	    RoundEnd(x + basex, y + basey, thick, 0);
X	    RoundEnd(x + basex, basey - y, thick, 0);
X	    RoundEnd(basex - x, y + basey, thick, 0);
X	    RoundEnd(basex - x, basey - y, thick, 0);
X	}
X    } else {		/* do the perimeter only (no fill) */
X	point(basex, fintr(ys) + basey);
X	point(basex, basey - fintr(ys));
X	while (ys >= 0) {
X	    xs += fmult(xepsilon, ys);	/* generate circumference */
X	    ys -= fmult(yepsilon, xs);
X	    x = fintr(xs);
X	    y = fintr(ys);
X	    point(x + basex, y + basey);
X	    point(x + basex, basey - y);
X	    point(basex - x, y + basey);
X	    point(basex - x, basey - y);
X        }
X    }
X}
X
X
X/*----------------------------------------------------------------------------
X * Routine:	DrawArc (xcenter, ycenter, xpoint, ypoint)
X *
X * Results:	Draws an arc starting at current (HorizontalPosition,
X *		VerticalPosition).  Center is at (HorizontalPosition + cdh,
X *		VerticalPosition + cdv) and the terminating point is
X *		at <center> + (pdh, pdv).  The angle between the lines
X *		formed by the starting, ending, and center points is figured
X *		first, then the points and angle are sent to HGArc for the
X *		drawing.
X *
X * Side Efct:	Resulting position is at the last point of the arc.
X *---------------------------------------------------------------------------*/
X
XDrawArc(cdh, cdv, pdh, pdv)
Xregister int cdh;
Xregister int cdv;
Xregister int pdh;
Xregister int pdv;
X{
X    register double angle;
X				/* figure angle from the three points...*/
X				/* and convert (and round) to degrees */
X    angle = (atan2((double) pdh, (double) pdv)
X		- atan2 ((double) -cdh, (double) -cdv)) * 180.0 / pi;
X				/* "normalize" and round */
X    angle += (angle < 0.0)  ?  360.5 : 0.5;
X
X    if (DisplayOutput) {
X	    HGArc(HorizontalPosition + cdh, VerticalPosition + cdv,
X		  HorizontalPosition, VerticalPosition, (int) angle);
X    }
X    hmot(cdh + pdh);
X    vmot(cdv + pdv);
X}
X
X
X/*----------------------------------------------------------------------------
X * Routine:	DrawSpline (character_buffer, type_flag)
X *
X * Results:	Given the starting position, the motion list in buf, and any
X *		extra characters from the file (terminated by a \n), drawwig
X *		sets up a point list to make a spline from.  If "pic" is set
X *		picurve is called to draw the curve in pic style; else it
X *		calls HGCurve for the gremlin-style curve.
X *
X * Side Efct:	Resulting position is reached from adding successive motions
X *		to the current position.
X *---------------------------------------------------------------------------*/
X
XDrawSpline(buf, pic)
Xchar *buf;
Xint pic;
X{
X    register int len = strlen(buf);	/* length of the string in "buf" */
X    register int npts = 1;		/* point list index */
X    register char *ptr = buf;		/* "walking" pointer into buf */
X    int x[MAXPOINTS], y[MAXPOINTS];	/* point list */
X    extern char *GetLine();
X
X    while (*ptr == ' ') ptr++;		/* skip any leading spaces */
X    x[1] = HorizontalPosition;		/* the curve starts at the */
X    y[1] = VerticalPosition;		/* current position */
X					/* curve commands end with a '\n' */
X    while (*ptr != '\n' && *ptr != NULL) {
X	if (npts < (MAXPOINTS - 1))	/* if too many points, forget some */
X	    npts++;
X	hmot(atoi(ptr));		/* convert motion to curve points */
X	x[npts] = HorizontalPosition;			/* and remember them */
X	while (isdigit(*++ptr));		/* skip number*/
X	while (*++ptr == ' ');		/* skip spaces 'tween numbers */
X	vmot(atoi(ptr));
X	y[npts] = VerticalPosition;
X	while (isdigit(*++ptr));
X	while (*ptr == ' ') ptr++;
X				/* if the amount we read wasn't the */
X		 		/*    whole thing, read some more in */
X	if (len - (ptr - buf) < 15 && *(buf + len - 1) != '\n') {
X	    char *cop = buf;
X
X	    while (*cop++ = *ptr++);	/* copy what's left to the beginning */
X	    (void) GetLine(cop-1, len-(cop-buf));
X	    printf("The rest of the line is :\n***%s***\n", cop-1);
X	    ptr = buf;
X	}
X    }
X				/* now, actually DO the curve */
X    if (DisplayOutput) {
X	if (pic > 0)
X	    picurve(x, y, npts);
X	else if (!pic)
X	    HGCurve(x, y, npts);
X	else
X	    polygon(x, y, npts);
X    }
X}
X
X/*ARGSUSED*/
Xpolygon(x,y,npts)
Xint *x;
Xint *y;
Xint npts;
X{
X}
X
X
X/*----------------------------------------------------------------------------*
X | Routine:	drawthick (thickness)
X |
X | Results:	sets the variable "linethickness" to the given size.
X |		NO motion is involved.
X *---------------------------------------------------------------------------*/
X
Xdrawthick(s)
Xint s;
X{
X    if ((linethickness = Scale(s)) < 1) linethickness = 1;
X}
X
X
X/*----------------------------------------------------------------------------*
X | Routine:	drawstyle (style_bit_map)
X |
X | Results:	sets the variable "linmod" to the given bit map.
X |		NO motion is involved.
X *---------------------------------------------------------------------------*/
X
Xdrawstyle(s)
Xint s;
X{
X    linmod = s;
X}
X
X
X/*----------------------------------------------------------------------------
X * Routine:	picurve (xpoints, ypoints, num_of_points)
X *
X * Results:	Draws a curve delimited by (not through) the line segments
X *		traced by (xpoints, ypoints) point list.  This is the "Pic"
X *		style curve.
X *---------------------------------------------------------------------------*/
X
Xpicurve (x, y, npts)
Xint x[MAXPOINTS];
Xint y[MAXPOINTS];
Xint npts;
X{
X    register int i;		/* line segment traverser */
X    register fixed nseg;	/* effective resolution for each curve */
X    register fixed w;		/* position factor */
X    register int xp;		/* current point (and intermediary) */
X    register int yp;
X    int pxp, pyp;		/* previous point (to make lines from) */
X    fixed t1, t2, t3;		/* calculation temps */
X    fixed j;			/* inner curve segment traverser */
X
X
X    if (x[1] == x[npts] && y[1] == y[npts]) {
X	x[0] = x[npts - 1];		/* if the lines' ends meet, make */
X	y[0] = y[npts - 1];		/* sure the curve meets */
X	x[npts + 1] = x[2];
X	y[npts + 1] = y[2];
X    } else {				/* otherwise, make the ends of the */
X	x[0] = x[1];			/* curve touch the ending points of */
X	y[0] = y[1];			/* the line segments */
X	x[npts + 1] = x[npts];
X	y[npts + 1] = y[npts];
X    }
X
X    pxp = (x[0] + x[1]) / 2;		/* make the last point pointers */
X    pyp = (y[0] + y[1]) / 2;		/* point to the start of the 1st line*/
X
X    for (i = 0; i < npts; i++) {	/* traverse the line segments */
X	xp = x[i] - x[i+1];
X	yp = y[i] - y[i+1];
X	nseg = ffixd(sqrt((double)(xp * xp + yp * yp)) / (20.0));
X	xp = x[i+1] - x[i+2];
X	yp = y[i+1] - y[i+2];		/* "nseg" is the number of line */
X					/* segments that will be drawn for */
X					/* each curve segment.  The division */
X					/* is there to get better performace */
X					/* by sacrificing resolution */
X	nseg += ffixd(sqrt((double)(xp * xp + yp * yp)) / (20.0));
X
X	for (j = ffix(1); j < nseg; j += ffix(1)) {
X	    w = fdiv(j, nseg);
X	    t1 = fmult(ffixd(0.5), fmult(w, w));
X	    w -= ffixd(0.5);
X	    t2 = ffixd(0.75) - fmult(w, w);
X	    w -= ffixd(0.5);
X	    t3 = fmult(ffixd(0.5), fmult(w, w));
X	    xp = fintr(fmult(t1, ffix(x[i+2]))
X			+ fmult(t2, ffix(x[i+1])) + fmult(t3, ffix(x[i])));
X	    yp = fintr(fmult(t1, ffix(y[i+2]))
X			+ fmult(t2, ffix(y[i+1])) + fmult(t3, ffix(y[i])));
X	    HGtline(pxp, pyp, xp, yp);
X	    pxp = xp;
X	    pyp = yp;
X	}
X    }
X}
X
X
X/*----------------------------------------------------------------------------
X * Routine:	HGtline(xstart, ystart, xend, yend)
X *
X * Results:	Draws a line of proper thickness (specified in linethickness).
X *		Scales its points before doing the line - NO scaling should
X *		be done before calling this routine.
X *---------------------------------------------------------------------------*/
X
X
XHGtline(xs, ys, xe, ye)
X{
X    register int x0;	/* starting point and line-walking registers */
X    register int y0;
X    int dx;		/* parameters in the line calculations */
X    int dy;
X    register int res;
X    int xinc;
X    int yinc;
X    int x1;		/* end-point of the line */
X    int y1;
X    int radius;
X    int top;		/* how much to bleed line in "up" (left) direction */
X    int bottom;		/* how much to bleed line in "down" (right) direction */
X    int stop1;		/* place to stop making circles at start of line */
X    int stop2;		/* place to start making circles at end of line */
X    int halfstop;	/* distance tween stop1 and stop3 */
X    int stop3;		/* midpoint `tween making circles and lines */
X    register int i;	/* line-bleeding carrier */
X
X
X    x0 = Scale(xs);	/* convert endpoints to SUN coordinates */
X    y0 = Scale(ys);
X    x1 = Scale(xe);
X    y1 = Scale(ye);
X
X    xinc = 1;
X    yinc = 1;
X    if ((dx = x1-x0) < 0) {
X        xinc = -1;
X        dx = -dx;
X    }
X    if ((dy = y1-y0) < 0) {
X        yinc = -1;
X        dy = -dy;
X    }
X
X    radius = (linethickness - 1) / 2;
X    RoundEnd(x0, y0, radius, TRUE);	/* add ends of line */
X    RoundEnd(x1, y1, radius, TRUE);	/* (nice and curvy) */
X
X    top = linethickness;	/* increase line thickness if at an angle */
X    stop1 = halfstop = 0;
X    if ((i = (int) (sqrt ((double) (dx * dx + dy * dy)) + 0.01)) < 2)
X	return;			/* small lines are done with endpoints */
X    if (dx >= dy) {
X	top = (linethickness * i) / dx;
X	stop1 = (linethickness * dy) / (i + 1);
X	halfstop = (radius * dy) / i;
X    } else {
X	top = (linethickness * i) / dy;
X	stop1 = (linethickness * dx) / (i + 1);
X	halfstop = (radius * dx) / i;
X    }
X    bottom = (top - 1) / 2;
X    top = top / 2;
X
X    if (dx >= dy) {
X	res = (dy >> 1) - (dx >> 1);
X	if (linethickness >= i) {
X	    stop1 = stop2 = x0;
X	    halfstop = i + 1;
X	} else if (xinc == 1) {
X	    stop2 = x1 - stop1;
X	    stop1 = x0 + stop1;
X	    stop3 = x0 + halfstop;
X	} else {
X	    stop2 = x1 + stop1;
X	    stop1 = x0 - stop1;
X	    stop3 = x0 - halfstop;
X	}
X
X	while (x0 != stop1) {
X	    RoundEnd(x0, y0, radius, FALSE);
X            if ((x0&linmod) && (xinc == 1 ? x0 > stop3 : x0 < stop3))
X		for (i = y0 - top; i <= y0 + bottom; i++)
X		    point(x0, i);
X            if (res >= 0) {
X                res -= dx;
X                y0 += yinc;
X            }
X            res += dy;
X            x0 += xinc;
X	}
X        while (x0 != stop2) {
X            if (x0&linmod)
X		for (i = y0 - top; i <= y0 + bottom; i++)
X		    point(x0, i);
X            if (res >= 0) {
X                res -= dx;
X                y0 += yinc;
X            }
X            res += dy;
X            x0 += xinc;
X        } 
X	stop3 = x1 + (xinc == 1 ? -halfstop : halfstop);
X        while (x0 != x1) {
X	    RoundEnd(x0, y0, radius, FALSE);
X            if ((x0&linmod) && (xinc == 1 ? x0 < stop3 : x0 > stop3))
X		for (i = y0 - top; i <= y0 + bottom; i++)
X		    point(x0, i);
X            if (res >= 0) {
X                res -= dx;
X                y0 += yinc;
X            }
X            res += dy;
X            x0 += xinc;
X        } 
X    } else {
X	res = (dx >> 1) - (dy >> 1);
X	if (linethickness >= i) {
X	    stop1 = stop2 = y0;
X	    halfstop = i + 1;
X	} else if (yinc == 1) {
X	    stop2 = y1 - stop1;
X	    stop1 = y0 + stop1;
X	    stop3 = y0 + halfstop;
X	} else {
X	    stop2 = y1 + stop1;
X	    stop1 = y0 - stop1;
X	    stop3 = y0 - halfstop;
X	}
X
X        while (y0 != stop1) {
X	    RoundEnd(x0, y0, radius, FALSE);
X            if ((y0&linmod) && (yinc == 1 ? y0 > stop3 : y0 < stop3))
X		for (i = x0 - top; i <= x0 + bottom; i++)
X		    point(i, y0);
X            if (res >= 0) {
X                res -= dy;
X                x0 += xinc;
X            }
X	    res += dx;
X            y0 += yinc;
X        }
X        while (y0 != stop2) {
X            if (y0&linmod)
X		for (i = x0 - top; i <= x0 + bottom; i++)
X		    point(i, y0);
X            if (res >= 0) {
X                res -= dy;
X                x0 += xinc;
X            }
X	    res += dx;
X            y0 += yinc;
X        }
X	stop3 = y1 + (yinc == 1 ? -halfstop : halfstop);
X        while (y0 != y1) {
X	    RoundEnd(x0, y0, radius, FALSE);
X            if ((y0&linmod) && (yinc == 1 ? y0 < stop3 : y0 > stop3))
X		for (i = x0 - top; i <= x0 + bottom; i++)
X		    point(i, y0);
X            if (res >= 0) {
X                res -= dy;
X                x0 += xinc;
X            }
X	    res += dx;
X            y0 += yinc;
X        }
X    }
X}
X
X
X/*----------------------------------------------------------------------------
X * Routine:	HGArc (xcenter, ycenter, xstart, ystart, angle)
X *
X * Results:	This routine plots an arc centered about (cx, cy) counter
X *		clockwise starting from the point (px, py) through 'angle'
X *		degrees.  If angle is 0, a full circle is drawn.
X *		It does so by calling RoundEnd (fat point maker) for points
X *		along the circle with density depending on the circle's size.
X *		The points that define the circle are Scaled before doing
X *		the actual drawing.  No scaling should be done before calling
X *		this routine.
X *---------------------------------------------------------------------------*/
X
XHGArc(cx,cy,px,py,angle)
Xregister int cx;
Xregister int cy;
Xint px;
Xint py;
Xint angle;
X{
X    double resolution, fullcircle;
X    int extent;
X    int halfline;
X    fixed epsilon;
X    register fixed xs;
X    register fixed ys;
X
X
X    halfline = linethickness / 2;
X
X    cx = Scale(cx);		/* set points to sun's res. before drawing */
X    cy = Scale(cy);
X    px = Scale(px);
X    py = Scale(py);
X
X    px -= cx;		/* px, py are equal to change in x and y from */
X    py -= cy;		/* center to starting point */
X
X/* calculate drawing parameters */
X
X    resolution = sqrt((double)(px * px + py * py));
X    fullcircle = ceil(2.0 * pi * resolution);
X    epsilon = ffixd(1.0 / resolution);
X    xs = ffix(px);
X    ys = ffix(py);
X
X    if (angle == 0)		/* calculate how long to do the arc */
X	extent = (int) fullcircle;
X    else
X	extent = (int) (fullcircle * (double) angle / 360.0);
X    if (extent < 1) extent = 1;
X
X    if (halfline < 1) {
X	do {
X	    xs += fmult(epsilon, ys);
X	    ys -= fmult(epsilon, xs);
X	    point(fintr(xs) + cx, fintr(ys) + cy);
X	} while (--extent);
X    } else {
X	do {
X	    xs += fmult(epsilon, ys);
X	    ys -= fmult(epsilon, xs);
X	    RoundEnd(cx + fintr(xs), cy + fintr(ys), halfline, FALSE);
X	} while (--extent);
X    }
X}  /* end HGArc */
X
X
X/*----------------------------------------------------------------------------
X * Routine:	RoundEnd (x, y, radius, filled_flag)
X *
X * Results:	Plots a filled (if requested) circle of the specified radius
X *		centered about (x, y).
X *---------------------------------------------------------------------------*/
X
XRoundEnd(x, y, radius, filled)
Xregister int x;
Xregister int y;
Xint radius, filled;
X{
X    fixed xs, ys, epsilon;
X    register int j;
X    register int k;
X
X
X    point(x, y + radius);	/* do the starting point of the circle */
X    if (radius < 1) return;	/* if circle is tiny, quit now */
X    point(x, y - radius);
X
X		/* Calculate trajectory of the circle for 1/4	*/
X		/* the circumference (while ys is positive) and	*/
X		/* mirror to get the other three quadrants.	*/
X
X    xs = ffix(0);
X    ys = ffix(radius);
X    epsilon = fdiv(ffix(1), ys);
X
X    while (ys >= 0) {
X	j = fintr(xs);
X	k = fintr(ys);
X        if (filled) {		/* fill from center */
X	    do {
X		point(j+x, k+y);
X		point(j+x, y-k);
X		point(x-j, k+y);
X		point(x-j, y-k);
X	    } while (--k >= 0);
X        } else {		/* do the perimeter only (no fill) */
X	    point(j+x, k+y);
X	    point(j+x, y-k);
X	    point(x-j, k+y);
X	    point(x-j, y-k);
X        }
X        xs += fmult(epsilon, ys);	/* generate circumference */
X        ys -= fmult(epsilon, xs);
X    }
X}  /* end RoundEnd */;
X
X
X/*----------------------------------------------------------------------------
X * Routine:	Paramaterize (xpoints, ypoints, hparams, num_points)
X *
X * Results:	This routine calculates parameteric values for use in
X *		calculating curves.  The parametric values are returned
X *		in the array h.  The values are an approximation of
X *		cumulative arc lengths of the curve (uses cord length).
X *		For additional information, see paper cited below.
X *---------------------------------------------------------------------------*/
X
Xstatic Paramaterize(x, y, h, n)
Xint x[MAXPOINTS];
Xint y[MAXPOINTS];
Xfloat h[MAXPOINTS];
Xint n;
X{
X	register int dx;
X	register int dy;
X	register int i;
X	register int j;
X	float u[MAXPOINTS];
X
X
X	for (i=1; i<=n; ++i) {
X	    u[i] = 0;
X	    for (j=1; j<i; j++) {
X		dx = x[j+1] - x[j];
X		dy = y[j+1] - y[j];
X		u[i] += sqrt ((double) (dx * dx + dy * dy));
X	    }
X	}
X	for (i=1; i<n; ++i)  h[i] = u[i+1] - u[i];
X}  /* end Paramaterize */
X
X
X/*----------------------------------------------------------------------------
X * Routine:	PeriodicSpline (h, z, dz, d2z, d3z, npoints)
X *
X * Results:	This routine solves for the cubic polynomial to fit a
X *		spline curve to the the points  specified by the list
X *		of values.  The Curve generated is periodic.  The algorithms
X *		for this curve are from the "Spline Curve Techniques" paper
X *		cited below.
X *---------------------------------------------------------------------------*/
X
Xstatic PeriodicSpline(h, z, dz, d2z, d3z, npoints)
Xfloat h[MAXPOINTS];		/* paramaterization  */
Xint z[MAXPOINTS];		/* point list */
Xfloat dz[MAXPOINTS];			/* to return the 1st derivative */
Xfloat d2z[MAXPOINTS], d3z[MAXPOINTS];	/* 2nd and 3rd derivatives */
Xint npoints;				/* number of valid points */
X{
X	float d[MAXPOINTS]; 
X	float deltaz[MAXPOINTS], a[MAXPOINTS], b[MAXPOINTS];
X	float c[MAXPOINTS], r[MAXPOINTS], s[MAXPOINTS];
X	int i;
X
X						/* step 1 */
X	for (i=1; i<npoints; ++i) {
X	    deltaz[i] = h[i] ? ((double) (z[i+1] - z[i])) / h[i] : 0;
X	}
X	h[0] = h[npoints-1];
X	deltaz[0] = deltaz[npoints-1];
X
X						/* step 2 */
X	for (i=1; i<npoints-1; ++i) {
X	    d[i] = deltaz[i+1] - deltaz[i];
X	}
X	d[0] = deltaz[1] - deltaz[0];
X
X						/* step 3a */
X	a[1] = 2 * (h[0] + h[1]);
X	b[1] = d[0];
X	c[1] = h[0];
X	for (i=2; i<npoints-1; ++i) {
X	    a[i] = 2*(h[i-1]+h[i]) - pow ((double) h[i-1],(double)2.0) / a[i-1];
X	    b[i] = d[i-1] - h[i-1] * b[i-1]/a[i-1];
X	    c[i] = -h[i-1] * c[i-1]/a[i-1];
X	}
X
X						/* step 3b */
X	r[npoints-1] = 1;
X	s[npoints-1] = 0;
X	for (i=npoints-2; i>0; --i) {
X	    r[i] = -(h[i] * r[i+1] + c[i])/a[i];
X	    s[i] = (6 * b[i] - h[i] * s[i+1])/a[i];
X	}
X
X						/* step 4 */
X	d2z[npoints-1] = (6 * d[npoints-2] - h[0] * s[1] 
X	                   - h[npoints-1] * s[npoints-2]) 
X	                 / (h[0] * r[1] + h[npoints-1] * r[npoints-2] 
X	                    + 2 * (h[npoints-2] + h[0]));
X	for (i=1; i<npoints-1; ++i) {
X	    d2z[i] = r[i] * d2z[npoints-1] + s[i];
X	}
X	d2z[npoints] = d2z[1];
X
X						/* step 5 */
X	for (i=1; i<npoints; ++i) {
X	    dz[i] = deltaz[i] - h[i] * (2 * d2z[i] + d2z[i+1])/6;
X	    d3z[i] = h[i] ? (d2z[i+1] - d2z[i])/h[i] : 0;
X	}
X}  /* end PeriodicSpline */
X
X
X/*----------------------------------------------------------------------------
X * Routine:	NaturalEndSpline (h, z, dz, d2z, d3z, npoints)
X *
X * Results:	This routine solves for the cubic polynomial to fit a
X *		spline curve the the points  specified by the list of
X *		values.  The alogrithms for this curve are from the
X *		"Spline Curve Techniques" paper cited below.
X *---------------------------------------------------------------------------*/
X
Xstatic NaturalEndSpline(h, z, dz, d2z, d3z, npoints)
Xfloat h[MAXPOINTS];		/* parameterization */
Xint z[MAXPOINTS];		/* Point list */
Xfloat dz[MAXPOINTS];			/* to return the 1st derivative */
Xfloat d2z[MAXPOINTS], d3z[MAXPOINTS];	/* 2nd and 3rd derivatives */
Xint npoints;				/* number of valid points */
X{
X	float d[MAXPOINTS];
X	float deltaz[MAXPOINTS], a[MAXPOINTS], b[MAXPOINTS];
X	int i;
X
X						/* step 1 */
X	for (i=1; i<npoints; ++i) {
X	    deltaz[i] = h[i] ? ((double) (z[i+1] - z[i])) / h[i] : 0;
X	}
X	deltaz[0] = deltaz[npoints-1];
X
X						/* step 2 */
X	for (i=1; i<npoints-1; ++i) {
X	    d[i] = deltaz[i+1] - deltaz[i];
X	}
X	d[0] = deltaz[1] - deltaz[0];
X
X						/* step 3 */
X	a[0] = 2 * (h[2] + h[1]);
X	b[0] = d[1];
X	for (i=1; i<npoints-2; ++i) {
X	    a[i] = 2*(h[i+1]+h[i+2]) - pow((double) h[i+1],(double) 2.0)/a[i-1];
X	    b[i] = d[i+1] - h[i+1] * b[i-1]/a[i-1];
X	}
X
X						/* step 4 */
X	d2z[npoints] = d2z[1] = 0;
X	for (i=npoints-1; i>1; --i) {
X	    d2z[i] = (6 * b[i-2] - h[i] *d2z[i+1])/a[i-2];
X	}
X
X						/* step 5 */
X	for (i=1; i<npoints; ++i) {
X	    dz[i] = deltaz[i] - h[i] * (2 * d2z[i] + d2z[i+1])/6;
X	    d3z[i] = h[i] ? (d2z[i+1] - d2z[i])/h[i] : 0;
X	}
X}  /* end NaturalEndSpline */
X
X
X/*----------------------------------------------------------------------------
X * Routine:	HGCurve(xpoints, ypoints, num_points)
X *
X * Results:	This routine generates a smooth curve through a set of points.
X *		The method used is the parametric spline curve on unit knot
X *		mesh described in "Spline Curve Techniques" by Patrick
X *		Baudelaire, Robert Flegal, and Robert Sproull -- Xerox Parc.
X *---------------------------------------------------------------------------*/
X
X#define POINTSPERINTERVAL 16
X
XHGCurve(x, y, numpoints)
Xint x[MAXPOINTS];
Xint y[MAXPOINTS];
Xint numpoints;
X{
X	float h[MAXPOINTS], dx[MAXPOINTS], dy[MAXPOINTS];
X	float d2x[MAXPOINTS], d2y[MAXPOINTS], d3x[MAXPOINTS], d3y[MAXPOINTS];
X	float t, t2, t3;
X	register int j;
X	register int k;
X	register int nx;
X	register int ny;
X	int lx, ly;
X	int PointsPerInterval;
X
X
X	lx = x[1];
X	ly = y[1];
X	PointsPerInterval = POINTSPERINTERVAL / (9999 / Scale(10000) + 1);
X
X	     /* Solve for derivatives of the curve at each point 
X              * separately for x and y (parametric).
X	      */
X	Paramaterize(x, y, h, numpoints);
X							/* closed curve */
X	if ((x[1] == x[numpoints]) && (y[1] == y[numpoints])) {
X	    PeriodicSpline(h, x, dx, d2x, d3x, numpoints);
X	    PeriodicSpline(h, y, dy, d2y, d3y, numpoints);
X	} else {
X	    NaturalEndSpline(h, x, dx, d2x, d3x, numpoints);
X	    NaturalEndSpline(h, y, dy, d2y, d3y, numpoints);
X	}
X
X	      /* generate the curve using the above information and 
X	       * PointsPerInterval vectors between each specified knot.
X	       */
X
X	for (j=1; j<numpoints; ++j) {
X	    if ((x[j] == x[j+1]) && (y[j] == y[j+1])) continue;
X	    for (k=0; k<=PointsPerInterval; ++k) {
X		t = (float) k * h[j] / (float) PointsPerInterval;
X		t2 = t * t;
X		t3 = t * t2;
X		nx = x[j] + (int)(t * dx[j] + t2 * d2x[j]/2 + t3 * d3x[j]/6);
X		ny = y[j] + (int)(t * dy[j] + t2 * d2y[j]/2 + t3 * d3y[j]/6);
X		HGtline(lx, ly, nx, ny);
X		lx = nx;
X		ly = ny;
X	    }  /* end for k */
X	}  /* end for j */
X}  /* end HGCurve */
END_OF_FILE
if test 28272 -ne `wc -c <'xtroff/curves.c'`; then
    echo shar: \"'xtroff/curves.c'\" unpacked with wrong size!
fi
# end of 'xtroff/curves.c'
fi
if test -f 'xtroff/suntroff.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'xtroff/suntroff.c'\"
else
echo shar: Extracting \"'xtroff/suntroff.c'\" \(23976 characters\)
sed "s/^X//" >'xtroff/suntroff.c' <<'END_OF_FILE'
X/*
X *	SunTroff -  A program to display the output of Device Independent
X *		Troff as a window on a Sun Workstation.
X *
X *	Suntroff - Code to interface the rather generic user interface
X *		provided by windows.c and the low level troff parsing 
X *		and drawing routines.
X *
X *	Authors - The original version of this program was written by
X *			Richard L. Hyde (Purdue)
X *			David Slattengren (Berkeley)
X *		It was nearly all rewritten, cleaned up and a more elegant
X *		user interface installed by
X *			Malcolm Slaney (Schlumberger Palo Alto Research)
X *		Write characters as words
X *			David Cahlander (Cray Research, Inc.)
X *
X *	Legalese -  This command was developed as an independent project
X *		to satisfy a need of the author.  This program may contain
X *		bugs and the user is cautioned to independently verify that
X *		the program is suitable for the user's intended purpose.
X *		The program is made available on an ``as is'' basis with
X *		all faults and without any implied or expressed warranties
X *		or support from either the author, Malcolm Slaney, or
X *		Schlumberger Palo Alto Research Laboratory.
X *
X *		I am putting this program in the public domain.  You are
X *		free to use it as you wish.  In return I ask two things.
X *		First, that you do not remove the names of the authors
X *		from this work.  Secondly, if you make changes or
X *		improvements to this program that you pass these back to
X *		the author so that everybody can benefit from the
X *		improvements.
X *
X *					Malcolm Slaney  (December 1986)
X *					Schlumberger Palo Alto Research
X *					3340 Hillview Avenue
X *					Palo Alto, CA 94304
X *					(415) 496-4669
X *					spar!malcolm at decwrl.dec.com
X *					malcolm at ecn.purdue.edu
X *					malcolm at spar.slb.com (Someday)
X */
X
X#include	"suntroff.h"
X#ifdef SUNTOOLS
X#include	<suntool/sunview.h>
X#endif SUNTOOLS
X#define	MAXPAGES	500		        /* Pages to remember */
X
Xstatic FILE *CurrentFilePointer;		/* Current input file. */
Xstatic FILE *RealBufferPointer;	    		/* Buffer file pointer */
Xstatic FILE *RealFilePointer;			/* Real File Pointer */
X
Xstatic long PagePlace[MAXPAGES];		/* Remembered ftell
X						   positions */
Xstatic int MaxPage = 0;			/* Number of remembered positions */
X
X
X					/* TYPESETTER ENVIRONMENT VARIABLES */
Xint	size = 1;			/* Current Font Size (internal
X					   pstable index) */
Xfloat	ditsiz;				/* Current Font Scale (special troff
X					   characters) */
Xint	font = 1;			/* Current Font (internal font
X					   number */
Xint	linmod;				/* Line Style....unused. */
X
Xint	linethickness;			/* unused */
X
Xint	HorizontalPosition;		/* Horizontal Position (Device
X					   Coordinates) */
Xint	VerticalPosition;		/* Vertical Position on the page
X					   (Device Coordinates) */
X
Xchar	DeviceName[11];			/* Output produced for this device */
X
Xint	DeviceResolution;		/* Output produced at this resolution*/
X
Xstruct FontBitStruct *CurrentFont = 0;	/* Pointer to the current font
X					   information. */
Xint	DisplayOutput = 1;		/* Don't display output (just parse)
X					   when this flag is zero. */
Xint	LineNumber = 0;			/* Input file line number */
X
Xextern	int SUNRES;			/* Resolution of display */
X
X#ifdef SUNTOOLS
Xchar	*DefaultTitle = "SUNTROFF (3.0) ";
X#else
Xchar	*DefaultTitle = "XTROFF (4.0) ";
X/*
X * We use this macro to pack two characters into an int, so we can test for
X * troff special characters efficiently. As long as we use PACK_TWO_CHARS for
X * both constants that we want to compare against, eg. PACK_TWO_CHARS('c',
X * 'i') for 'ci', as well as for variables, it should be portable. Idea from
X * Dave Cahlander <dac at cray.com>, portable implementation from Henry Spencer
X * <henry at utzoo.uucp>, Jeffrey Lee <jonah at db.toronto.edu>
X */
X#define	PACK_TWO_CHARS(c1, c2)	(((c1)<<8)|(c2))
X#endif
X
Xint	CurrentPage = 0;		/* Current Page in Input File */
X
Xint	LastPage = 0;			/* Last Page of input file */
X
XShowPage(PageNumber){
X	int	i;
X
X	if (!CurrentFilePointer){
X		warning("No file open for input.");
X		return(0);
X	}
X
X	if (PageNumber < 1)
X		PageNumber = 1;
X
X	if (LastPage && PageNumber > LastPage){
X		warning("There are only %d pages in\nthis document.",
X		      LastPage);
X		return(CurrentPage);
X	}
X
X	if (PageNumber < MAXPAGES){
X		if (PagePlace[PageNumber]){
X			FileSeek(PagePlace[PageNumber]);
X			CurrentPage = PageNumber;
X		} else {
X			for (i=PageNumber;i>0 && !PagePlace[i];i--)
X				;
X			FileSeek(PagePlace[i]);
X			
X			SetTitleBar("Skipping",i);
X			DisplayOutput = 0;
X			while (!feof(CurrentFilePointer) &&
X			       ((CurrentPage = ParseInput()) != PageNumber))
X				;
X		}
X		DisplayOutput = 1;
X		ClearPage();
X		SetTitleBar("Rasterizing",PageNumber);
X		CurrentPage = ParseInput();
X		RefreshPage();
X	}
X
X	if (LastPage && PageNumber > LastPage){
X		warning("There are only %d pages in\nthis document.",
X		      LastPage);
X		SetTitleBar("Displaying",CurrentPage);
X		return(CurrentPage);
X	}
X
X	SetTitleBar("Displaying",PageNumber);
X	return(PageNumber);
X}
X
X
XClearPagePositions(){
X	int	i;
X
X	for (i=0;i<MAXPAGES;i++){
X		PagePlace[i] = 0;
X	}
X	MaxPage = 0;
X}
X
X#ifdef SUNTOOLS
Xstatic short IconImage[] = {
X#include	"ditroff.icon"
X}; 
XDEFINE_ICON_FROM_IMAGE(DitroffIcon,IconImage);
X
XInitializeApplication(Frame,Canvas)
XWindow Frame, Canvas;
X{
X	window_set(Frame,
X		   FRAME_ICON,&DitroffIcon,
X		   0);
X	SetTitleBar("Initializing",0);
X}
X#endif SUNTOOLS
X	
X
XInitializeFile(RealFile, TempFile)
XFILE	*RealFile, *TempFile;
X{
X	CurrentFilePointer = RealFilePointer = RealFile;
X	RealBufferPointer = TempFile;
X	FileSeek(0L);
X	ClearPagePositions();
X	CurrentPage = LastPage = 0;
X}
X
XHorizontalMove(delta)
Xint	delta;
X{
X	HorizontalPosition += delta;
X}
X
XHorizontalGoto(NewPosition)
Xint	NewPosition;
X{
X	HorizontalPosition = NewPosition;
X}
X
XVerticalMove(delta)
Xint	delta;
X{
X	VerticalPosition += delta;
X}
X
XVerticalGoto(NewPosition)
Xint	NewPosition;
X{
X	VerticalPosition = NewPosition;
X}
X
X/*
X *  An attempt is made to gather characters up into words.  This
X *  produces a much better display since the individual characters
X *  in a word are separated by the space allocated for the character
X *  at this font size.  On the average, the position desired and
X *  the actual screen position will match, since the screen characters
X *  have the spacing described by the troff description file DESC.out.
X *  However, if the font has incorrect space or an incorrect discription
X *  file is used, this scheme will not work.  An error term is calculated
X *  that indicates the difference between where the character actually
X *  will be placed and the position required by cononical troff position
X *  file.  When this difference exceeds 3 pixels (arbitrary) the
X *  assembled word is terminated and the next character is placed at
X *  the position designated by troff.
X *  Note that the troff position can be a fractional pixel while 
X *  the screen position must always be an integer.
X */
XPutCharacterString()
X{
X	char	string[100];
X	char	strch[100];
X	char	strpos[100];
X	int	i, n = 0;
X	int	c, ch, x, w;
X	float	xdelta, xerror;
X	char	**CodeTable, **AsciiTable;
X	
X	CodeTable = OutputTypesetter->CodeTable;
X	AsciiTable = OutputTypesetter->AsciiTable;
X
X	ch = GetChar();
X	if (ch < 32 || ch > 128 ||
X	 (AsciiTable[font] != NULL && AsciiTable[font][ch-32] == 0)) {
X		PutCharacter(ch);
X		return;
X	}
X	x = HorizontalPosition;
X	xerror = 0;
X	LoadFontBits();
X
X/*  character translation */
X	
X	strpos[n] = 0;
X	strch[n] = ch;
X	ch = CodeTable[font][AsciiTable[font][ch-32]&0xff];
X	string[n++] = ch;
X
X	while((c = GetChar()) != EOF) {
X		switch(c) {
X
X		case '\n':
X			LineNumber++;
X			break;
X		case '0': case '1': case '2': case '3': case '4':
X		case '5': case '6': case '7': case '8': case '9':
X			HorizontalMove(w = (c-'0')*10 + GetChar()-'0');
X			strpos[n] = w;
X			xdelta = CurrentFont->Bits->per_char[ch].width -
X			    (w * SUNRES) / (float)UserTypesetter->Device.res;
X			xerror += xdelta;
X#ifdef	FONTDEBUG
X			printf("ch=%c d=%g e=%g\n", ch, xdelta, xerror);
X#endif	/* FONTDEBUG */
X			if (xdelta < -5) {
X				c = 'c';
X			} else {
X				ch = GetChar();
X
X/*  character translation */
X
X				strch[n] = ch;
X				ch = CodeTable[font][AsciiTable[font][ch-32]&0xff];
X				string[n++] = ch;
X				if (ch != 0)
X					break;
X				c = 'w';
X			}
X
X		default:
X/*
X * check cumulative error
X * The error should be less than .5 space on the wide side or
X * about 5 spaces on the narrow side.  The canned numbers of
X * 5 pixels and 50 pixels may also be O.K.
X */
X			if (xerror > 5 || xerror < -50) {
X				HorizontalPosition = x;
X				for (i = 0; i < n; i++) {
X					HorizontalPosition += strpos[i];
X					PutCharacter(strch[i]&0xff);
X				}
X			} else {
X				string[n] = '\0';
X				PutString(x, string);
X			}
X			UnGetChar(c);
X			return;
X		}
X	}
X}
X
XPutString(x, string)
Xint	x;
Xchar	*string;
X{
X	if (!DisplayOutput)
X		return;
X	DrawString(x, VerticalPosition, string);
X}
X
XPutCharacter(c)
Xint	c;
X{
X	int	OldFont, i, cwidth;
X	char	**AsciiTable, *SpecialCharacterName, **CodeTable;
X	short	*SpecialCharacterNumber;
X	struct Font **FontInformation;
X	struct dev *Device;
X
X	AsciiTable = OutputTypesetter->AsciiTable;
X	SpecialCharacterNumber = OutputTypesetter->SpecialCharacterNumber;
X	SpecialCharacterName = OutputTypesetter->SpecialCharacterName;
X	CodeTable = OutputTypesetter->CodeTable;
X	FontInformation = OutputTypesetter->FontInformation;
X	Device = &OutputTypesetter->Device;
X
X
X	if (!DisplayOutput){
X		return;
X	}
X
X	if (c == ' ')				/* Spaces are easy */
X		return;
X	  
X	c -= 32;
X	if (c < 0 || c > 128-32+Device->nchtab){
X		warning(
X		      "Bad character (%d) passed to PutCharacter at line %d.\n"
X		      ,c+32,LineNumber);
X	}
X	
X	OldFont = font;
X
X	if (AsciiTable[font][c] == 0){			/* If its not in the
X							   table then look for
X							   it in the other 
X							   fonts. */
X		for (i=0;i<=Device->nfonts;i++){
X			if (!FontInformation)
X				continue;
X#ifdef	MAYBENOT			
X			if (!FontInformation[i]->specfont)
X				continue;
X#endif	MAYBENOT			
X			if (!AsciiTable[i])
X				continue;
X			if (AsciiTable[i][c])
X				break;
X		}
X		if (i <= Device->nfonts){
X			font = i;
X		        VirtualLoadFont(FontInformation[i]->namefont, size);
X		} else {
X			char *s = &SpecialCharacterName[SpecialCharacterNumber[c+32-128]];
X			switch(PACK_TWO_CHARS(s[0], s[1])) {
X
X			case PACK_TWO_CHARS('F', 'i'):
X				PutString(HorizontalPosition, "ffi");
X				return;
X
X			case PACK_TWO_CHARS('F', 'l'):
X				PutString(HorizontalPosition, "ffl");
X				return;
X
X			case PACK_TWO_CHARS('f', 'i'):
X				PutString(HorizontalPosition, "fi");
X				return;
X
X			case PACK_TWO_CHARS('f', 'f'):
X				PutString(HorizontalPosition, "ff");
X				return;
X
X			case PACK_TWO_CHARS('f', 'l'):
X				PutString(HorizontalPosition, "fl");
X				return;
X
X			default:
X				warning(
X				      "Can't find (%s)%d in %s character table.\n",
X				      &SpecialCharacterName[SpecialCharacterNumber[
X							     c+32-128]],
X				      c+32,
X				      OutputTypesetter->Name);
X				return;
X			}
X		}
X	}
X
X	LoadFontBits();
X
X#ifndef NOADJUST
X	/*
X	 *  A hack to help centre the X11 font in the space of the laser
X	 *  printer font so it looks much nicer. Taken from David
X	 *  Blythe's xproof previewer for X10, at the University of
X	 *  Toronto. It might work in Suntools as well - I haven't
X	 *  tried. - moraes
X	 */
X	cwidth = UserTypesetter->WidthTable[font]
X		[UserTypesetter->AsciiTable[font][c]&0xff]&0xff;
X	cwidth = (cwidth * UserTypesetter->PointSizeTable[size - 1]
X	 + UserTypesetter->Device.unitwidth/2)
X	 / UserTypesetter->Device.unitwidth;
X#else
X	cwidth = 0;
X#endif
X	
X	DrawCharacter(HorizontalPosition,VerticalPosition,
X		      CodeTable[font][AsciiTable[font][c]&0xff], cwidth);
X	SetFont(OldFont);
X}
X
XPutSpecialCharacter(CharacterName)
Xchar	*CharacterName;
X{
X	int 	i, c;
X	struct dev *Device;
X	short	*SpecialCharacterNumber;
X	char	*SpecialCharacterName;
X
X	Device = &OutputTypesetter->Device;
X	SpecialCharacterNumber = OutputTypesetter->SpecialCharacterNumber;
X	SpecialCharacterName = OutputTypesetter->SpecialCharacterName;
X
X	if (!DisplayOutput){
X		return;
X	}
X
X#ifndef SUNTOOLS
X	/* Draw Troff special graphics (non-character) */
X
X	c = PACK_TWO_CHARS(CharacterName[0], CharacterName[1]);
X
X	switch (c) {
X/*
X * /bv{0 800 moveto 0 -1000 rls}def
X */
X	case PACK_TWO_CHARS('b', 'v'):
X		line(.25, -.8, .25, .2);
X		return;
X/*
X * /br{0 750 moveto 0 -1000 rls}def
X */
X	case PACK_TWO_CHARS('b', 'r'):
X		line(0., -.75, 0., .25);
X		return;
X/*
X * /ru{500 0 rls}def
X */
X	case PACK_TWO_CHARS('r', 'u'):
X		line(0., 0., .5, 0.);
X		return;
X/*
X * /lf{0 800 moveto 0 -1000 rlineto s4 0 rls}def
X */
X	case PACK_TWO_CHARS('l', 'f'):
X		line(.25, -.8, .25, .2);
X		line(.25, .2, .5, .2);
X		return;
X/*
X * /rf{0 800 moveto 0 -1000 rlineto s4 neg 0 rls}def
X */
X	case PACK_TWO_CHARS('r', 'f'):
X		line(.25, -.8, .25, .2);
X		line(.25, .2, 0., .2);
X		return;
X/*
X * /lc{0 -200 moveto 0 1000 rlineto s4 0 rls}def
X */
X	case PACK_TWO_CHARS('l', 'c'):
X		line(.25, .2, .25, -.8);
X		line(.25, -.8, .5, -.8);
X		return;
X/*
X * /rc{0 -200 moveto 0 1000 rlineto s4 neg 0 rls}def
X */
X	case PACK_TWO_CHARS('r', 'c'):
X		line(.25, .2, .25, -.8);
X		line(.25, -.8, 0., -.8);
X		return;
X/*
X * /sq{80 0 rmoveto currentpoint dround newpath moveto
X *     640 0 rlineto 0 640 rlineto -640 0 rlineto closepath stroke}def
X */
X	case PACK_TWO_CHARS('s', 'q'):
X		line(.08, 0., .72, 0.);
X		line(.72, 0., .72, -.64);
X		line(.72, -.64, .08, -.64);
X		line(.08, -.64, .08, 0.);
X		return;
X/*
X * /bx{80 0 rmoveto currentpoint dround newpath moveto
X *     640 0 rlineto 0 640 rlineto -640 0 rlineto closepath fill}def
X */
X	case PACK_TWO_CHARS('b', 'x'):
X		box(.08, -.64, .72, 0.);
X		return;
X/*
X * /ci{500 360 rmoveto currentpoint newpath 333 0 360 arc
X *     50 setlinewidth stroke}def
X */
X	case PACK_TWO_CHARS('c', 'i'):
X		circle(.5, -.36, .25, 0);
X		return;
X/*
X * /lt{0 -200 moveto 0 550 rlineto currx 800 2cx s4 add exch s4 a4p stroke}def
X */
X	case PACK_TWO_CHARS('l', 't'):
X		line(.25, .2, .25, -.55);
X		arc(.5, -.55, .25, 180, -90, 0);
X		return;
X/*
X * /rt{0 -200 moveto 0 550 rlineto currx 800 2cx s4 sub exch s4 a4p stroke}def
X */
X	case PACK_TWO_CHARS('r', 't'):
X		line(.25, .2, .25, -.55);
X		arc(0., -.55, .25, 0, 90, 0);
X		return;
X/*
X * /lb{0 800 moveto 0 -550 rlineto currx -200 2cx s4 add exch s4 a4p stroke}def
X */
X	case PACK_TWO_CHARS('l', 'b'):
X		line(.25, -.8, .25, -.05);
X		arc(.5, -.05, .25, 180, 90, 0);
X		return;
X/*
X * /rb{0 800 moveto 0 -500 rlineto currx -200 2cx s4 sub exch s4 a4p stroke}def
X */
X	case PACK_TWO_CHARS('r', 'b'):
X		line(.25, -.8, .25, -.05);
X		arc(0., -.05, .25, 0, -90, 0);
X		return;
X/*
X * /lk{0 800 moveto 0 300 -300 300 s4 arcto pop pop 1000 sub
X *     0 300 4 2 roll s4 a4p 0 -200 lineto stroke}def
X */
X	case PACK_TWO_CHARS('l', 'k'):
X		line(.25, -.8, .25, -.55);
X		arc(0., -.55, .25, 0, -90, 0);
X		arc(0., -.05, .25, 90, -90, 0);
X		line(.25, -.05, .25, .2);
X		return;
X/*
X * /rk{0 800 moveto 0 300 s2 300 s4 arcto pop pop 1000 sub
X *     0 300 4 2 roll s4 a4p 0 -200 lineto stroke}def
X */
X	case PACK_TWO_CHARS('r', 'k'):
X		line(.25, -.8, .25, -.55);
X		arc(.5, -.55, .25, 180, 90, 0);
X		arc(.5, -.05, .25, 90, 90, 0);
X		line(.25, -.05, .25, .2);
X		return;
X/*
X * /bu{200 250 rmoveto currentpoint newpath 200 0 360 arc closepath fill}def
X */
X	case PACK_TWO_CHARS('b', 'u'):
X		circle(.25, -.36, .25, 1);
X		return;
X/*
X * /ob{200 250 rmoveto currentpoint newpath 200 0 360 arc closepath stroke}def
X */
X	case PACK_TWO_CHARS('o', 'b'):
X		arc(.25, -.36, .25, 0, 360, 0);
X		return;
X/*
X * /vr{0 800 moveto 0 -770 rls}def
X */
X	case PACK_TWO_CHARS('v', 'r'):
X		line(.25, -.8, .25, -.03);
X		return;
X/*
X * /rn{0 840 moveto 500 0 rls}def
X */
X	case PACK_TWO_CHARS('r', 'n'):
X		line(.25, -.84, .75, -.84);
X		return;
X/*
X * /ul{0 -140 moveto 500 0 rls}def
X */
X	case PACK_TWO_CHARS('u', 'l'):
X		line(.25, .14, .75, .14);
X		return;
X/*
X * /fractm [.65 0 0 .6 0 0] def
X * /fraction
X *  {/fden exch def /fnum exch def gsave /cf currentfont def
X *   cf fractm makefont setfont 0 .3 dm 2 copy neg rmoveto
X *   fnum show rmoveto currentfont cf setfont(\244)show setfont fden show 
X *   grestore ditwid 0 rmoveto} def
X */
X	case PACK_TWO_CHARS('1', '8'):
X		draw_fraction('1', '8', size);
X		return;
X	case PACK_TWO_CHARS('3', '8'):
X		draw_fraction('3', '8', size);
X		return;
X	case PACK_TWO_CHARS('5', '8'):
X		draw_fraction('5', '8', size);
X		return;
X	case PACK_TWO_CHARS('7', '8'):
X		draw_fraction('7', '8', size);
X		return;
X	case PACK_TWO_CHARS('1', '3'):
X		draw_fraction('1', '3', size);
X		return;
X	case PACK_TWO_CHARS('2', '3'):
X		draw_fraction('2', '3', size);
X		return;
X/*
X *  space codes
X */
X	case PACK_TWO_CHARS('\\', '^'):
X		return;
X	case PACK_TWO_CHARS('\\', '|'):
X		return;
X	}
X#endif /* SUNTOOLS */
X	
X
X	for (i=0;i<Device->nchtab;i++){
X		if (STREQ(&SpecialCharacterName[SpecialCharacterNumber[i]],
X			   CharacterName))
X			break;
X	}
X	if (i < Device->nchtab){
X		PutCharacter(i+128);
X		return;
X	} else {
X		switch(c) {
X
X		case PACK_TWO_CHARS('F', 'i'):
X			PutString(HorizontalPosition, "ffi");
X			return;
X
X		case PACK_TWO_CHARS('F', 'l'):
X			PutString(HorizontalPosition, "ffl");
X			return;
X
X		case PACK_TWO_CHARS('f', 'i'):
X			PutString(HorizontalPosition, "fi");
X			return;
X
X		case PACK_TWO_CHARS('f', 'f'):
X			PutString(HorizontalPosition, "ff");
X			return;
X
X		case PACK_TWO_CHARS('f', 'l'):
X			PutString(HorizontalPosition, "fl");
X			return;
X
X		default:
X			warning("Couldn't find special character %s in %s character list.\n",
X		  	    CharacterName, OutputTypesetter->Name);
X
X
X		}
X	}
X}
X
X	
XPrintDocument(ActualFileName,Printer)
Xchar	*ActualFileName, *Printer;
X{
X	char	Command[BUFSIZ];	
X	int	i, SavedPageNumber;
X
X	SavedPageNumber = CurrentPage;		/* Save this, just in case */
X	SaveTitleBar();
X	if (!LastPage && RealBufferPointer != RealFilePointer){
X		for (i=1; i < MAXPAGES; i++){
X			if (PagePlace[i])
X				CurrentPage = i;
X		}
X		FileSeek(PagePlace[CurrentPage]);
X		DisplayOutput = 0;		/* Now flush the rest of input
X						   */
X		while (!LastPage || !feof(RealFilePointer)){
X			SetTitleBar("Flushing", CurrentPage);
X			CurrentPage = ParseInput();
X		}
X	}
X	
X	SetTitleBar("Printing Document", -1);
X	fflush(RealBufferPointer);
X
X	sprintf(Command,"%s%s %s",LPRCOMMAND,Printer,
X		ActualFileName);
X	system(Command);
X	RestoreTitleBar();
X	CurrentPage = SavedPageNumber;
X}
X
X
XPrintPage(PageNumber,Printer)
Xint	PageNumber;
Xchar	*Printer;
X{
X	char	FileName[BUFSIZ], Command[BUFSIZ];
X	FILE	*fp;
X	extern char *mktemp();
X
X	(void) strcpy(FileName,"/tmp/suntroff.XXXXXX");
X	(void) mktemp(FileName);
X	
X	fp = fopen(FileName,"w");
X	if (!fp){
X		warning("Can't open %s for writing page image.\n",
X		      FileName);
X		return;
X	}
X
X	SaveTitleBar();
X	SetTitleBar("Printing Page", PageNumber);
X	OutputPage(0L, PagePlace[1], CurrentFilePointer, fp);
X	OutputPage(PagePlace[PageNumber], PagePlace[PageNumber+1],
X		   CurrentFilePointer,fp);
X	fprintf(fp, "\n");
X	fprintf(fp, "x trailer\n");
X	fprintf(fp, "x stop\n");
X	fclose(fp);
X	
X	(void) sprintf(Command,"%s%s -n %s", LPRCOMMAND, Printer, FileName);
X	(void) system(Command);
X        unlink(FileName);
X	RestoreTitleBar();
X}
X
X/*ARGSUSED*/
XOutputPage(Start,End,Input,Output)
Xlong	Start, End;
XFILE	*Input, *Output;
X{
X	int	c;
X
X	if (End != 0 && Start > End){
X		fatal("PrintPage: starting offset (%d) is less than\nending offset (%d)\n",Start,End);
X		return;
X	}
X
X	FileSeek(Start);
X
X	do {
X		c = GetChar();
X		if (c != EOF){
X			putc(c, Output);
X		}
X		Start ++;
X	} while (c != EOF && (End == 0 || Start < End));
X	
X}
X	
X
XSearchFile(String,PageNumber,Direction)
Xint	PageNumber, Direction;
Xchar	*String;
X{
X	PageNumber += Direction;		/* Skip Current Page */
X
X	if (PageNumber <= 0 || (LastPage && PageNumber > PageNumber) ||
X	    !String || String[0] == NULL){
X		return(0);
X	}
X
X	if (PagePlace[PageNumber] == 0){
X		warning("Can't find the current page while searching.");
X		return(0);
X	}
X
X	FileSeek(PagePlace[PageNumber]);
X	for (;PageNumber>0 ;PageNumber += Direction){
X		if (LastPage && PageNumber > LastPage){
X			return(0);
X		}
X		if (feof(CurrentFilePointer)){
X			return(0);
X		}
X		if (Direction < 0){
X			FileSeek(PagePlace[PageNumber]);
X		}
X
X		SetTitleBar("Searching",PageNumber);
X		if (SearchPage(String)) {
X			return(PageNumber);
X		}
X	}
X	return(0);
X}
X
XSearchPage(String)
Xchar	*String;
X{
X	char	*StringP = String;
X	int	c;
X
X	while ((c = GetChar()) != EOF){
X		switch(c){
X		case ' ':
X		case 0:
X		case '{':
X		case '}':
X		case '\n':
X			break;
X		case '0': case '1': case '2': case '3': case '4':
X		case '5': case '6': case '7': case '8': case '9':
X			GetChar();
X		case 'c':
X			c = GetChar();
X			if (c == *StringP){
X				StringP++;
X				if (*StringP == 0){
X					return(1);
X				}
X			} else {
X				StringP = String;
X			}
X			break;
X		case 'C':
X			GetChar();
X			GetChar();
X			StringP = String;
X			break;
X		case 'D':
X		case 'x':
X		case '#':
X			do {
X				c = GetChar();
X			} while (c != '\n' && c != EOF);
X			StringP = String;
X			break;
X		case 'w':
X			if (*StringP == ' '){
X				*StringP++;
X				if (*StringP == 0){
X					return(1);
X				}
X			} else {
X				StringP = String;
X			}
X			break;
X		case 'n':
X			if (*StringP == ' '){
X				*StringP++;
X				if (*StringP == 0){
X					return(1);
X				} 
X			} else {
X				StringP = String;
X			}
X			GetNumber();
X			GetNumber();
X			break;
X		case 's':
X		case 'f':
X		case 'H':
X		case 'V':
X		case 'h':
X		case 'v':
X			GetNumber();
X			break;
X		case 'p':
X			(void) GetNumber();
X			(void) RememberPagePosition();
X			return(0);
X		default:
X			warning("Unknown input character %c(%d)\n",
X			      c,c);
X			break;
X		}
X	}
X	return(0);
X}
X
Xstatic	UnreadCharacter = 0;
X
X/*
X * Pages are ordered by physical position in the file, because of the weird
X * numbers possible with troff pages
X */
XRememberPagePosition()
X{
X	extern long ftell();
X	int pageplace = ftell(RealBufferPointer);
X	int mid;
X#ifdef SEEK
X	char *unread = "";
X#endif
X
X	if (UnreadCharacter) {
X		pageplace--;
X		UnreadCharacter = 0;
X#ifdef SEEK
X		unread = " with unread character";
X#endif /* SEEK */
X	}
X
X	if (pageplace > PagePlace[MaxPage]) { /* Usual case */
X		PagePlace[++MaxPage] = pageplace;
X		mid = MaxPage;
X	} else {
X		/* Binary search for the page - it must be in the table */
X		int hi = MaxPage;
X		int lo = 0;
X		while (hi >= lo) {
X			mid = lo + (hi - lo) / 2;
X			if (PagePlace[mid] == pageplace)
X				break;
X			if (pageplace < PagePlace[mid])
X				hi = mid - 1;
X			else
X				lo = mid + 1;
X		}
X		if (PagePlace[mid] != pageplace) 
X			fatal("pageplace 0x%x wasn't in table\n");
X	}
X#ifdef	SEEK					
X	printf("Remembering page %d at 0x%x%s.\n", mid, PagePlace[mid], 
X	 unread);
X#endif	/* SEEK	*/
X	return(mid);
X}
X
XFileSeek(Position)
Xlong	Position;
X{
X	UnreadCharacter = 0;
X	CurrentFilePointer = RealBufferPointer;
X	fseek(CurrentFilePointer,Position,0);
X#ifdef	SEEK		
X	printf("Seeking to %x of real buffer.\n", Position);
X#endif	SEEK
X}
X
XGetChar(){
X	int	i;
X	
X	if (UnreadCharacter){
X		i = UnreadCharacter;
X		UnreadCharacter = 0;
X		return(i);
X	}
X
X	i = getc(CurrentFilePointer);
X	if (CurrentFilePointer != RealBufferPointer){
X		putc(i, RealBufferPointer);
X	}			
X	
X	if (i == EOF){
X		if (RealFilePointer != RealBufferPointer){
X			if (CurrentFilePointer == RealBufferPointer){
X				CurrentFilePointer = RealFilePointer;
X				i = GetChar();
X			}
X		}
X	}
X	
X	return(i);
X}
X
XUnGetChar(c)
Xint	c;
X{
X	if (UnreadCharacter){
X		fatal("Can't UnGetChar more than one character.\n");
X	}
X
X	UnreadCharacter = c;
X}
X
Xchar *
XGetLine(Buffer, Length)
Xchar	*Buffer;
Xint	Length;
X{
X	int 	i = 0, c;
X	char	*p = Buffer;
X	
X	Length--;			    /* Save room for final NULL */
X	
X	while (i < Length && (c = GetChar()) != EOF && c != '\n'){
X		if (p)
X			*p++ = c;
X	}
X	if (c == '\n' && p){		    /* Retain the newline like fgets */
X		*p++ = c;
X	}
X	if (c == '\n')
X		UnGetChar(c);
X	
X
X	if (p)	
X		*p = NULL;
X	return(Buffer);
X} 
X
Xchar *
XGetWord(Buffer, Length)
Xchar	*Buffer;
Xint	Length;
X{
X	int 	i = 0, c;
X	char	*p = Buffer;
X	
X	Length--;			    /* Save room for final NULL */
X	
X	while ((c = GetChar()) != EOF && isspace(c));
X	if (c != EOF){
X		UnGetChar(c);
X	}
X
X	while (i < Length && (c = GetChar()) != EOF && !isspace(c)){
X		if (p)
X			*p++ = c;
X	}
X	if (c != EOF)
X		UnGetChar(c);
X	
X	if (p)
X		*p = NULL;
X	return(Buffer);
X} 
X
XGetNumber(){
X	int	i = 0,  c;
X
X	while ((c = GetChar()) != EOF && isspace(c));
X
X	if (c != EOF){
X		UnGetChar(c);
X	}
X
X	while ((c = GetChar()) != EOF && isdigit(c)){
X		i = i*10 + c - '0';
X	}
X
X	if (c != EOF)
X		UnGetChar(c);
X	return (i);
X}
X	
X	    
END_OF_FILE
if test 23976 -ne `wc -c <'xtroff/suntroff.c'`; then
    echo shar: \"'xtroff/suntroff.c'\" unpacked with wrong size!
fi
# end of 'xtroff/suntroff.c'
fi
echo shar: End of archive 14 \(of 18\).
cp /dev/null ark14isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 18 archives.
    rm -f ark[1-9]isdone ark[1-9][0-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0



More information about the Comp.sources.x mailing list