home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / x / volume4 / xtroff / part14 < prev    next >
Encoding:
Internet Message Format  |  1989-07-19  |  55.2 KB

  1. Path: uunet!island!argv
  2. From: argv@island.uu.net (Dan Heller)
  3. Newsgroups: comp.sources.x
  4. Subject: v04i059: xtroff -- troff previewer for X11, Part14/18
  5. Message-ID: <894@island.uu.net>
  6. Date: 19 Jul 89 09:12:40 GMT
  7. Organization: Island Graphics, Marin County, California
  8. Lines: 2059
  9. Approved: island!argv@sun.com
  10.  
  11. Submitted-by: Mark Moraes <moraes@ai.toronto.edu>
  12. Posting-number: Volume 4, Issue 59
  13. Archive-name: xtroff/part14
  14.  
  15.  
  16.  
  17. #! /bin/sh
  18. # This is a shell archive.  Remove anything before this line, then unpack
  19. # it by saving it into a file and typing "sh file".  To overwrite existing
  20. # files, type "sh file -c".  You can also feed this as standard input via
  21. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  22. # will see the following message at the end:
  23. #        "End of archive 14 (of 18)."
  24. # Contents:  xtroff/curves.c xtroff/suntroff.c
  25. # Wrapped by moraes@neat.ai on Thu Jul 13 20:55:21 1989
  26. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  27. if test -f 'xtroff/curves.c' -a "${1}" != "-c" ; then 
  28.   echo shar: Will not clobber existing file \"'xtroff/curves.c'\"
  29. else
  30. echo shar: Extracting \"'xtroff/curves.c'\" \(28272 characters\)
  31. sed "s/^X//" >'xtroff/curves.c' <<'END_OF_FILE'
  32. X/*
  33. X *    SunTroff -  A program to display the output of Device Independent
  34. X *        Troff as a window on a Sun Workstation.
  35. X *
  36. X *    Troff_curves.c - Code to draw the fancy curves needed in the
  37. X *        ditroff spec.  Code written at Berkeley and cleaned up
  38. X *        just a bit at SPAR.
  39. X *
  40. X *    Authors - The original version of this program was written by
  41. X *            Richard L. Hyde (Purdue)
  42. X *            David Slattengren (Berkeley)
  43. X *        It was nearly all rewritten, cleaned up and a more elegant
  44. X *        user interface installed by
  45. X *            Malcolm Slaney (Schlumberger Palo Alto Research)
  46. X *
  47. X *    Legalese -  This command was developed as an independent project
  48. X *        to satisfy a need of the author.  This program may contain
  49. X *        bugs and the user is cautioned to independently verify that
  50. X *        the program is suitable for the user's intended purpose.
  51. X *        The program is made available on an ``as is'' basis with
  52. X *        all faults and without any implied or expressed warranties
  53. X *        or support from either the author, Malcolm Slaney, or
  54. X *        Schlumberger Palo Alto Research Laboratory.
  55. X *
  56. X *        I am putting this program in the public domain.  You are
  57. X *        free to use it as you wish.  In return I ask two things.
  58. X *        First, that you do not remove the names of the authors
  59. X *        from this work.  Secondly, if you make changes or
  60. X *        improvements to this program that you pass these back to
  61. X *        the author so that everybody can benefit from the
  62. X *        improvements.
  63. X *
  64. X *                    Malcolm Slaney  (December 1986)
  65. X *                    Schlumberger Palo Alto Research
  66. X *                    3340 Hillview Avenue
  67. X *                    Palo Alto, CA 94304
  68. X *                    (415) 496-4669
  69. X *                    spar!malcolm@decwrl.dec.com
  70. X *                    malcolm@ecn.purdue.edu
  71. X *                    malcolm@spar.slb.com (Someday)
  72. X */
  73. X
  74. X/*
  75. X *
  76. X *    This file contains the functions for producing the graphics
  77. X *   images in the sun driver for ditroff.
  78. X */
  79. X
  80. X
  81. X#include <stdio.h>
  82. X#include <ctype.h>
  83. X#include <math.h>
  84. X#include "fixpoint.h"
  85. X
  86. X
  87. X#define TRUE    1
  88. X#define FALSE    0
  89. X                /* imports from dver.c */
  90. X#define  hmot(n)    HorizontalMove(n)
  91. X#define  vmot(n)    VerticalMove(n)
  92. X#define  vgoto(n)    VerticalGoto(n)
  93. X
  94. Xextern int HorizontalPosition;
  95. Xextern int VerticalPosition;
  96. Xextern int DisplayOutput;
  97. Xextern point();
  98. Xextern int scale();
  99. X
  100. X#define MAXPOINTS 200    /* number of points legal for a curve */
  101. X
  102. X#define SOLID -1    /* line styles:  these are used as bit masks to */
  103. X#define DOTTED 004    /* create the right style lines. */
  104. X#define DASHED 020
  105. X#define DOTDASHED 024
  106. X#define LONGDASHED 074
  107. X                /* constants... */
  108. X#define  pi        3.14159265358979324
  109. X
  110. X
  111. Xint    linethickness = 1;    /* number of pixels wide to make lines */
  112. Xint    linmod = SOLID;        /* type of line (SOLID, DOTTED, DASHED...) */
  113. X
  114. X
  115. Xvoid
  116. Xsetstip(n)
  117. X    int n;
  118. X{
  119. X}
  120. X
  121. X/*----------------------------------------------------------------------------
  122. X * Routine:    drawline (horizontal_motion, vertical_motion)
  123. X *
  124. X * Results:    Draws a line of "linethickness" width and "linmod" style
  125. X *        from current (HorizontalPosition, VerticalPosition) to
  126. X *        (HorizontalPosition + dh, VerticalPosition + dv).
  127. X *
  128. X * Side Efct:    Resulting position is at end of line (HorizontalPosition + dh,
  129. X *                            VerticalPosition + dv)
  130. X *----------------------------------------------------------------------------*/
  131. X
  132. Xdrawline(dh, dv)
  133. Xregister int dh;
  134. Xregister int dv;
  135. X{
  136. X    if (DisplayOutput) {
  137. X        HGtline (HorizontalPosition, VerticalPosition,
  138. X             HorizontalPosition + dh, VerticalPosition + dv);
  139. X    }
  140. X    hmot (dh);                    /* new position is at */
  141. X    vmot (dv);                    /* the end of the line */
  142. X}
  143. X
  144. X
  145. X/*----------------------------------------------------------------------------
  146. X * Routine:    DrawCircle (diameter)
  147. X *
  148. X * Results:    Draws a circle with leftmost point at current
  149. X *        (HorizontalPosition, VerticalPosition)
  150. X *        with the given diameter d.  Does a thick line by calling
  151. X *        RoundEnd many times with varying radii.
  152. X *
  153. X * Side Efct:    Resulting position is at (HorizontalPosition + diameter,
  154. X *                        VerticalPosition)
  155. X *----------------------------------------------------------------------------*/
  156. X
  157. XDrawCircle(d)
  158. Xint d;
  159. X{
  160. X    register int delta_rad;
  161. X    register int limit;
  162. X    register int radius;
  163. X
  164. X
  165. X    if (DisplayOutput) {
  166. X    radius = Scale(d) / 2;
  167. X    delta_rad = radius - linethickness / 2;
  168. X    limit = radius + (linethickness - 1) / 2;
  169. X    while (delta_rad <= limit) {
  170. X        RoundEnd (Scale(HorizontalPosition)+radius,
  171. X              Scale(VerticalPosition), delta_rad, FALSE);
  172. X        delta_rad++;
  173. X    }
  174. X    }
  175. X
  176. X    hmot (d);
  177. X}
  178. X
  179. X
  180. X/*----------------------------------------------------------------------------
  181. X * Routine:    DrawEllipse(horizontal_diameter, vertical_diameter)
  182. X *
  183. X * Results:    Draws regular ellipses given the major "diameters."  It does
  184. X *        so using a modified circle algorithm (see RoundEnd) that
  185. X *        increments x and y proportionally to their axes.
  186. X *
  187. X * Side Efct:    Resulting position is at (HorizontalPosition + hd,
  188. X *                        VerticalPosition).
  189. X *---------------------------------------------------------------------------*/
  190. X
  191. XDrawEllipse(hd, vd)
  192. Xint hd;
  193. Xint vd;
  194. X{
  195. X    fixed xs, ys, xepsilon, yepsilon;
  196. X    int thick;
  197. X    register int basex;
  198. X    register int basey;
  199. X    register int x;
  200. X    register int y;
  201. X
  202. X                        /* bases == coordinates of center */
  203. X    basex = Scale(HorizontalPosition + (hd >> 1));    
  204. X    hmot(hd);                /* horizontal motion */
  205. X                        /*   (HorizontalPosition should */
  206. X                    /*   NOT be used after this) */
  207. X    basey = Scale(VerticalPosition);    
  208. X                    /* hd and vd are radii, not diameters*/
  209. X    if ((hd=Scale(hd >> 1)) < 1) hd++;    /* neither diameter can be zero. */
  210. X    if ((vd=Scale(vd >> 1)) < 1) vd++;    /*   hd changed!! no hmot after this */
  211. X    ys = ffix(vd);            /* start at top of the ellipse */
  212. X    xs = ffix(0);            /*   (y = 1/2 diameter, x = 0) */
  213. X
  214. X    if ((thick = vd) > hd) thick = hd;
  215. X    xepsilon = ffixd((double) thick / (double) (vd * vd));
  216. X    yepsilon = ffixd((double) thick / (double) (hd * hd));
  217. X
  218. X        /* Calculate trajectory of the ellipse for 1/4    */
  219. X        /* the circumference (while ys is non-negative)    */
  220. X        /* and mirror to get the other three quadrants.    */
  221. X
  222. X    thick = linethickness / 2;
  223. X    if (thick) {        /* more than one pixel thick */
  224. X    RoundEnd(basex, fintr(ys) + basey, thick, 0);
  225. X    RoundEnd(basex, basey - fintr(ys), thick, 0);
  226. X    while (ys >= 0) {
  227. X        xs += fmult(xepsilon, ys);    /* generate circumference */
  228. X        ys -= fmult(yepsilon, xs);
  229. X        x = fintr(xs);
  230. X        y = fintr(ys);
  231. X        RoundEnd(x + basex, y + basey, thick, 0);
  232. X        RoundEnd(x + basex, basey - y, thick, 0);
  233. X        RoundEnd(basex - x, y + basey, thick, 0);
  234. X        RoundEnd(basex - x, basey - y, thick, 0);
  235. X    }
  236. X    } else {        /* do the perimeter only (no fill) */
  237. X    point(basex, fintr(ys) + basey);
  238. X    point(basex, basey - fintr(ys));
  239. X    while (ys >= 0) {
  240. X        xs += fmult(xepsilon, ys);    /* generate circumference */
  241. X        ys -= fmult(yepsilon, xs);
  242. X        x = fintr(xs);
  243. X        y = fintr(ys);
  244. X        point(x + basex, y + basey);
  245. X        point(x + basex, basey - y);
  246. X        point(basex - x, y + basey);
  247. X        point(basex - x, basey - y);
  248. X        }
  249. X    }
  250. X}
  251. X
  252. X
  253. X/*----------------------------------------------------------------------------
  254. X * Routine:    DrawArc (xcenter, ycenter, xpoint, ypoint)
  255. X *
  256. X * Results:    Draws an arc starting at current (HorizontalPosition,
  257. X *        VerticalPosition).  Center is at (HorizontalPosition + cdh,
  258. X *        VerticalPosition + cdv) and the terminating point is
  259. X *        at <center> + (pdh, pdv).  The angle between the lines
  260. X *        formed by the starting, ending, and center points is figured
  261. X *        first, then the points and angle are sent to HGArc for the
  262. X *        drawing.
  263. X *
  264. X * Side Efct:    Resulting position is at the last point of the arc.
  265. X *---------------------------------------------------------------------------*/
  266. X
  267. XDrawArc(cdh, cdv, pdh, pdv)
  268. Xregister int cdh;
  269. Xregister int cdv;
  270. Xregister int pdh;
  271. Xregister int pdv;
  272. X{
  273. X    register double angle;
  274. X                /* figure angle from the three points...*/
  275. X                /* and convert (and round) to degrees */
  276. X    angle = (atan2((double) pdh, (double) pdv)
  277. X        - atan2 ((double) -cdh, (double) -cdv)) * 180.0 / pi;
  278. X                /* "normalize" and round */
  279. X    angle += (angle < 0.0)  ?  360.5 : 0.5;
  280. X
  281. X    if (DisplayOutput) {
  282. X        HGArc(HorizontalPosition + cdh, VerticalPosition + cdv,
  283. X          HorizontalPosition, VerticalPosition, (int) angle);
  284. X    }
  285. X    hmot(cdh + pdh);
  286. X    vmot(cdv + pdv);
  287. X}
  288. X
  289. X
  290. X/*----------------------------------------------------------------------------
  291. X * Routine:    DrawSpline (character_buffer, type_flag)
  292. X *
  293. X * Results:    Given the starting position, the motion list in buf, and any
  294. X *        extra characters from the file (terminated by a \n), drawwig
  295. X *        sets up a point list to make a spline from.  If "pic" is set
  296. X *        picurve is called to draw the curve in pic style; else it
  297. X *        calls HGCurve for the gremlin-style curve.
  298. X *
  299. X * Side Efct:    Resulting position is reached from adding successive motions
  300. X *        to the current position.
  301. X *---------------------------------------------------------------------------*/
  302. X
  303. XDrawSpline(buf, pic)
  304. Xchar *buf;
  305. Xint pic;
  306. X{
  307. X    register int len = strlen(buf);    /* length of the string in "buf" */
  308. X    register int npts = 1;        /* point list index */
  309. X    register char *ptr = buf;        /* "walking" pointer into buf */
  310. X    int x[MAXPOINTS], y[MAXPOINTS];    /* point list */
  311. X    extern char *GetLine();
  312. X
  313. X    while (*ptr == ' ') ptr++;        /* skip any leading spaces */
  314. X    x[1] = HorizontalPosition;        /* the curve starts at the */
  315. X    y[1] = VerticalPosition;        /* current position */
  316. X                    /* curve commands end with a '\n' */
  317. X    while (*ptr != '\n' && *ptr != NULL) {
  318. X    if (npts < (MAXPOINTS - 1))    /* if too many points, forget some */
  319. X        npts++;
  320. X    hmot(atoi(ptr));        /* convert motion to curve points */
  321. X    x[npts] = HorizontalPosition;            /* and remember them */
  322. X    while (isdigit(*++ptr));        /* skip number*/
  323. X    while (*++ptr == ' ');        /* skip spaces 'tween numbers */
  324. X    vmot(atoi(ptr));
  325. X    y[npts] = VerticalPosition;
  326. X    while (isdigit(*++ptr));
  327. X    while (*ptr == ' ') ptr++;
  328. X                /* if the amount we read wasn't the */
  329. X                 /*    whole thing, read some more in */
  330. X    if (len - (ptr - buf) < 15 && *(buf + len - 1) != '\n') {
  331. X        char *cop = buf;
  332. X
  333. X        while (*cop++ = *ptr++);    /* copy what's left to the beginning */
  334. X        (void) GetLine(cop-1, len-(cop-buf));
  335. X        printf("The rest of the line is :\n***%s***\n", cop-1);
  336. X        ptr = buf;
  337. X    }
  338. X    }
  339. X                /* now, actually DO the curve */
  340. X    if (DisplayOutput) {
  341. X    if (pic > 0)
  342. X        picurve(x, y, npts);
  343. X    else if (!pic)
  344. X        HGCurve(x, y, npts);
  345. X    else
  346. X        polygon(x, y, npts);
  347. X    }
  348. X}
  349. X
  350. X/*ARGSUSED*/
  351. Xpolygon(x,y,npts)
  352. Xint *x;
  353. Xint *y;
  354. Xint npts;
  355. X{
  356. X}
  357. X
  358. X
  359. X/*----------------------------------------------------------------------------*
  360. X | Routine:    drawthick (thickness)
  361. X |
  362. X | Results:    sets the variable "linethickness" to the given size.
  363. X |        NO motion is involved.
  364. X *---------------------------------------------------------------------------*/
  365. X
  366. Xdrawthick(s)
  367. Xint s;
  368. X{
  369. X    if ((linethickness = Scale(s)) < 1) linethickness = 1;
  370. X}
  371. X
  372. X
  373. X/*----------------------------------------------------------------------------*
  374. X | Routine:    drawstyle (style_bit_map)
  375. X |
  376. X | Results:    sets the variable "linmod" to the given bit map.
  377. X |        NO motion is involved.
  378. X *---------------------------------------------------------------------------*/
  379. X
  380. Xdrawstyle(s)
  381. Xint s;
  382. X{
  383. X    linmod = s;
  384. X}
  385. X
  386. X
  387. X/*----------------------------------------------------------------------------
  388. X * Routine:    picurve (xpoints, ypoints, num_of_points)
  389. X *
  390. X * Results:    Draws a curve delimited by (not through) the line segments
  391. X *        traced by (xpoints, ypoints) point list.  This is the "Pic"
  392. X *        style curve.
  393. X *---------------------------------------------------------------------------*/
  394. X
  395. Xpicurve (x, y, npts)
  396. Xint x[MAXPOINTS];
  397. Xint y[MAXPOINTS];
  398. Xint npts;
  399. X{
  400. X    register int i;        /* line segment traverser */
  401. X    register fixed nseg;    /* effective resolution for each curve */
  402. X    register fixed w;        /* position factor */
  403. X    register int xp;        /* current point (and intermediary) */
  404. X    register int yp;
  405. X    int pxp, pyp;        /* previous point (to make lines from) */
  406. X    fixed t1, t2, t3;        /* calculation temps */
  407. X    fixed j;            /* inner curve segment traverser */
  408. X
  409. X
  410. X    if (x[1] == x[npts] && y[1] == y[npts]) {
  411. X    x[0] = x[npts - 1];        /* if the lines' ends meet, make */
  412. X    y[0] = y[npts - 1];        /* sure the curve meets */
  413. X    x[npts + 1] = x[2];
  414. X    y[npts + 1] = y[2];
  415. X    } else {                /* otherwise, make the ends of the */
  416. X    x[0] = x[1];            /* curve touch the ending points of */
  417. X    y[0] = y[1];            /* the line segments */
  418. X    x[npts + 1] = x[npts];
  419. X    y[npts + 1] = y[npts];
  420. X    }
  421. X
  422. X    pxp = (x[0] + x[1]) / 2;        /* make the last point pointers */
  423. X    pyp = (y[0] + y[1]) / 2;        /* point to the start of the 1st line*/
  424. X
  425. X    for (i = 0; i < npts; i++) {    /* traverse the line segments */
  426. X    xp = x[i] - x[i+1];
  427. X    yp = y[i] - y[i+1];
  428. X    nseg = ffixd(sqrt((double)(xp * xp + yp * yp)) / (20.0));
  429. X    xp = x[i+1] - x[i+2];
  430. X    yp = y[i+1] - y[i+2];        /* "nseg" is the number of line */
  431. X                    /* segments that will be drawn for */
  432. X                    /* each curve segment.  The division */
  433. X                    /* is there to get better performace */
  434. X                    /* by sacrificing resolution */
  435. X    nseg += ffixd(sqrt((double)(xp * xp + yp * yp)) / (20.0));
  436. X
  437. X    for (j = ffix(1); j < nseg; j += ffix(1)) {
  438. X        w = fdiv(j, nseg);
  439. X        t1 = fmult(ffixd(0.5), fmult(w, w));
  440. X        w -= ffixd(0.5);
  441. X        t2 = ffixd(0.75) - fmult(w, w);
  442. X        w -= ffixd(0.5);
  443. X        t3 = fmult(ffixd(0.5), fmult(w, w));
  444. X        xp = fintr(fmult(t1, ffix(x[i+2]))
  445. X            + fmult(t2, ffix(x[i+1])) + fmult(t3, ffix(x[i])));
  446. X        yp = fintr(fmult(t1, ffix(y[i+2]))
  447. X            + fmult(t2, ffix(y[i+1])) + fmult(t3, ffix(y[i])));
  448. X        HGtline(pxp, pyp, xp, yp);
  449. X        pxp = xp;
  450. X        pyp = yp;
  451. X    }
  452. X    }
  453. X}
  454. X
  455. X
  456. X/*----------------------------------------------------------------------------
  457. X * Routine:    HGtline(xstart, ystart, xend, yend)
  458. X *
  459. X * Results:    Draws a line of proper thickness (specified in linethickness).
  460. X *        Scales its points before doing the line - NO scaling should
  461. X *        be done before calling this routine.
  462. X *---------------------------------------------------------------------------*/
  463. X
  464. X
  465. XHGtline(xs, ys, xe, ye)
  466. X{
  467. X    register int x0;    /* starting point and line-walking registers */
  468. X    register int y0;
  469. X    int dx;        /* parameters in the line calculations */
  470. X    int dy;
  471. X    register int res;
  472. X    int xinc;
  473. X    int yinc;
  474. X    int x1;        /* end-point of the line */
  475. X    int y1;
  476. X    int radius;
  477. X    int top;        /* how much to bleed line in "up" (left) direction */
  478. X    int bottom;        /* how much to bleed line in "down" (right) direction */
  479. X    int stop1;        /* place to stop making circles at start of line */
  480. X    int stop2;        /* place to start making circles at end of line */
  481. X    int halfstop;    /* distance tween stop1 and stop3 */
  482. X    int stop3;        /* midpoint `tween making circles and lines */
  483. X    register int i;    /* line-bleeding carrier */
  484. X
  485. X
  486. X    x0 = Scale(xs);    /* convert endpoints to SUN coordinates */
  487. X    y0 = Scale(ys);
  488. X    x1 = Scale(xe);
  489. X    y1 = Scale(ye);
  490. X
  491. X    xinc = 1;
  492. X    yinc = 1;
  493. X    if ((dx = x1-x0) < 0) {
  494. X        xinc = -1;
  495. X        dx = -dx;
  496. X    }
  497. X    if ((dy = y1-y0) < 0) {
  498. X        yinc = -1;
  499. X        dy = -dy;
  500. X    }
  501. X
  502. X    radius = (linethickness - 1) / 2;
  503. X    RoundEnd(x0, y0, radius, TRUE);    /* add ends of line */
  504. X    RoundEnd(x1, y1, radius, TRUE);    /* (nice and curvy) */
  505. X
  506. X    top = linethickness;    /* increase line thickness if at an angle */
  507. X    stop1 = halfstop = 0;
  508. X    if ((i = (int) (sqrt ((double) (dx * dx + dy * dy)) + 0.01)) < 2)
  509. X    return;            /* small lines are done with endpoints */
  510. X    if (dx >= dy) {
  511. X    top = (linethickness * i) / dx;
  512. X    stop1 = (linethickness * dy) / (i + 1);
  513. X    halfstop = (radius * dy) / i;
  514. X    } else {
  515. X    top = (linethickness * i) / dy;
  516. X    stop1 = (linethickness * dx) / (i + 1);
  517. X    halfstop = (radius * dx) / i;
  518. X    }
  519. X    bottom = (top - 1) / 2;
  520. X    top = top / 2;
  521. X
  522. X    if (dx >= dy) {
  523. X    res = (dy >> 1) - (dx >> 1);
  524. X    if (linethickness >= i) {
  525. X        stop1 = stop2 = x0;
  526. X        halfstop = i + 1;
  527. X    } else if (xinc == 1) {
  528. X        stop2 = x1 - stop1;
  529. X        stop1 = x0 + stop1;
  530. X        stop3 = x0 + halfstop;
  531. X    } else {
  532. X        stop2 = x1 + stop1;
  533. X        stop1 = x0 - stop1;
  534. X        stop3 = x0 - halfstop;
  535. X    }
  536. X
  537. X    while (x0 != stop1) {
  538. X        RoundEnd(x0, y0, radius, FALSE);
  539. X            if ((x0&linmod) && (xinc == 1 ? x0 > stop3 : x0 < stop3))
  540. X        for (i = y0 - top; i <= y0 + bottom; i++)
  541. X            point(x0, i);
  542. X            if (res >= 0) {
  543. X                res -= dx;
  544. X                y0 += yinc;
  545. X            }
  546. X            res += dy;
  547. X            x0 += xinc;
  548. X    }
  549. X        while (x0 != stop2) {
  550. X            if (x0&linmod)
  551. X        for (i = y0 - top; i <= y0 + bottom; i++)
  552. X            point(x0, i);
  553. X            if (res >= 0) {
  554. X                res -= dx;
  555. X                y0 += yinc;
  556. X            }
  557. X            res += dy;
  558. X            x0 += xinc;
  559. X        } 
  560. X    stop3 = x1 + (xinc == 1 ? -halfstop : halfstop);
  561. X        while (x0 != x1) {
  562. X        RoundEnd(x0, y0, radius, FALSE);
  563. X            if ((x0&linmod) && (xinc == 1 ? x0 < stop3 : x0 > stop3))
  564. X        for (i = y0 - top; i <= y0 + bottom; i++)
  565. X            point(x0, i);
  566. X            if (res >= 0) {
  567. X                res -= dx;
  568. X                y0 += yinc;
  569. X            }
  570. X            res += dy;
  571. X            x0 += xinc;
  572. X        } 
  573. X    } else {
  574. X    res = (dx >> 1) - (dy >> 1);
  575. X    if (linethickness >= i) {
  576. X        stop1 = stop2 = y0;
  577. X        halfstop = i + 1;
  578. X    } else if (yinc == 1) {
  579. X        stop2 = y1 - stop1;
  580. X        stop1 = y0 + stop1;
  581. X        stop3 = y0 + halfstop;
  582. X    } else {
  583. X        stop2 = y1 + stop1;
  584. X        stop1 = y0 - stop1;
  585. X        stop3 = y0 - halfstop;
  586. X    }
  587. X
  588. X        while (y0 != stop1) {
  589. X        RoundEnd(x0, y0, radius, FALSE);
  590. X            if ((y0&linmod) && (yinc == 1 ? y0 > stop3 : y0 < stop3))
  591. X        for (i = x0 - top; i <= x0 + bottom; i++)
  592. X            point(i, y0);
  593. X            if (res >= 0) {
  594. X                res -= dy;
  595. X                x0 += xinc;
  596. X            }
  597. X        res += dx;
  598. X            y0 += yinc;
  599. X        }
  600. X        while (y0 != stop2) {
  601. X            if (y0&linmod)
  602. X        for (i = x0 - top; i <= x0 + bottom; i++)
  603. X            point(i, y0);
  604. X            if (res >= 0) {
  605. X                res -= dy;
  606. X                x0 += xinc;
  607. X            }
  608. X        res += dx;
  609. X            y0 += yinc;
  610. X        }
  611. X    stop3 = y1 + (yinc == 1 ? -halfstop : halfstop);
  612. X        while (y0 != y1) {
  613. X        RoundEnd(x0, y0, radius, FALSE);
  614. X            if ((y0&linmod) && (yinc == 1 ? y0 < stop3 : y0 > stop3))
  615. X        for (i = x0 - top; i <= x0 + bottom; i++)
  616. X            point(i, y0);
  617. X            if (res >= 0) {
  618. X                res -= dy;
  619. X                x0 += xinc;
  620. X            }
  621. X        res += dx;
  622. X            y0 += yinc;
  623. X        }
  624. X    }
  625. X}
  626. X
  627. X
  628. X/*----------------------------------------------------------------------------
  629. X * Routine:    HGArc (xcenter, ycenter, xstart, ystart, angle)
  630. X *
  631. X * Results:    This routine plots an arc centered about (cx, cy) counter
  632. X *        clockwise starting from the point (px, py) through 'angle'
  633. X *        degrees.  If angle is 0, a full circle is drawn.
  634. X *        It does so by calling RoundEnd (fat point maker) for points
  635. X *        along the circle with density depending on the circle's size.
  636. X *        The points that define the circle are Scaled before doing
  637. X *        the actual drawing.  No scaling should be done before calling
  638. X *        this routine.
  639. X *---------------------------------------------------------------------------*/
  640. X
  641. XHGArc(cx,cy,px,py,angle)
  642. Xregister int cx;
  643. Xregister int cy;
  644. Xint px;
  645. Xint py;
  646. Xint angle;
  647. X{
  648. X    double resolution, fullcircle;
  649. X    int extent;
  650. X    int halfline;
  651. X    fixed epsilon;
  652. X    register fixed xs;
  653. X    register fixed ys;
  654. X
  655. X
  656. X    halfline = linethickness / 2;
  657. X
  658. X    cx = Scale(cx);        /* set points to sun's res. before drawing */
  659. X    cy = Scale(cy);
  660. X    px = Scale(px);
  661. X    py = Scale(py);
  662. X
  663. X    px -= cx;        /* px, py are equal to change in x and y from */
  664. X    py -= cy;        /* center to starting point */
  665. X
  666. X/* calculate drawing parameters */
  667. X
  668. X    resolution = sqrt((double)(px * px + py * py));
  669. X    fullcircle = ceil(2.0 * pi * resolution);
  670. X    epsilon = ffixd(1.0 / resolution);
  671. X    xs = ffix(px);
  672. X    ys = ffix(py);
  673. X
  674. X    if (angle == 0)        /* calculate how long to do the arc */
  675. X    extent = (int) fullcircle;
  676. X    else
  677. X    extent = (int) (fullcircle * (double) angle / 360.0);
  678. X    if (extent < 1) extent = 1;
  679. X
  680. X    if (halfline < 1) {
  681. X    do {
  682. X        xs += fmult(epsilon, ys);
  683. X        ys -= fmult(epsilon, xs);
  684. X        point(fintr(xs) + cx, fintr(ys) + cy);
  685. X    } while (--extent);
  686. X    } else {
  687. X    do {
  688. X        xs += fmult(epsilon, ys);
  689. X        ys -= fmult(epsilon, xs);
  690. X        RoundEnd(cx + fintr(xs), cy + fintr(ys), halfline, FALSE);
  691. X    } while (--extent);
  692. X    }
  693. X}  /* end HGArc */
  694. X
  695. X
  696. X/*----------------------------------------------------------------------------
  697. X * Routine:    RoundEnd (x, y, radius, filled_flag)
  698. X *
  699. X * Results:    Plots a filled (if requested) circle of the specified radius
  700. X *        centered about (x, y).
  701. X *---------------------------------------------------------------------------*/
  702. X
  703. XRoundEnd(x, y, radius, filled)
  704. Xregister int x;
  705. Xregister int y;
  706. Xint radius, filled;
  707. X{
  708. X    fixed xs, ys, epsilon;
  709. X    register int j;
  710. X    register int k;
  711. X
  712. X
  713. X    point(x, y + radius);    /* do the starting point of the circle */
  714. X    if (radius < 1) return;    /* if circle is tiny, quit now */
  715. X    point(x, y - radius);
  716. X
  717. X        /* Calculate trajectory of the circle for 1/4    */
  718. X        /* the circumference (while ys is positive) and    */
  719. X        /* mirror to get the other three quadrants.    */
  720. X
  721. X    xs = ffix(0);
  722. X    ys = ffix(radius);
  723. X    epsilon = fdiv(ffix(1), ys);
  724. X
  725. X    while (ys >= 0) {
  726. X    j = fintr(xs);
  727. X    k = fintr(ys);
  728. X        if (filled) {        /* fill from center */
  729. X        do {
  730. X        point(j+x, k+y);
  731. X        point(j+x, y-k);
  732. X        point(x-j, k+y);
  733. X        point(x-j, y-k);
  734. X        } while (--k >= 0);
  735. X        } else {        /* do the perimeter only (no fill) */
  736. X        point(j+x, k+y);
  737. X        point(j+x, y-k);
  738. X        point(x-j, k+y);
  739. X        point(x-j, y-k);
  740. X        }
  741. X        xs += fmult(epsilon, ys);    /* generate circumference */
  742. X        ys -= fmult(epsilon, xs);
  743. X    }
  744. X}  /* end RoundEnd */;
  745. X
  746. X
  747. X/*----------------------------------------------------------------------------
  748. X * Routine:    Paramaterize (xpoints, ypoints, hparams, num_points)
  749. X *
  750. X * Results:    This routine calculates parameteric values for use in
  751. X *        calculating curves.  The parametric values are returned
  752. X *        in the array h.  The values are an approximation of
  753. X *        cumulative arc lengths of the curve (uses cord length).
  754. X *        For additional information, see paper cited below.
  755. X *---------------------------------------------------------------------------*/
  756. X
  757. Xstatic Paramaterize(x, y, h, n)
  758. Xint x[MAXPOINTS];
  759. Xint y[MAXPOINTS];
  760. Xfloat h[MAXPOINTS];
  761. Xint n;
  762. X{
  763. X    register int dx;
  764. X    register int dy;
  765. X    register int i;
  766. X    register int j;
  767. X    float u[MAXPOINTS];
  768. X
  769. X
  770. X    for (i=1; i<=n; ++i) {
  771. X        u[i] = 0;
  772. X        for (j=1; j<i; j++) {
  773. X        dx = x[j+1] - x[j];
  774. X        dy = y[j+1] - y[j];
  775. X        u[i] += sqrt ((double) (dx * dx + dy * dy));
  776. X        }
  777. X    }
  778. X    for (i=1; i<n; ++i)  h[i] = u[i+1] - u[i];
  779. X}  /* end Paramaterize */
  780. X
  781. X
  782. X/*----------------------------------------------------------------------------
  783. X * Routine:    PeriodicSpline (h, z, dz, d2z, d3z, npoints)
  784. X *
  785. X * Results:    This routine solves for the cubic polynomial to fit a
  786. X *        spline curve to the the points  specified by the list
  787. X *        of values.  The Curve generated is periodic.  The algorithms
  788. X *        for this curve are from the "Spline Curve Techniques" paper
  789. X *        cited below.
  790. X *---------------------------------------------------------------------------*/
  791. X
  792. Xstatic PeriodicSpline(h, z, dz, d2z, d3z, npoints)
  793. Xfloat h[MAXPOINTS];        /* paramaterization  */
  794. Xint z[MAXPOINTS];        /* point list */
  795. Xfloat dz[MAXPOINTS];            /* to return the 1st derivative */
  796. Xfloat d2z[MAXPOINTS], d3z[MAXPOINTS];    /* 2nd and 3rd derivatives */
  797. Xint npoints;                /* number of valid points */
  798. X{
  799. X    float d[MAXPOINTS]; 
  800. X    float deltaz[MAXPOINTS], a[MAXPOINTS], b[MAXPOINTS];
  801. X    float c[MAXPOINTS], r[MAXPOINTS], s[MAXPOINTS];
  802. X    int i;
  803. X
  804. X                        /* step 1 */
  805. X    for (i=1; i<npoints; ++i) {
  806. X        deltaz[i] = h[i] ? ((double) (z[i+1] - z[i])) / h[i] : 0;
  807. X    }
  808. X    h[0] = h[npoints-1];
  809. X    deltaz[0] = deltaz[npoints-1];
  810. X
  811. X                        /* step 2 */
  812. X    for (i=1; i<npoints-1; ++i) {
  813. X        d[i] = deltaz[i+1] - deltaz[i];
  814. X    }
  815. X    d[0] = deltaz[1] - deltaz[0];
  816. X
  817. X                        /* step 3a */
  818. X    a[1] = 2 * (h[0] + h[1]);
  819. X    b[1] = d[0];
  820. X    c[1] = h[0];
  821. X    for (i=2; i<npoints-1; ++i) {
  822. X        a[i] = 2*(h[i-1]+h[i]) - pow ((double) h[i-1],(double)2.0) / a[i-1];
  823. X        b[i] = d[i-1] - h[i-1] * b[i-1]/a[i-1];
  824. X        c[i] = -h[i-1] * c[i-1]/a[i-1];
  825. X    }
  826. X
  827. X                        /* step 3b */
  828. X    r[npoints-1] = 1;
  829. X    s[npoints-1] = 0;
  830. X    for (i=npoints-2; i>0; --i) {
  831. X        r[i] = -(h[i] * r[i+1] + c[i])/a[i];
  832. X        s[i] = (6 * b[i] - h[i] * s[i+1])/a[i];
  833. X    }
  834. X
  835. X                        /* step 4 */
  836. X    d2z[npoints-1] = (6 * d[npoints-2] - h[0] * s[1] 
  837. X                       - h[npoints-1] * s[npoints-2]) 
  838. X                     / (h[0] * r[1] + h[npoints-1] * r[npoints-2] 
  839. X                        + 2 * (h[npoints-2] + h[0]));
  840. X    for (i=1; i<npoints-1; ++i) {
  841. X        d2z[i] = r[i] * d2z[npoints-1] + s[i];
  842. X    }
  843. X    d2z[npoints] = d2z[1];
  844. X
  845. X                        /* step 5 */
  846. X    for (i=1; i<npoints; ++i) {
  847. X        dz[i] = deltaz[i] - h[i] * (2 * d2z[i] + d2z[i+1])/6;
  848. X        d3z[i] = h[i] ? (d2z[i+1] - d2z[i])/h[i] : 0;
  849. X    }
  850. X}  /* end PeriodicSpline */
  851. X
  852. X
  853. X/*----------------------------------------------------------------------------
  854. X * Routine:    NaturalEndSpline (h, z, dz, d2z, d3z, npoints)
  855. X *
  856. X * Results:    This routine solves for the cubic polynomial to fit a
  857. X *        spline curve the the points  specified by the list of
  858. X *        values.  The alogrithms for this curve are from the
  859. X *        "Spline Curve Techniques" paper cited below.
  860. X *---------------------------------------------------------------------------*/
  861. X
  862. Xstatic NaturalEndSpline(h, z, dz, d2z, d3z, npoints)
  863. Xfloat h[MAXPOINTS];        /* parameterization */
  864. Xint z[MAXPOINTS];        /* Point list */
  865. Xfloat dz[MAXPOINTS];            /* to return the 1st derivative */
  866. Xfloat d2z[MAXPOINTS], d3z[MAXPOINTS];    /* 2nd and 3rd derivatives */
  867. Xint npoints;                /* number of valid points */
  868. X{
  869. X    float d[MAXPOINTS];
  870. X    float deltaz[MAXPOINTS], a[MAXPOINTS], b[MAXPOINTS];
  871. X    int i;
  872. X
  873. X                        /* step 1 */
  874. X    for (i=1; i<npoints; ++i) {
  875. X        deltaz[i] = h[i] ? ((double) (z[i+1] - z[i])) / h[i] : 0;
  876. X    }
  877. X    deltaz[0] = deltaz[npoints-1];
  878. X
  879. X                        /* step 2 */
  880. X    for (i=1; i<npoints-1; ++i) {
  881. X        d[i] = deltaz[i+1] - deltaz[i];
  882. X    }
  883. X    d[0] = deltaz[1] - deltaz[0];
  884. X
  885. X                        /* step 3 */
  886. X    a[0] = 2 * (h[2] + h[1]);
  887. X    b[0] = d[1];
  888. X    for (i=1; i<npoints-2; ++i) {
  889. X        a[i] = 2*(h[i+1]+h[i+2]) - pow((double) h[i+1],(double) 2.0)/a[i-1];
  890. X        b[i] = d[i+1] - h[i+1] * b[i-1]/a[i-1];
  891. X    }
  892. X
  893. X                        /* step 4 */
  894. X    d2z[npoints] = d2z[1] = 0;
  895. X    for (i=npoints-1; i>1; --i) {
  896. X        d2z[i] = (6 * b[i-2] - h[i] *d2z[i+1])/a[i-2];
  897. X    }
  898. X
  899. X                        /* step 5 */
  900. X    for (i=1; i<npoints; ++i) {
  901. X        dz[i] = deltaz[i] - h[i] * (2 * d2z[i] + d2z[i+1])/6;
  902. X        d3z[i] = h[i] ? (d2z[i+1] - d2z[i])/h[i] : 0;
  903. X    }
  904. X}  /* end NaturalEndSpline */
  905. X
  906. X
  907. X/*----------------------------------------------------------------------------
  908. X * Routine:    HGCurve(xpoints, ypoints, num_points)
  909. X *
  910. X * Results:    This routine generates a smooth curve through a set of points.
  911. X *        The method used is the parametric spline curve on unit knot
  912. X *        mesh described in "Spline Curve Techniques" by Patrick
  913. X *        Baudelaire, Robert Flegal, and Robert Sproull -- Xerox Parc.
  914. X *---------------------------------------------------------------------------*/
  915. X
  916. X#define POINTSPERINTERVAL 16
  917. X
  918. XHGCurve(x, y, numpoints)
  919. Xint x[MAXPOINTS];
  920. Xint y[MAXPOINTS];
  921. Xint numpoints;
  922. X{
  923. X    float h[MAXPOINTS], dx[MAXPOINTS], dy[MAXPOINTS];
  924. X    float d2x[MAXPOINTS], d2y[MAXPOINTS], d3x[MAXPOINTS], d3y[MAXPOINTS];
  925. X    float t, t2, t3;
  926. X    register int j;
  927. X    register int k;
  928. X    register int nx;
  929. X    register int ny;
  930. X    int lx, ly;
  931. X    int PointsPerInterval;
  932. X
  933. X
  934. X    lx = x[1];
  935. X    ly = y[1];
  936. X    PointsPerInterval = POINTSPERINTERVAL / (9999 / Scale(10000) + 1);
  937. X
  938. X         /* Solve for derivatives of the curve at each point 
  939. X              * separately for x and y (parametric).
  940. X          */
  941. X    Paramaterize(x, y, h, numpoints);
  942. X                            /* closed curve */
  943. X    if ((x[1] == x[numpoints]) && (y[1] == y[numpoints])) {
  944. X        PeriodicSpline(h, x, dx, d2x, d3x, numpoints);
  945. X        PeriodicSpline(h, y, dy, d2y, d3y, numpoints);
  946. X    } else {
  947. X        NaturalEndSpline(h, x, dx, d2x, d3x, numpoints);
  948. X        NaturalEndSpline(h, y, dy, d2y, d3y, numpoints);
  949. X    }
  950. X
  951. X          /* generate the curve using the above information and 
  952. X           * PointsPerInterval vectors between each specified knot.
  953. X           */
  954. X
  955. X    for (j=1; j<numpoints; ++j) {
  956. X        if ((x[j] == x[j+1]) && (y[j] == y[j+1])) continue;
  957. X        for (k=0; k<=PointsPerInterval; ++k) {
  958. X        t = (float) k * h[j] / (float) PointsPerInterval;
  959. X        t2 = t * t;
  960. X        t3 = t * t2;
  961. X        nx = x[j] + (int)(t * dx[j] + t2 * d2x[j]/2 + t3 * d3x[j]/6);
  962. X        ny = y[j] + (int)(t * dy[j] + t2 * d2y[j]/2 + t3 * d3y[j]/6);
  963. X        HGtline(lx, ly, nx, ny);
  964. X        lx = nx;
  965. X        ly = ny;
  966. X        }  /* end for k */
  967. X    }  /* end for j */
  968. X}  /* end HGCurve */
  969. END_OF_FILE
  970. if test 28272 -ne `wc -c <'xtroff/curves.c'`; then
  971.     echo shar: \"'xtroff/curves.c'\" unpacked with wrong size!
  972. fi
  973. # end of 'xtroff/curves.c'
  974. fi
  975. if test -f 'xtroff/suntroff.c' -a "${1}" != "-c" ; then 
  976.   echo shar: Will not clobber existing file \"'xtroff/suntroff.c'\"
  977. else
  978. echo shar: Extracting \"'xtroff/suntroff.c'\" \(23976 characters\)
  979. sed "s/^X//" >'xtroff/suntroff.c' <<'END_OF_FILE'
  980. X/*
  981. X *    SunTroff -  A program to display the output of Device Independent
  982. X *        Troff as a window on a Sun Workstation.
  983. X *
  984. X *    Suntroff - Code to interface the rather generic user interface
  985. X *        provided by windows.c and the low level troff parsing 
  986. X *        and drawing routines.
  987. X *
  988. X *    Authors - The original version of this program was written by
  989. X *            Richard L. Hyde (Purdue)
  990. X *            David Slattengren (Berkeley)
  991. X *        It was nearly all rewritten, cleaned up and a more elegant
  992. X *        user interface installed by
  993. X *            Malcolm Slaney (Schlumberger Palo Alto Research)
  994. X *        Write characters as words
  995. X *            David Cahlander (Cray Research, Inc.)
  996. X *
  997. X *    Legalese -  This command was developed as an independent project
  998. X *        to satisfy a need of the author.  This program may contain
  999. X *        bugs and the user is cautioned to independently verify that
  1000. X *        the program is suitable for the user's intended purpose.
  1001. X *        The program is made available on an ``as is'' basis with
  1002. X *        all faults and without any implied or expressed warranties
  1003. X *        or support from either the author, Malcolm Slaney, or
  1004. X *        Schlumberger Palo Alto Research Laboratory.
  1005. X *
  1006. X *        I am putting this program in the public domain.  You are
  1007. X *        free to use it as you wish.  In return I ask two things.
  1008. X *        First, that you do not remove the names of the authors
  1009. X *        from this work.  Secondly, if you make changes or
  1010. X *        improvements to this program that you pass these back to
  1011. X *        the author so that everybody can benefit from the
  1012. X *        improvements.
  1013. X *
  1014. X *                    Malcolm Slaney  (December 1986)
  1015. X *                    Schlumberger Palo Alto Research
  1016. X *                    3340 Hillview Avenue
  1017. X *                    Palo Alto, CA 94304
  1018. X *                    (415) 496-4669
  1019. X *                    spar!malcolm@decwrl.dec.com
  1020. X *                    malcolm@ecn.purdue.edu
  1021. X *                    malcolm@spar.slb.com (Someday)
  1022. X */
  1023. X
  1024. X#include    "suntroff.h"
  1025. X#ifdef SUNTOOLS
  1026. X#include    <suntool/sunview.h>
  1027. X#endif SUNTOOLS
  1028. X#define    MAXPAGES    500                /* Pages to remember */
  1029. X
  1030. Xstatic FILE *CurrentFilePointer;        /* Current input file. */
  1031. Xstatic FILE *RealBufferPointer;                /* Buffer file pointer */
  1032. Xstatic FILE *RealFilePointer;            /* Real File Pointer */
  1033. X
  1034. Xstatic long PagePlace[MAXPAGES];        /* Remembered ftell
  1035. X                           positions */
  1036. Xstatic int MaxPage = 0;            /* Number of remembered positions */
  1037. X
  1038. X
  1039. X                    /* TYPESETTER ENVIRONMENT VARIABLES */
  1040. Xint    size = 1;            /* Current Font Size (internal
  1041. X                       pstable index) */
  1042. Xfloat    ditsiz;                /* Current Font Scale (special troff
  1043. X                       characters) */
  1044. Xint    font = 1;            /* Current Font (internal font
  1045. X                       number */
  1046. Xint    linmod;                /* Line Style....unused. */
  1047. X
  1048. Xint    linethickness;            /* unused */
  1049. X
  1050. Xint    HorizontalPosition;        /* Horizontal Position (Device
  1051. X                       Coordinates) */
  1052. Xint    VerticalPosition;        /* Vertical Position on the page
  1053. X                       (Device Coordinates) */
  1054. X
  1055. Xchar    DeviceName[11];            /* Output produced for this device */
  1056. X
  1057. Xint    DeviceResolution;        /* Output produced at this resolution*/
  1058. X
  1059. Xstruct FontBitStruct *CurrentFont = 0;    /* Pointer to the current font
  1060. X                       information. */
  1061. Xint    DisplayOutput = 1;        /* Don't display output (just parse)
  1062. X                       when this flag is zero. */
  1063. Xint    LineNumber = 0;            /* Input file line number */
  1064. X
  1065. Xextern    int SUNRES;            /* Resolution of display */
  1066. X
  1067. X#ifdef SUNTOOLS
  1068. Xchar    *DefaultTitle = "SUNTROFF (3.0) ";
  1069. X#else
  1070. Xchar    *DefaultTitle = "XTROFF (4.0) ";
  1071. X/*
  1072. X * We use this macro to pack two characters into an int, so we can test for
  1073. X * troff special characters efficiently. As long as we use PACK_TWO_CHARS for
  1074. X * both constants that we want to compare against, eg. PACK_TWO_CHARS('c',
  1075. X * 'i') for 'ci', as well as for variables, it should be portable. Idea from
  1076. X * Dave Cahlander <dac@cray.com>, portable implementation from Henry Spencer
  1077. X * <henry@utzoo.uucp>, Jeffrey Lee <jonah@db.toronto.edu>
  1078. X */
  1079. X#define    PACK_TWO_CHARS(c1, c2)    (((c1)<<8)|(c2))
  1080. X#endif
  1081. X
  1082. Xint    CurrentPage = 0;        /* Current Page in Input File */
  1083. X
  1084. Xint    LastPage = 0;            /* Last Page of input file */
  1085. X
  1086. XShowPage(PageNumber){
  1087. X    int    i;
  1088. X
  1089. X    if (!CurrentFilePointer){
  1090. X        warning("No file open for input.");
  1091. X        return(0);
  1092. X    }
  1093. X
  1094. X    if (PageNumber < 1)
  1095. X        PageNumber = 1;
  1096. X
  1097. X    if (LastPage && PageNumber > LastPage){
  1098. X        warning("There are only %d pages in\nthis document.",
  1099. X              LastPage);
  1100. X        return(CurrentPage);
  1101. X    }
  1102. X
  1103. X    if (PageNumber < MAXPAGES){
  1104. X        if (PagePlace[PageNumber]){
  1105. X            FileSeek(PagePlace[PageNumber]);
  1106. X            CurrentPage = PageNumber;
  1107. X        } else {
  1108. X            for (i=PageNumber;i>0 && !PagePlace[i];i--)
  1109. X                ;
  1110. X            FileSeek(PagePlace[i]);
  1111. X            
  1112. X            SetTitleBar("Skipping",i);
  1113. X            DisplayOutput = 0;
  1114. X            while (!feof(CurrentFilePointer) &&
  1115. X                   ((CurrentPage = ParseInput()) != PageNumber))
  1116. X                ;
  1117. X        }
  1118. X        DisplayOutput = 1;
  1119. X        ClearPage();
  1120. X        SetTitleBar("Rasterizing",PageNumber);
  1121. X        CurrentPage = ParseInput();
  1122. X        RefreshPage();
  1123. X    }
  1124. X
  1125. X    if (LastPage && PageNumber > LastPage){
  1126. X        warning("There are only %d pages in\nthis document.",
  1127. X              LastPage);
  1128. X        SetTitleBar("Displaying",CurrentPage);
  1129. X        return(CurrentPage);
  1130. X    }
  1131. X
  1132. X    SetTitleBar("Displaying",PageNumber);
  1133. X    return(PageNumber);
  1134. X}
  1135. X
  1136. X
  1137. XClearPagePositions(){
  1138. X    int    i;
  1139. X
  1140. X    for (i=0;i<MAXPAGES;i++){
  1141. X        PagePlace[i] = 0;
  1142. X    }
  1143. X    MaxPage = 0;
  1144. X}
  1145. X
  1146. X#ifdef SUNTOOLS
  1147. Xstatic short IconImage[] = {
  1148. X#include    "ditroff.icon"
  1149. X}; 
  1150. XDEFINE_ICON_FROM_IMAGE(DitroffIcon,IconImage);
  1151. X
  1152. XInitializeApplication(Frame,Canvas)
  1153. XWindow Frame, Canvas;
  1154. X{
  1155. X    window_set(Frame,
  1156. X           FRAME_ICON,&DitroffIcon,
  1157. X           0);
  1158. X    SetTitleBar("Initializing",0);
  1159. X}
  1160. X#endif SUNTOOLS
  1161. X    
  1162. X
  1163. XInitializeFile(RealFile, TempFile)
  1164. XFILE    *RealFile, *TempFile;
  1165. X{
  1166. X    CurrentFilePointer = RealFilePointer = RealFile;
  1167. X    RealBufferPointer = TempFile;
  1168. X    FileSeek(0L);
  1169. X    ClearPagePositions();
  1170. X    CurrentPage = LastPage = 0;
  1171. X}
  1172. X
  1173. XHorizontalMove(delta)
  1174. Xint    delta;
  1175. X{
  1176. X    HorizontalPosition += delta;
  1177. X}
  1178. X
  1179. XHorizontalGoto(NewPosition)
  1180. Xint    NewPosition;
  1181. X{
  1182. X    HorizontalPosition = NewPosition;
  1183. X}
  1184. X
  1185. XVerticalMove(delta)
  1186. Xint    delta;
  1187. X{
  1188. X    VerticalPosition += delta;
  1189. X}
  1190. X
  1191. XVerticalGoto(NewPosition)
  1192. Xint    NewPosition;
  1193. X{
  1194. X    VerticalPosition = NewPosition;
  1195. X}
  1196. X
  1197. X/*
  1198. X *  An attempt is made to gather characters up into words.  This
  1199. X *  produces a much better display since the individual characters
  1200. X *  in a word are separated by the space allocated for the character
  1201. X *  at this font size.  On the average, the position desired and
  1202. X *  the actual screen position will match, since the screen characters
  1203. X *  have the spacing described by the troff description file DESC.out.
  1204. X *  However, if the font has incorrect space or an incorrect discription
  1205. X *  file is used, this scheme will not work.  An error term is calculated
  1206. X *  that indicates the difference between where the character actually
  1207. X *  will be placed and the position required by cononical troff position
  1208. X *  file.  When this difference exceeds 3 pixels (arbitrary) the
  1209. X *  assembled word is terminated and the next character is placed at
  1210. X *  the position designated by troff.
  1211. X *  Note that the troff position can be a fractional pixel while 
  1212. X *  the screen position must always be an integer.
  1213. X */
  1214. XPutCharacterString()
  1215. X{
  1216. X    char    string[100];
  1217. X    char    strch[100];
  1218. X    char    strpos[100];
  1219. X    int    i, n = 0;
  1220. X    int    c, ch, x, w;
  1221. X    float    xdelta, xerror;
  1222. X    char    **CodeTable, **AsciiTable;
  1223. X    
  1224. X    CodeTable = OutputTypesetter->CodeTable;
  1225. X    AsciiTable = OutputTypesetter->AsciiTable;
  1226. X
  1227. X    ch = GetChar();
  1228. X    if (ch < 32 || ch > 128 ||
  1229. X     (AsciiTable[font] != NULL && AsciiTable[font][ch-32] == 0)) {
  1230. X        PutCharacter(ch);
  1231. X        return;
  1232. X    }
  1233. X    x = HorizontalPosition;
  1234. X    xerror = 0;
  1235. X    LoadFontBits();
  1236. X
  1237. X/*  character translation */
  1238. X    
  1239. X    strpos[n] = 0;
  1240. X    strch[n] = ch;
  1241. X    ch = CodeTable[font][AsciiTable[font][ch-32]&0xff];
  1242. X    string[n++] = ch;
  1243. X
  1244. X    while((c = GetChar()) != EOF) {
  1245. X        switch(c) {
  1246. X
  1247. X        case '\n':
  1248. X            LineNumber++;
  1249. X            break;
  1250. X        case '0': case '1': case '2': case '3': case '4':
  1251. X        case '5': case '6': case '7': case '8': case '9':
  1252. X            HorizontalMove(w = (c-'0')*10 + GetChar()-'0');
  1253. X            strpos[n] = w;
  1254. X            xdelta = CurrentFont->Bits->per_char[ch].width -
  1255. X                (w * SUNRES) / (float)UserTypesetter->Device.res;
  1256. X            xerror += xdelta;
  1257. X#ifdef    FONTDEBUG
  1258. X            printf("ch=%c d=%g e=%g\n", ch, xdelta, xerror);
  1259. X#endif    /* FONTDEBUG */
  1260. X            if (xdelta < -5) {
  1261. X                c = 'c';
  1262. X            } else {
  1263. X                ch = GetChar();
  1264. X
  1265. X/*  character translation */
  1266. X
  1267. X                strch[n] = ch;
  1268. X                ch = CodeTable[font][AsciiTable[font][ch-32]&0xff];
  1269. X                string[n++] = ch;
  1270. X                if (ch != 0)
  1271. X                    break;
  1272. X                c = 'w';
  1273. X            }
  1274. X
  1275. X        default:
  1276. X/*
  1277. X * check cumulative error
  1278. X * The error should be less than .5 space on the wide side or
  1279. X * about 5 spaces on the narrow side.  The canned numbers of
  1280. X * 5 pixels and 50 pixels may also be O.K.
  1281. X */
  1282. X            if (xerror > 5 || xerror < -50) {
  1283. X                HorizontalPosition = x;
  1284. X                for (i = 0; i < n; i++) {
  1285. X                    HorizontalPosition += strpos[i];
  1286. X                    PutCharacter(strch[i]&0xff);
  1287. X                }
  1288. X            } else {
  1289. X                string[n] = '\0';
  1290. X                PutString(x, string);
  1291. X            }
  1292. X            UnGetChar(c);
  1293. X            return;
  1294. X        }
  1295. X    }
  1296. X}
  1297. X
  1298. XPutString(x, string)
  1299. Xint    x;
  1300. Xchar    *string;
  1301. X{
  1302. X    if (!DisplayOutput)
  1303. X        return;
  1304. X    DrawString(x, VerticalPosition, string);
  1305. X}
  1306. X
  1307. XPutCharacter(c)
  1308. Xint    c;
  1309. X{
  1310. X    int    OldFont, i, cwidth;
  1311. X    char    **AsciiTable, *SpecialCharacterName, **CodeTable;
  1312. X    short    *SpecialCharacterNumber;
  1313. X    struct Font **FontInformation;
  1314. X    struct dev *Device;
  1315. X
  1316. X    AsciiTable = OutputTypesetter->AsciiTable;
  1317. X    SpecialCharacterNumber = OutputTypesetter->SpecialCharacterNumber;
  1318. X    SpecialCharacterName = OutputTypesetter->SpecialCharacterName;
  1319. X    CodeTable = OutputTypesetter->CodeTable;
  1320. X    FontInformation = OutputTypesetter->FontInformation;
  1321. X    Device = &OutputTypesetter->Device;
  1322. X
  1323. X
  1324. X    if (!DisplayOutput){
  1325. X        return;
  1326. X    }
  1327. X
  1328. X    if (c == ' ')                /* Spaces are easy */
  1329. X        return;
  1330. X      
  1331. X    c -= 32;
  1332. X    if (c < 0 || c > 128-32+Device->nchtab){
  1333. X        warning(
  1334. X              "Bad character (%d) passed to PutCharacter at line %d.\n"
  1335. X              ,c+32,LineNumber);
  1336. X    }
  1337. X    
  1338. X    OldFont = font;
  1339. X
  1340. X    if (AsciiTable[font][c] == 0){            /* If its not in the
  1341. X                               table then look for
  1342. X                               it in the other 
  1343. X                               fonts. */
  1344. X        for (i=0;i<=Device->nfonts;i++){
  1345. X            if (!FontInformation)
  1346. X                continue;
  1347. X#ifdef    MAYBENOT            
  1348. X            if (!FontInformation[i]->specfont)
  1349. X                continue;
  1350. X#endif    MAYBENOT            
  1351. X            if (!AsciiTable[i])
  1352. X                continue;
  1353. X            if (AsciiTable[i][c])
  1354. X                break;
  1355. X        }
  1356. X        if (i <= Device->nfonts){
  1357. X            font = i;
  1358. X                VirtualLoadFont(FontInformation[i]->namefont, size);
  1359. X        } else {
  1360. X            char *s = &SpecialCharacterName[SpecialCharacterNumber[c+32-128]];
  1361. X            switch(PACK_TWO_CHARS(s[0], s[1])) {
  1362. X
  1363. X            case PACK_TWO_CHARS('F', 'i'):
  1364. X                PutString(HorizontalPosition, "ffi");
  1365. X                return;
  1366. X
  1367. X            case PACK_TWO_CHARS('F', 'l'):
  1368. X                PutString(HorizontalPosition, "ffl");
  1369. X                return;
  1370. X
  1371. X            case PACK_TWO_CHARS('f', 'i'):
  1372. X                PutString(HorizontalPosition, "fi");
  1373. X                return;
  1374. X
  1375. X            case PACK_TWO_CHARS('f', 'f'):
  1376. X                PutString(HorizontalPosition, "ff");
  1377. X                return;
  1378. X
  1379. X            case PACK_TWO_CHARS('f', 'l'):
  1380. X                PutString(HorizontalPosition, "fl");
  1381. X                return;
  1382. X
  1383. X            default:
  1384. X                warning(
  1385. X                      "Can't find (%s)%d in %s character table.\n",
  1386. X                      &SpecialCharacterName[SpecialCharacterNumber[
  1387. X                                 c+32-128]],
  1388. X                      c+32,
  1389. X                      OutputTypesetter->Name);
  1390. X                return;
  1391. X            }
  1392. X        }
  1393. X    }
  1394. X
  1395. X    LoadFontBits();
  1396. X
  1397. X#ifndef NOADJUST
  1398. X    /*
  1399. X     *  A hack to help centre the X11 font in the space of the laser
  1400. X     *  printer font so it looks much nicer. Taken from David
  1401. X     *  Blythe's xproof previewer for X10, at the University of
  1402. X     *  Toronto. It might work in Suntools as well - I haven't
  1403. X     *  tried. - moraes
  1404. X     */
  1405. X    cwidth = UserTypesetter->WidthTable[font]
  1406. X        [UserTypesetter->AsciiTable[font][c]&0xff]&0xff;
  1407. X    cwidth = (cwidth * UserTypesetter->PointSizeTable[size - 1]
  1408. X     + UserTypesetter->Device.unitwidth/2)
  1409. X     / UserTypesetter->Device.unitwidth;
  1410. X#else
  1411. X    cwidth = 0;
  1412. X#endif
  1413. X    
  1414. X    DrawCharacter(HorizontalPosition,VerticalPosition,
  1415. X              CodeTable[font][AsciiTable[font][c]&0xff], cwidth);
  1416. X    SetFont(OldFont);
  1417. X}
  1418. X
  1419. XPutSpecialCharacter(CharacterName)
  1420. Xchar    *CharacterName;
  1421. X{
  1422. X    int     i, c;
  1423. X    struct dev *Device;
  1424. X    short    *SpecialCharacterNumber;
  1425. X    char    *SpecialCharacterName;
  1426. X
  1427. X    Device = &OutputTypesetter->Device;
  1428. X    SpecialCharacterNumber = OutputTypesetter->SpecialCharacterNumber;
  1429. X    SpecialCharacterName = OutputTypesetter->SpecialCharacterName;
  1430. X
  1431. X    if (!DisplayOutput){
  1432. X        return;
  1433. X    }
  1434. X
  1435. X#ifndef SUNTOOLS
  1436. X    /* Draw Troff special graphics (non-character) */
  1437. X
  1438. X    c = PACK_TWO_CHARS(CharacterName[0], CharacterName[1]);
  1439. X
  1440. X    switch (c) {
  1441. X/*
  1442. X * /bv{0 800 moveto 0 -1000 rls}def
  1443. X */
  1444. X    case PACK_TWO_CHARS('b', 'v'):
  1445. X        line(.25, -.8, .25, .2);
  1446. X        return;
  1447. X/*
  1448. X * /br{0 750 moveto 0 -1000 rls}def
  1449. X */
  1450. X    case PACK_TWO_CHARS('b', 'r'):
  1451. X        line(0., -.75, 0., .25);
  1452. X        return;
  1453. X/*
  1454. X * /ru{500 0 rls}def
  1455. X */
  1456. X    case PACK_TWO_CHARS('r', 'u'):
  1457. X        line(0., 0., .5, 0.);
  1458. X        return;
  1459. X/*
  1460. X * /lf{0 800 moveto 0 -1000 rlineto s4 0 rls}def
  1461. X */
  1462. X    case PACK_TWO_CHARS('l', 'f'):
  1463. X        line(.25, -.8, .25, .2);
  1464. X        line(.25, .2, .5, .2);
  1465. X        return;
  1466. X/*
  1467. X * /rf{0 800 moveto 0 -1000 rlineto s4 neg 0 rls}def
  1468. X */
  1469. X    case PACK_TWO_CHARS('r', 'f'):
  1470. X        line(.25, -.8, .25, .2);
  1471. X        line(.25, .2, 0., .2);
  1472. X        return;
  1473. X/*
  1474. X * /lc{0 -200 moveto 0 1000 rlineto s4 0 rls}def
  1475. X */
  1476. X    case PACK_TWO_CHARS('l', 'c'):
  1477. X        line(.25, .2, .25, -.8);
  1478. X        line(.25, -.8, .5, -.8);
  1479. X        return;
  1480. X/*
  1481. X * /rc{0 -200 moveto 0 1000 rlineto s4 neg 0 rls}def
  1482. X */
  1483. X    case PACK_TWO_CHARS('r', 'c'):
  1484. X        line(.25, .2, .25, -.8);
  1485. X        line(.25, -.8, 0., -.8);
  1486. X        return;
  1487. X/*
  1488. X * /sq{80 0 rmoveto currentpoint dround newpath moveto
  1489. X *     640 0 rlineto 0 640 rlineto -640 0 rlineto closepath stroke}def
  1490. X */
  1491. X    case PACK_TWO_CHARS('s', 'q'):
  1492. X        line(.08, 0., .72, 0.);
  1493. X        line(.72, 0., .72, -.64);
  1494. X        line(.72, -.64, .08, -.64);
  1495. X        line(.08, -.64, .08, 0.);
  1496. X        return;
  1497. X/*
  1498. X * /bx{80 0 rmoveto currentpoint dround newpath moveto
  1499. X *     640 0 rlineto 0 640 rlineto -640 0 rlineto closepath fill}def
  1500. X */
  1501. X    case PACK_TWO_CHARS('b', 'x'):
  1502. X        box(.08, -.64, .72, 0.);
  1503. X        return;
  1504. X/*
  1505. X * /ci{500 360 rmoveto currentpoint newpath 333 0 360 arc
  1506. X *     50 setlinewidth stroke}def
  1507. X */
  1508. X    case PACK_TWO_CHARS('c', 'i'):
  1509. X        circle(.5, -.36, .25, 0);
  1510. X        return;
  1511. X/*
  1512. X * /lt{0 -200 moveto 0 550 rlineto currx 800 2cx s4 add exch s4 a4p stroke}def
  1513. X */
  1514. X    case PACK_TWO_CHARS('l', 't'):
  1515. X        line(.25, .2, .25, -.55);
  1516. X        arc(.5, -.55, .25, 180, -90, 0);
  1517. X        return;
  1518. X/*
  1519. X * /rt{0 -200 moveto 0 550 rlineto currx 800 2cx s4 sub exch s4 a4p stroke}def
  1520. X */
  1521. X    case PACK_TWO_CHARS('r', 't'):
  1522. X        line(.25, .2, .25, -.55);
  1523. X        arc(0., -.55, .25, 0, 90, 0);
  1524. X        return;
  1525. X/*
  1526. X * /lb{0 800 moveto 0 -550 rlineto currx -200 2cx s4 add exch s4 a4p stroke}def
  1527. X */
  1528. X    case PACK_TWO_CHARS('l', 'b'):
  1529. X        line(.25, -.8, .25, -.05);
  1530. X        arc(.5, -.05, .25, 180, 90, 0);
  1531. X        return;
  1532. X/*
  1533. X * /rb{0 800 moveto 0 -500 rlineto currx -200 2cx s4 sub exch s4 a4p stroke}def
  1534. X */
  1535. X    case PACK_TWO_CHARS('r', 'b'):
  1536. X        line(.25, -.8, .25, -.05);
  1537. X        arc(0., -.05, .25, 0, -90, 0);
  1538. X        return;
  1539. X/*
  1540. X * /lk{0 800 moveto 0 300 -300 300 s4 arcto pop pop 1000 sub
  1541. X *     0 300 4 2 roll s4 a4p 0 -200 lineto stroke}def
  1542. X */
  1543. X    case PACK_TWO_CHARS('l', 'k'):
  1544. X        line(.25, -.8, .25, -.55);
  1545. X        arc(0., -.55, .25, 0, -90, 0);
  1546. X        arc(0., -.05, .25, 90, -90, 0);
  1547. X        line(.25, -.05, .25, .2);
  1548. X        return;
  1549. X/*
  1550. X * /rk{0 800 moveto 0 300 s2 300 s4 arcto pop pop 1000 sub
  1551. X *     0 300 4 2 roll s4 a4p 0 -200 lineto stroke}def
  1552. X */
  1553. X    case PACK_TWO_CHARS('r', 'k'):
  1554. X        line(.25, -.8, .25, -.55);
  1555. X        arc(.5, -.55, .25, 180, 90, 0);
  1556. X        arc(.5, -.05, .25, 90, 90, 0);
  1557. X        line(.25, -.05, .25, .2);
  1558. X        return;
  1559. X/*
  1560. X * /bu{200 250 rmoveto currentpoint newpath 200 0 360 arc closepath fill}def
  1561. X */
  1562. X    case PACK_TWO_CHARS('b', 'u'):
  1563. X        circle(.25, -.36, .25, 1);
  1564. X        return;
  1565. X/*
  1566. X * /ob{200 250 rmoveto currentpoint newpath 200 0 360 arc closepath stroke}def
  1567. X */
  1568. X    case PACK_TWO_CHARS('o', 'b'):
  1569. X        arc(.25, -.36, .25, 0, 360, 0);
  1570. X        return;
  1571. X/*
  1572. X * /vr{0 800 moveto 0 -770 rls}def
  1573. X */
  1574. X    case PACK_TWO_CHARS('v', 'r'):
  1575. X        line(.25, -.8, .25, -.03);
  1576. X        return;
  1577. X/*
  1578. X * /rn{0 840 moveto 500 0 rls}def
  1579. X */
  1580. X    case PACK_TWO_CHARS('r', 'n'):
  1581. X        line(.25, -.84, .75, -.84);
  1582. X        return;
  1583. X/*
  1584. X * /ul{0 -140 moveto 500 0 rls}def
  1585. X */
  1586. X    case PACK_TWO_CHARS('u', 'l'):
  1587. X        line(.25, .14, .75, .14);
  1588. X        return;
  1589. X/*
  1590. X * /fractm [.65 0 0 .6 0 0] def
  1591. X * /fraction
  1592. X *  {/fden exch def /fnum exch def gsave /cf currentfont def
  1593. X *   cf fractm makefont setfont 0 .3 dm 2 copy neg rmoveto
  1594. X *   fnum show rmoveto currentfont cf setfont(\244)show setfont fden show 
  1595. X *   grestore ditwid 0 rmoveto} def
  1596. X */
  1597. X    case PACK_TWO_CHARS('1', '8'):
  1598. X        draw_fraction('1', '8', size);
  1599. X        return;
  1600. X    case PACK_TWO_CHARS('3', '8'):
  1601. X        draw_fraction('3', '8', size);
  1602. X        return;
  1603. X    case PACK_TWO_CHARS('5', '8'):
  1604. X        draw_fraction('5', '8', size);
  1605. X        return;
  1606. X    case PACK_TWO_CHARS('7', '8'):
  1607. X        draw_fraction('7', '8', size);
  1608. X        return;
  1609. X    case PACK_TWO_CHARS('1', '3'):
  1610. X        draw_fraction('1', '3', size);
  1611. X        return;
  1612. X    case PACK_TWO_CHARS('2', '3'):
  1613. X        draw_fraction('2', '3', size);
  1614. X        return;
  1615. X/*
  1616. X *  space codes
  1617. X */
  1618. X    case PACK_TWO_CHARS('\\', '^'):
  1619. X        return;
  1620. X    case PACK_TWO_CHARS('\\', '|'):
  1621. X        return;
  1622. X    }
  1623. X#endif /* SUNTOOLS */
  1624. X    
  1625. X
  1626. X    for (i=0;i<Device->nchtab;i++){
  1627. X        if (STREQ(&SpecialCharacterName[SpecialCharacterNumber[i]],
  1628. X               CharacterName))
  1629. X            break;
  1630. X    }
  1631. X    if (i < Device->nchtab){
  1632. X        PutCharacter(i+128);
  1633. X        return;
  1634. X    } else {
  1635. X        switch(c) {
  1636. X
  1637. X        case PACK_TWO_CHARS('F', 'i'):
  1638. X            PutString(HorizontalPosition, "ffi");
  1639. X            return;
  1640. X
  1641. X        case PACK_TWO_CHARS('F', 'l'):
  1642. X            PutString(HorizontalPosition, "ffl");
  1643. X            return;
  1644. X
  1645. X        case PACK_TWO_CHARS('f', 'i'):
  1646. X            PutString(HorizontalPosition, "fi");
  1647. X            return;
  1648. X
  1649. X        case PACK_TWO_CHARS('f', 'f'):
  1650. X            PutString(HorizontalPosition, "ff");
  1651. X            return;
  1652. X
  1653. X        case PACK_TWO_CHARS('f', 'l'):
  1654. X            PutString(HorizontalPosition, "fl");
  1655. X            return;
  1656. X
  1657. X        default:
  1658. X            warning("Couldn't find special character %s in %s character list.\n",
  1659. X                  CharacterName, OutputTypesetter->Name);
  1660. X
  1661. X
  1662. X        }
  1663. X    }
  1664. X}
  1665. X
  1666. X    
  1667. XPrintDocument(ActualFileName,Printer)
  1668. Xchar    *ActualFileName, *Printer;
  1669. X{
  1670. X    char    Command[BUFSIZ];    
  1671. X    int    i, SavedPageNumber;
  1672. X
  1673. X    SavedPageNumber = CurrentPage;        /* Save this, just in case */
  1674. X    SaveTitleBar();
  1675. X    if (!LastPage && RealBufferPointer != RealFilePointer){
  1676. X        for (i=1; i < MAXPAGES; i++){
  1677. X            if (PagePlace[i])
  1678. X                CurrentPage = i;
  1679. X        }
  1680. X        FileSeek(PagePlace[CurrentPage]);
  1681. X        DisplayOutput = 0;        /* Now flush the rest of input
  1682. X                           */
  1683. X        while (!LastPage || !feof(RealFilePointer)){
  1684. X            SetTitleBar("Flushing", CurrentPage);
  1685. X            CurrentPage = ParseInput();
  1686. X        }
  1687. X    }
  1688. X    
  1689. X    SetTitleBar("Printing Document", -1);
  1690. X    fflush(RealBufferPointer);
  1691. X
  1692. X    sprintf(Command,"%s%s %s",LPRCOMMAND,Printer,
  1693. X        ActualFileName);
  1694. X    system(Command);
  1695. X    RestoreTitleBar();
  1696. X    CurrentPage = SavedPageNumber;
  1697. X}
  1698. X
  1699. X
  1700. XPrintPage(PageNumber,Printer)
  1701. Xint    PageNumber;
  1702. Xchar    *Printer;
  1703. X{
  1704. X    char    FileName[BUFSIZ], Command[BUFSIZ];
  1705. X    FILE    *fp;
  1706. X    extern char *mktemp();
  1707. X
  1708. X    (void) strcpy(FileName,"/tmp/suntroff.XXXXXX");
  1709. X    (void) mktemp(FileName);
  1710. X    
  1711. X    fp = fopen(FileName,"w");
  1712. X    if (!fp){
  1713. X        warning("Can't open %s for writing page image.\n",
  1714. X              FileName);
  1715. X        return;
  1716. X    }
  1717. X
  1718. X    SaveTitleBar();
  1719. X    SetTitleBar("Printing Page", PageNumber);
  1720. X    OutputPage(0L, PagePlace[1], CurrentFilePointer, fp);
  1721. X    OutputPage(PagePlace[PageNumber], PagePlace[PageNumber+1],
  1722. X           CurrentFilePointer,fp);
  1723. X    fprintf(fp, "\n");
  1724. X    fprintf(fp, "x trailer\n");
  1725. X    fprintf(fp, "x stop\n");
  1726. X    fclose(fp);
  1727. X    
  1728. X    (void) sprintf(Command,"%s%s -n %s", LPRCOMMAND, Printer, FileName);
  1729. X    (void) system(Command);
  1730. X        unlink(FileName);
  1731. X    RestoreTitleBar();
  1732. X}
  1733. X
  1734. X/*ARGSUSED*/
  1735. XOutputPage(Start,End,Input,Output)
  1736. Xlong    Start, End;
  1737. XFILE    *Input, *Output;
  1738. X{
  1739. X    int    c;
  1740. X
  1741. X    if (End != 0 && Start > End){
  1742. X        fatal("PrintPage: starting offset (%d) is less than\nending offset (%d)\n",Start,End);
  1743. X        return;
  1744. X    }
  1745. X
  1746. X    FileSeek(Start);
  1747. X
  1748. X    do {
  1749. X        c = GetChar();
  1750. X        if (c != EOF){
  1751. X            putc(c, Output);
  1752. X        }
  1753. X        Start ++;
  1754. X    } while (c != EOF && (End == 0 || Start < End));
  1755. X    
  1756. X}
  1757. X    
  1758. X
  1759. XSearchFile(String,PageNumber,Direction)
  1760. Xint    PageNumber, Direction;
  1761. Xchar    *String;
  1762. X{
  1763. X    PageNumber += Direction;        /* Skip Current Page */
  1764. X
  1765. X    if (PageNumber <= 0 || (LastPage && PageNumber > PageNumber) ||
  1766. X        !String || String[0] == NULL){
  1767. X        return(0);
  1768. X    }
  1769. X
  1770. X    if (PagePlace[PageNumber] == 0){
  1771. X        warning("Can't find the current page while searching.");
  1772. X        return(0);
  1773. X    }
  1774. X
  1775. X    FileSeek(PagePlace[PageNumber]);
  1776. X    for (;PageNumber>0 ;PageNumber += Direction){
  1777. X        if (LastPage && PageNumber > LastPage){
  1778. X            return(0);
  1779. X        }
  1780. X        if (feof(CurrentFilePointer)){
  1781. X            return(0);
  1782. X        }
  1783. X        if (Direction < 0){
  1784. X            FileSeek(PagePlace[PageNumber]);
  1785. X        }
  1786. X
  1787. X        SetTitleBar("Searching",PageNumber);
  1788. X        if (SearchPage(String)) {
  1789. X            return(PageNumber);
  1790. X        }
  1791. X    }
  1792. X    return(0);
  1793. X}
  1794. X
  1795. XSearchPage(String)
  1796. Xchar    *String;
  1797. X{
  1798. X    char    *StringP = String;
  1799. X    int    c;
  1800. X
  1801. X    while ((c = GetChar()) != EOF){
  1802. X        switch(c){
  1803. X        case ' ':
  1804. X        case 0:
  1805. X        case '{':
  1806. X        case '}':
  1807. X        case '\n':
  1808. X            break;
  1809. X        case '0': case '1': case '2': case '3': case '4':
  1810. X        case '5': case '6': case '7': case '8': case '9':
  1811. X            GetChar();
  1812. X        case 'c':
  1813. X            c = GetChar();
  1814. X            if (c == *StringP){
  1815. X                StringP++;
  1816. X                if (*StringP == 0){
  1817. X                    return(1);
  1818. X                }
  1819. X            } else {
  1820. X                StringP = String;
  1821. X            }
  1822. X            break;
  1823. X        case 'C':
  1824. X            GetChar();
  1825. X            GetChar();
  1826. X            StringP = String;
  1827. X            break;
  1828. X        case 'D':
  1829. X        case 'x':
  1830. X        case '#':
  1831. X            do {
  1832. X                c = GetChar();
  1833. X            } while (c != '\n' && c != EOF);
  1834. X            StringP = String;
  1835. X            break;
  1836. X        case 'w':
  1837. X            if (*StringP == ' '){
  1838. X                *StringP++;
  1839. X                if (*StringP == 0){
  1840. X                    return(1);
  1841. X                }
  1842. X            } else {
  1843. X                StringP = String;
  1844. X            }
  1845. X            break;
  1846. X        case 'n':
  1847. X            if (*StringP == ' '){
  1848. X                *StringP++;
  1849. X                if (*StringP == 0){
  1850. X                    return(1);
  1851. X                } 
  1852. X            } else {
  1853. X                StringP = String;
  1854. X            }
  1855. X            GetNumber();
  1856. X            GetNumber();
  1857. X            break;
  1858. X        case 's':
  1859. X        case 'f':
  1860. X        case 'H':
  1861. X        case 'V':
  1862. X        case 'h':
  1863. X        case 'v':
  1864. X            GetNumber();
  1865. X            break;
  1866. X        case 'p':
  1867. X            (void) GetNumber();
  1868. X            (void) RememberPagePosition();
  1869. X            return(0);
  1870. X        default:
  1871. X            warning("Unknown input character %c(%d)\n",
  1872. X                  c,c);
  1873. X            break;
  1874. X        }
  1875. X    }
  1876. X    return(0);
  1877. X}
  1878. X
  1879. Xstatic    UnreadCharacter = 0;
  1880. X
  1881. X/*
  1882. X * Pages are ordered by physical position in the file, because of the weird
  1883. X * numbers possible with troff pages
  1884. X */
  1885. XRememberPagePosition()
  1886. X{
  1887. X    extern long ftell();
  1888. X    int pageplace = ftell(RealBufferPointer);
  1889. X    int mid;
  1890. X#ifdef SEEK
  1891. X    char *unread = "";
  1892. X#endif
  1893. X
  1894. X    if (UnreadCharacter) {
  1895. X        pageplace--;
  1896. X        UnreadCharacter = 0;
  1897. X#ifdef SEEK
  1898. X        unread = " with unread character";
  1899. X#endif /* SEEK */
  1900. X    }
  1901. X
  1902. X    if (pageplace > PagePlace[MaxPage]) { /* Usual case */
  1903. X        PagePlace[++MaxPage] = pageplace;
  1904. X        mid = MaxPage;
  1905. X    } else {
  1906. X        /* Binary search for the page - it must be in the table */
  1907. X        int hi = MaxPage;
  1908. X        int lo = 0;
  1909. X        while (hi >= lo) {
  1910. X            mid = lo + (hi - lo) / 2;
  1911. X            if (PagePlace[mid] == pageplace)
  1912. X                break;
  1913. X            if (pageplace < PagePlace[mid])
  1914. X                hi = mid - 1;
  1915. X            else
  1916. X                lo = mid + 1;
  1917. X        }
  1918. X        if (PagePlace[mid] != pageplace) 
  1919. X            fatal("pageplace 0x%x wasn't in table\n");
  1920. X    }
  1921. X#ifdef    SEEK                    
  1922. X    printf("Remembering page %d at 0x%x%s.\n", mid, PagePlace[mid], 
  1923. X     unread);
  1924. X#endif    /* SEEK    */
  1925. X    return(mid);
  1926. X}
  1927. X
  1928. XFileSeek(Position)
  1929. Xlong    Position;
  1930. X{
  1931. X    UnreadCharacter = 0;
  1932. X    CurrentFilePointer = RealBufferPointer;
  1933. X    fseek(CurrentFilePointer,Position,0);
  1934. X#ifdef    SEEK        
  1935. X    printf("Seeking to %x of real buffer.\n", Position);
  1936. X#endif    SEEK
  1937. X}
  1938. X
  1939. XGetChar(){
  1940. X    int    i;
  1941. X    
  1942. X    if (UnreadCharacter){
  1943. X        i = UnreadCharacter;
  1944. X        UnreadCharacter = 0;
  1945. X        return(i);
  1946. X    }
  1947. X
  1948. X    i = getc(CurrentFilePointer);
  1949. X    if (CurrentFilePointer != RealBufferPointer){
  1950. X        putc(i, RealBufferPointer);
  1951. X    }            
  1952. X    
  1953. X    if (i == EOF){
  1954. X        if (RealFilePointer != RealBufferPointer){
  1955. X            if (CurrentFilePointer == RealBufferPointer){
  1956. X                CurrentFilePointer = RealFilePointer;
  1957. X                i = GetChar();
  1958. X            }
  1959. X        }
  1960. X    }
  1961. X    
  1962. X    return(i);
  1963. X}
  1964. X
  1965. XUnGetChar(c)
  1966. Xint    c;
  1967. X{
  1968. X    if (UnreadCharacter){
  1969. X        fatal("Can't UnGetChar more than one character.\n");
  1970. X    }
  1971. X
  1972. X    UnreadCharacter = c;
  1973. X}
  1974. X
  1975. Xchar *
  1976. XGetLine(Buffer, Length)
  1977. Xchar    *Buffer;
  1978. Xint    Length;
  1979. X{
  1980. X    int     i = 0, c;
  1981. X    char    *p = Buffer;
  1982. X    
  1983. X    Length--;                /* Save room for final NULL */
  1984. X    
  1985. X    while (i < Length && (c = GetChar()) != EOF && c != '\n'){
  1986. X        if (p)
  1987. X            *p++ = c;
  1988. X    }
  1989. X    if (c == '\n' && p){            /* Retain the newline like fgets */
  1990. X        *p++ = c;
  1991. X    }
  1992. X    if (c == '\n')
  1993. X        UnGetChar(c);
  1994. X    
  1995. X
  1996. X    if (p)    
  1997. X        *p = NULL;
  1998. X    return(Buffer);
  1999. X} 
  2000. X
  2001. Xchar *
  2002. XGetWord(Buffer, Length)
  2003. Xchar    *Buffer;
  2004. Xint    Length;
  2005. X{
  2006. X    int     i = 0, c;
  2007. X    char    *p = Buffer;
  2008. X    
  2009. X    Length--;                /* Save room for final NULL */
  2010. X    
  2011. X    while ((c = GetChar()) != EOF && isspace(c));
  2012. X    if (c != EOF){
  2013. X        UnGetChar(c);
  2014. X    }
  2015. X
  2016. X    while (i < Length && (c = GetChar()) != EOF && !isspace(c)){
  2017. X        if (p)
  2018. X            *p++ = c;
  2019. X    }
  2020. X    if (c != EOF)
  2021. X        UnGetChar(c);
  2022. X    
  2023. X    if (p)
  2024. X        *p = NULL;
  2025. X    return(Buffer);
  2026. X} 
  2027. X
  2028. XGetNumber(){
  2029. X    int    i = 0,  c;
  2030. X
  2031. X    while ((c = GetChar()) != EOF && isspace(c));
  2032. X
  2033. X    if (c != EOF){
  2034. X        UnGetChar(c);
  2035. X    }
  2036. X
  2037. X    while ((c = GetChar()) != EOF && isdigit(c)){
  2038. X        i = i*10 + c - '0';
  2039. X    }
  2040. X
  2041. X    if (c != EOF)
  2042. X        UnGetChar(c);
  2043. X    return (i);
  2044. X}
  2045. X    
  2046. X        
  2047. END_OF_FILE
  2048. if test 23976 -ne `wc -c <'xtroff/suntroff.c'`; then
  2049.     echo shar: \"'xtroff/suntroff.c'\" unpacked with wrong size!
  2050. fi
  2051. # end of 'xtroff/suntroff.c'
  2052. fi
  2053. echo shar: End of archive 14 \(of 18\).
  2054. cp /dev/null ark14isdone
  2055. MISSING=""
  2056. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 ; do
  2057.     if test ! -f ark${I}isdone ; then
  2058.     MISSING="${MISSING} ${I}"
  2059.     fi
  2060. done
  2061. if test "${MISSING}" = "" ; then
  2062.     echo You have unpacked all 18 archives.
  2063.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  2064. else
  2065.     echo You still need to unpack the following archives:
  2066.     echo "        " ${MISSING}
  2067. fi
  2068. ##  End of shell archive.
  2069. exit 0
  2070.