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