home *** CD-ROM | disk | FTP | other *** search
- Path: uunet!island!argv
- From: argv@island.uu.net (Dan Heller)
- Newsgroups: comp.sources.x
- Subject: v04i059: xtroff -- troff previewer for X11, Part14/18
- Message-ID: <894@island.uu.net>
- Date: 19 Jul 89 09:12:40 GMT
- Organization: Island Graphics, Marin County, California
- Lines: 2059
- Approved: island!argv@sun.com
-
- Submitted-by: Mark Moraes <moraes@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@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@decwrl.dec.com
- X * malcolm@ecn.purdue.edu
- X * malcolm@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@decwrl.dec.com
- X * malcolm@ecn.purdue.edu
- X * malcolm@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@cray.com>, portable implementation from Henry Spencer
- X * <henry@utzoo.uucp>, Jeffrey Lee <jonah@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
-