home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / misc / volume38 / lout / part10 < prev    next >
Encoding:
Text File  |  1993-08-11  |  72.1 KB  |  1,717 lines

  1. Newsgroups: comp.sources.misc
  2. From: jeff@joyce.cs.su.oz.au (Jeff Kingston)
  3. Subject: v38i078:  lout - Lout document formatting system, v2.05, Part10/35
  4. Message-ID: <1993Aug8.180844.11715@sparky.sterling.com>
  5. X-Md4-Signature: c58532976b10e786df458a1bb95bfbe8
  6. Sender: kent@sparky.sterling.com (Kent Landfield)
  7. Organization: Sterling Software
  8. Date: Sun, 8 Aug 1993 18:08:44 GMT
  9. Approved: kent@sparky.sterling.com
  10.  
  11. Submitted-by: jeff@joyce.cs.su.oz.au (Jeff Kingston)
  12. Posting-number: Volume 38, Issue 78
  13. Archive-name: lout/part10
  14. Environment: UNIX
  15. Supersedes: lout: Volume 37, Issue 99-128
  16.  
  17. #! /bin/sh
  18. # This is a shell archive.  Remove anything before this line, then feed it
  19. # into a shell via "sh file" or similar.  To overwrite existing files,
  20. # type "sh file -c".
  21. # Contents:  z04.c z23.c z24.c
  22. # Wrapped by kent@sparky on Sun Aug  8 12:29:24 1993
  23. PATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:/usr/lbin ; export PATH
  24. echo If this archive is complete, you will see the following message:
  25. echo '          "shar: End of archive 10 (of 35)."'
  26. if test -f 'z04.c' -a "${1}" != "-c" ; then 
  27.   echo shar: Will not clobber existing file \"'z04.c'\"
  28. else
  29.   echo shar: Extracting \"'z04.c'\" \(7484 characters\)
  30.   sed "s/^X//" >'z04.c' <<'END_OF_FILE'
  31. X/*@z04.c:Token Service:NewToken(), CopyTokenList()@***************************/
  32. X/*                                                                           */
  33. X/*  LOUT: A HIGH-LEVEL LANGUAGE FOR DOCUMENT FORMATTING (VERSION 2.05)       */
  34. X/*  COPYRIGHT (C) 1993 Jeffrey H. Kingston                                   */
  35. X/*                                                                           */
  36. X/*  Jeffrey H. Kingston (jeff@cs.su.oz.au)                                   */
  37. X/*  Basser Department of Computer Science                                    */
  38. X/*  The University of Sydney 2006                                            */
  39. X/*  AUSTRALIA                                                                */
  40. X/*                                                                           */
  41. X/*  This program is free software; you can redistribute it and/or modify     */
  42. X/*  it under the terms of the GNU General Public License as published by     */
  43. X/*  the Free Software Foundation; either version 1, or (at your option)      */
  44. X/*  any later version.                                                       */
  45. X/*                                                                           */
  46. X/*  This program is distributed in the hope that it will be useful,          */
  47. X/*  but WITHOUT ANY WARRANTY; without even the implied warranty of           */
  48. X/*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            */
  49. X/*  GNU General Public License for more details.                             */
  50. X/*                                                                           */
  51. X/*  You should have received a copy of the GNU General Public License        */
  52. X/*  along with this program; if not, write to the Free Software              */
  53. X/*  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.                */
  54. X/*                                                                           */
  55. X/*  FILE:         z04.c                                                      */
  56. X/*  MODULE:       Token Service                                              */
  57. X/*  EXTERNS:      NewToken(), CopyTokenList(), EchoCatOp(), EchoToken()      */
  58. X/*                                                                           */
  59. X/*****************************************************************************/
  60. X#include "externs"
  61. X
  62. X
  63. X/*****************************************************************************/
  64. X/*                                                                           */
  65. X/*  OBJECT NewToken(xtype, xfpos, xvspace, xhspace, xprec, xactual)          */
  66. X/*                                                                           */
  67. X/*  Returns a new non-WORD token initialised as the parameters indicate.     */
  68. X/*                                                                           */
  69. X/*****************************************************************************/
  70. X
  71. XOBJECT NewToken(xtype, xfpos, xvspace, xhspace, xprec, xactual)
  72. Xunsigned char xtype;  FILE_POS *xfpos;  unsigned char xvspace, xhspace;
  73. Xunsigned char xprec;  OBJECT xactual;
  74. X{ OBJECT res;
  75. X  debug1(DTS, DDD, "NewToken(%s, ...)", Image(xtype));
  76. X  res = New(xtype);  FposCopy(fpos(res), *xfpos);
  77. X  vspace(res) = xvspace;  hspace(res) = xhspace;
  78. X  precedence(res) = xprec;  actual(res) = xactual;
  79. X  debug1(DTS, DDD, "NewToken returning %s", EchoToken(res));
  80. X  return res;
  81. X} /* end NewToken */
  82. X
  83. X
  84. X/*****************************************************************************/
  85. X/*                                                                           */
  86. X/*  OBJECT CopyTokenList(x, pos)                                             */
  87. X/*                                                                           */
  88. X/*  Returns a copy of the list of tokens pointed to by x.                    */
  89. X/*  All file positions in the copy are set to *pos.                          */
  90. X/*                                                                           */
  91. X/*****************************************************************************/
  92. X
  93. XOBJECT CopyTokenList(x, pos)
  94. XOBJECT x;  FILE_POS *pos;
  95. X{ OBJECT y, z, res;
  96. X  res = nil;  y = x;
  97. X  if( x != nil ) do
  98. X  { if( is_word(type(y)) )
  99. X    { z = MakeWord(type(y), string(y), pos);
  100. X      vspace(z) = vspace(y);  hspace(z) = hspace(y);
  101. X    }
  102. X    else z = NewToken(type(y), pos,vspace(y),hspace(y),precedence(y),actual(y));
  103. X    res = Append(res, z, PARENT);
  104. X    y = succ(y, PARENT);
  105. X  } while( y != x );
  106. X  return res;
  107. X} /* end CopyTokenList */
  108. X
  109. X/*@::EchoCatOp(), EchoToken()@************************************************/
  110. X/*                                                                           */
  111. X/*  FULL_CHAR *EchoCatOp(xtype, xmark, xjoin)                                */
  112. X/*                                                                           */
  113. X/*  Return the catenation operator with this type, mark and join.            */
  114. X/*                                                                           */
  115. X/*****************************************************************************/
  116. X
  117. XFULL_CHAR *EchoCatOp(xtype, xmark, xjoin)
  118. Xunsigned xtype;  BOOLEAN xmark, xjoin;
  119. X{ switch( xtype )
  120. X  {
  121. X    case VCAT:    return    (xmark ? xjoin ? KW_VCAT_MJ : KW_VCAT_MN
  122. X                   : xjoin ? KW_VCAT_NJ : KW_VCAT_NN);
  123. X
  124. X    case HCAT:    return    (xmark ? xjoin ? KW_HCAT_MJ : KW_HCAT_MN
  125. X                   : xjoin ? KW_HCAT_NJ : KW_HCAT_NN);
  126. X
  127. X    case ACAT:    return    (xmark ? xjoin ? KW_ACAT_MJ : AsciiToFull("??")
  128. X                   : xjoin ? KW_ACAT_NJ : AsciiToFull("??") );
  129. X
  130. X    default:    Error(INTERN, no_fpos, "EchoCatOp: xtype = %d", xtype);
  131. X        return STR_EMPTY;
  132. X
  133. X  } /* end switch */
  134. X} /* end EchoCatOp */
  135. X
  136. X
  137. X#if DEBUG_ON
  138. X/*****************************************************************************/
  139. X/*                                                                           */
  140. X/*  FULL_CHAR *EchoToken(x)                                                  */
  141. X/*                                                                           */
  142. X/*  Return an image of token x.  Do not worry about preceding space.         */
  143. X/*                                                                           */
  144. X/*****************************************************************************/
  145. X
  146. XFULL_CHAR *EchoToken(x)
  147. XOBJECT x;
  148. X{ switch( type(x) )
  149. X  {
  150. X    case WORD:
  151. X    
  152. X      return string(x);
  153. X      break;
  154. X
  155. X
  156. X    case QWORD:
  157. X    
  158. X      return StringQuotedWord(x);
  159. X      break;
  160. X
  161. X
  162. X    case TSPACE:
  163. X    case TJUXTA:
  164. X    case USE:
  165. X    case GSTUB_EXT:
  166. X    case GSTUB_INT:
  167. X    case GSTUB_NONE:
  168. X    
  169. X      return Image(type(x));
  170. X      break;
  171. X
  172. X
  173. X    case BEGIN:
  174. X    case END:
  175. X    case ENV:
  176. X    case CLOS:
  177. X    case LBR:
  178. X    case RBR:
  179. X    case NULL_CLOS:
  180. X    case CROSS:
  181. X    case ONE_COL:
  182. X    case ONE_ROW:
  183. X    case WIDE:
  184. X    case HIGH:
  185. X    case HSCALE:
  186. X    case VSCALE:
  187. X    case SCALE:
  188. X    case HCONTRACT:
  189. X    case VCONTRACT:
  190. X    case HEXPAND:
  191. X    case VEXPAND:
  192. X    case PADJUST:
  193. X    case HADJUST:
  194. X    case VADJUST:
  195. X    case ROTATE:
  196. X    case CASE:
  197. X    case YIELD:
  198. X    case XCHAR:
  199. X    case FONT:
  200. X    case SPACE:
  201. X    case BREAK:
  202. X    case NEXT:
  203. X    case OPEN:
  204. X    case TAGGED:
  205. X    case INCGRAPHIC:
  206. X    case SINCGRAPHIC:
  207. X    case GRAPHIC:
  208. X    case ACAT:
  209. X    case HCAT:
  210. X    case VCAT:
  211. X    case CLOSURE:
  212. X    case PREPEND:
  213. X    case SYS_PREPEND:
  214. X    case DATABASE:
  215. X    case SYS_DATABASE:
  216. X    
  217. X      return SymName(actual(x));
  218. X      break;
  219. X
  220. X
  221. X    default:
  222. X    
  223. X      Error(INTERN, &fpos(x), "EchoToken: %s", Image(type(x)));
  224. X      return STR_EMPTY;
  225. X      break;
  226. X  }
  227. X} /* end EchoToken */
  228. X#endif
  229. END_OF_FILE
  230.   if test 7484 -ne `wc -c <'z04.c'`; then
  231.     echo shar: \"'z04.c'\" unpacked with wrong size!
  232.   fi
  233.   # end of 'z04.c'
  234. fi
  235. if test -f 'z23.c' -a "${1}" != "-c" ; then 
  236.   echo shar: Will not clobber existing file \"'z23.c'\"
  237. else
  238.   echo shar: Extracting \"'z23.c'\" \(28455 characters\)
  239.   sed "s/^X//" >'z23.c' <<'END_OF_FILE'
  240. X/*@z23.c:Galley Printer:ScaleFactor()@****************************************/
  241. X/*                                                                           */
  242. X/*  LOUT: A HIGH-LEVEL LANGUAGE FOR DOCUMENT FORMATTING (VERSION 2.05)       */
  243. X/*  COPYRIGHT (C) 1993 Jeffrey H. Kingston                                   */
  244. X/*                                                                           */
  245. X/*  Jeffrey H. Kingston (jeff@cs.su.oz.au)                                   */
  246. X/*  Basser Department of Computer Science                                    */
  247. X/*  The University of Sydney 2006                                            */
  248. X/*  AUSTRALIA                                                                */
  249. X/*                                                                           */
  250. X/*  This program is free software; you can redistribute it and/or modify     */
  251. X/*  it under the terms of the GNU General Public License as published by     */
  252. X/*  the Free Software Foundation; either version 1, or (at your option)      */
  253. X/*  any later version.                                                       */
  254. X/*                                                                           */
  255. X/*  This program is distributed in the hope that it will be useful,          */
  256. X/*  but WITHOUT ANY WARRANTY; without even the implied warranty of           */
  257. X/*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            */
  258. X/*  GNU General Public License for more details.                             */
  259. X/*                                                                           */
  260. X/*  You should have received a copy of the GNU General Public License        */
  261. X/*  along with this program; if not, write to the Free Software              */
  262. X/*  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.                */
  263. X/*                                                                           */
  264. X/*  FILE:         z23.c                                                      */
  265. X/*  MODULE:       Galley Printer                                             */
  266. X/*  EXTERNS:      FixAndPrintObject()                                        */
  267. X/*                                                                           */
  268. X/*****************************************************************************/
  269. X#include "externs"
  270. X#define    NO_SUPPRESS    FALSE
  271. X#define    SUPPRESS    TRUE
  272. X#define    ALL_ADJUST    2
  273. X#define    LAST_ADJUST    1
  274. X#define    ALL_ADJUST    2
  275. X
  276. X#define CountChild(y, link, i)                        \
  277. Xfor( y=pred(link, PARENT), i=1; type(y)==LINK;  y = pred(y, PARENT), i++ )
  278. X
  279. X
  280. X/*****************************************************************************/
  281. X/*                                                                           */
  282. X/*  static float ScaleFactor(avail_size, inner_size)                         */
  283. X/*                                                                           */
  284. X/*  Return the scale factor for this scaling, or 0 if impossible.            */
  285. X/*                                                                           */
  286. X/*****************************************************************************/
  287. X
  288. Xstatic float ScaleFactor(avail_size, inner_size)
  289. XLENGTH avail_size, inner_size;
  290. X{ float scale_factor;
  291. X  scale_factor = avail_size <= 0 ? 0 :
  292. X         inner_size <= 0 ? 0 : (float) avail_size / inner_size;
  293. X  return scale_factor;
  294. X}
  295. X
  296. X
  297. X/*@::FindAdjustIncrement()@***************************************************/
  298. X/*                                                                           */
  299. X/*  static LENGTH FindAdjustIncrement(x, frame_size, dim)                    */
  300. X/*                                                                           */
  301. X/*  Find the amount by which to increase the width of the subobjects of      */
  302. X/*  concatenation object x so that it is adjusted to fill size frame_size.   */
  303. X/*                                                                           */
  304. X/*****************************************************************************/
  305. X
  306. Xstatic LENGTH FindAdjustIncrement(x, frame_size, dim)
  307. XOBJECT x;  LENGTH frame_size;  int dim;
  308. X{ OBJECT y, link, prev, g;
  309. X  int adjustable_gaps;
  310. X  LENGTH inc, mk, actual_size;
  311. X
  312. X  debug2(DGP, D, "FindAdjustIncrement(x, %s, %s)",
  313. X    EchoLength(frame_size), dimen(dim));
  314. X  FirstDefinite(x, link, prev);
  315. X  if( link != x )
  316. X  { adjustable_gaps = 0;
  317. X    mk = back(prev, dim);
  318. X    NextDefiniteWithGap(x, link, y, g);
  319. X    while( link != x )
  320. X    { if ( mode(gap(g)) == TAB_MODE || units(gap(g)) == AVAIL_UNIT
  321. X                    || units(gap(g)) == FRAME_UNIT )
  322. X      {    debug0(DGP, D, "FindAdjustIncrement returning 0 (tab gap)");
  323. X    return 0;
  324. X      }
  325. X      mk += ActualGap(fwd(prev, dim), back(y, dim), fwd(y, dim), &gap(g),
  326. X        frame_size, mk);
  327. X      prev = y;
  328. X      adjustable_gaps++;
  329. X      NextDefiniteWithGap(x, link, y, g);
  330. X    }
  331. X    actual_size = mk + fwd(prev, dim);
  332. X    debug2(DGP, DD, "  actual_size = %s, adjustable_gaps = %d",
  333. X    EchoLength(actual_size), adjustable_gaps);
  334. X    inc = adjustable_gaps==0 ? 0 : (frame_size - actual_size) / adjustable_gaps;
  335. X  }
  336. X  else inc = 0;
  337. X  debug1(DGP, D, "FindAdjustIncrement returning %s", EchoLength(inc));
  338. X  return inc;
  339. X} /* end FindAdjustIncrement */
  340. X
  341. X
  342. X/*@::FixAndPrintObject()@*****************************************************/
  343. X/*                                                                           */
  344. X/*  FixAndPrintObject(x, xmk, xb, xf, dim, adjust, suppress, padj, pg,count) */
  345. X/*                                                                           */
  346. X/*  Fix the absolute position of object x in dimension dim, in such a way    */
  347. X/*  that the principal mark of x has coordinate xmk, and x has actual size   */
  348. X/*  (xb, xf), where xb >= back(x, dim) and xf >= fwd(x, dim).                */
  349. X/*                                                                           */
  350. X/*  Actually, in the case where x includes an object lying on a thread       */
  351. X/*  leading outside x, the final size of x may be different.  Because        */
  352. X/*  of this, the procedure sets back(x, dim) and fwd(x, dim) to the actual   */
  353. X/*  size of x upon return.  The caller assumes that x will exactly occupy    */
  354. X/*  this space back(x, dim), fwd(x, dim).                                    */
  355. X/*                                                                           */
  356. X/*  If x does not fill the forward part of the space allocated to it, the    */
  357. X/*  adjust parameter determines what, if anything, to do about this.  The    */
  358. X/*  two possible values of this parameter are:                               */
  359. X/*                                                                           */
  360. X/*    LAST_ADJUST        Adjust x to fill the forward space available to     */
  361. X/*                       it, by adjusting the last component if x is a       */
  362. X/*                       CAT object, or adjusting the child otherwise.       */
  363. X/*                                                                           */
  364. X/*    ALL_ADJUST         Adjust x to fill the forward space available to     */
  365. X/*                       it, by adjusting all the components if x is a       */
  366. X/*                       CAT object, or adjusting the child otherwise.       */
  367. X/*                                                                           */
  368. X/*  The suppress parameter is true if a temporary suppression of adjustment  */
  369. X/*  is in effect (because a neighbouring adjustment has already been done).  */
  370. X/*                                                                           */
  371. X/*  The padj parameter is analogous to the adjust parameter, but it          */
  372. X/*  applies only to & adjustment, not to | or / adjustment.                  */
  373. X/*                                                                           */
  374. X/*  If dim == COL, the coordinate information is merely stored; but if       */
  375. X/*  dim == ROW, it is used to generate PostScript for printing x.            */
  376. X/*                                                                           */
  377. X/*  Parameter pg records the height of the current page.  This is used       */
  378. X/*  to correct for the fact that Lout places its origin is at the top left,  */
  379. X/*  while PostScript places its origin at the bottom left.  This correction  */
  380. X/*  cannot be made by transforming user space.                               */
  381. X/*                                                                           */
  382. X/*  x is child number count of its parent (used by COL_THR and ROW_THR only) */
  383. X/*                                                                           */
  384. X/*****************************************************************************/
  385. X
  386. XFixAndPrintObject(x, xmk, xb, xf, dim, adjust, suppress, padj, pg, count)
  387. XOBJECT x;  LENGTH xmk, xb, xf; int dim, adjust;  BOOLEAN suppress;
  388. Xint padj;  LENGTH pg;  int count;
  389. X{ OBJECT y, link, prev, g, uplink, z;
  390. X  LENGTH mk, frame_size, back_edge, yb, yf, inc;
  391. X  int i; float scale_factor;
  392. X  debug8(DGP, D, "[ FixAndPrintObject(%s, %s, %s,%s, %s, %s, %s, %s, pg ), x =",
  393. X    Image(type(x)), EchoLength(xmk), EchoLength(xb), EchoLength(xf), dimen(dim),
  394. X    (adjust == LAST_ADJUST ? "last_adjust" : "all_adjust"),
  395. X    (suppress == SUPPRESS ? "suppress" : "no_suppress"),
  396. X    (padj   == LAST_ADJUST ? "last_adjust" : "all_adjust"));
  397. X  ifdebug(DGP, DD, DebugObject(x));
  398. X
  399. X  switch( type(x) )
  400. X  {
  401. X
  402. X    case CLOSURE:
  403. X    case NULL_CLOS:
  404. X    case CROSS:
  405. X    
  406. X      back(x, dim) = xb;  fwd(x, dim) = xf;
  407. X      break;
  408. X
  409. X
  410. X    case WORD:
  411. X    case QWORD:
  412. X    
  413. X      if( dim == COL )  word_save_mark(x) = xmk;
  414. X      else if( string(x)[0] != '\0' )  PrintWord(x, word_save_mark(x), pg-xmk);
  415. X      back(x, dim) = xb;  fwd(x, dim) = xf;
  416. X      break;
  417. X
  418. X
  419. X    case WIDE:
  420. X    case HIGH:
  421. X    
  422. X      CountChild(y, Down(x), count);
  423. X      if( (dim == COL) == (type(x) == WIDE) )
  424. X      { yf = bfc(constraint(x)) - back(y, dim);
  425. X        FixAndPrintObject(y, xmk, back(y,dim), yf, dim, LAST_ADJUST,
  426. X        NO_SUPPRESS, padj, pg, count);
  427. X        back(x, dim) = xb;  fwd(x, dim) = xf;
  428. X      }
  429. X      else
  430. X      {    FixAndPrintObject(y, xmk, xb, xf, dim, adjust, suppress,
  431. X      padj, pg, count);
  432. X    back(x, dim) = back(y, dim);  fwd(x, dim) = fwd(y, dim);
  433. X      }
  434. X      break;
  435. X
  436. X
  437. X    case HCONTRACT:
  438. X    case VCONTRACT:
  439. X    
  440. X      CountChild(y, Down(x), count);
  441. X      if( (dim == COL) == (type(x) == HCONTRACT) )
  442. X      {    FixAndPrintObject(y, xmk, back(y,dim), fwd(y,dim), dim, LAST_ADJUST,
  443. X      NO_SUPPRESS, padj, pg, count);
  444. X        back(x, dim) = xb;  fwd(x, dim) = xf;
  445. X      }
  446. X      else
  447. X      {    FixAndPrintObject(y, xmk, xb, xf, dim, adjust, suppress, padj,pg,count);
  448. X        back(x, dim) = back(y, dim);  fwd(x, dim) = fwd(y, dim);
  449. X      }
  450. X      break;
  451. X
  452. X
  453. X    case ONE_COL:
  454. X    case ONE_ROW:
  455. X    case HEXPAND:
  456. X    case VEXPAND:
  457. X    
  458. X      CountChild(y, Down(x), count);
  459. X      if( (dim == COL) == (type(x) == ONE_COL || type(x) == HEXPAND) )
  460. X      { FixAndPrintObject(y, xmk, xb, xf, dim, LAST_ADJUST,
  461. X        NO_SUPPRESS, padj, pg, count);
  462. X        back(x, dim) = xb;  fwd(x, dim) = xf;
  463. X      }
  464. X      else
  465. X      {    FixAndPrintObject(y, xmk, xb, xf, dim, adjust, suppress, padj,pg,count);
  466. X    back(x, dim) = back(y, dim);  fwd(x, dim) = fwd(y, dim);
  467. X      }
  468. X      break;
  469. X
  470. X
  471. X    case PADJUST:
  472. X    
  473. X      CountChild(y, Down(x), count);
  474. X      FixAndPrintObject(y, xmk, xb, xf, dim, adjust, suppress,
  475. X    ALL_ADJUST, pg, count);
  476. X      back(x, dim) = back(y, dim);  fwd(x, dim) = fwd(y, dim);
  477. X      break;
  478. X
  479. X
  480. X    case HADJUST:
  481. X    case VADJUST:
  482. X    
  483. X      CountChild(y, Down(x), count);
  484. X      if( (dim == COL) == (type(x) == HADJUST) )
  485. X      {    FixAndPrintObject(y, xmk, xb, xf, dim, ALL_ADJUST, suppress,
  486. X      padj, pg, count);
  487. X        back(x, dim) = xb;  fwd(x, dim) = xf;
  488. X      }
  489. X      else
  490. X      {    FixAndPrintObject(y, xmk, xb, xf, dim, adjust, suppress,
  491. X      padj, pg, count);
  492. X    back(x, dim) = back(y, dim);  fwd(x, dim) = fwd(y, dim);
  493. X      }
  494. X      break;
  495. X
  496. X
  497. X    case VSCALE:
  498. X
  499. X      debug0(DRS, D, "FixAndPrintObject at VSCALE");
  500. X      CountChild(y, Down(x), count);
  501. X      if( dim == COL )
  502. X      {    FixAndPrintObject(y, xmk, xb, xf, dim, LAST_ADJUST, NO_SUPPRESS,
  503. X        padj,pg,count);
  504. X      }
  505. X      else if( (scale_factor = ScaleFactor(xb+xf, size(y, ROW))) > 0 )
  506. X      {    SaveGraphicState();
  507. X    CoordTranslate(0, pg - (xmk-xb + (LENGTH) (back(y, ROW)*scale_factor)));
  508. X    CoordScale(1.0, scale_factor);
  509. X        FixAndPrintObject(y, 0, back(y, ROW), fwd(y, ROW), dim, LAST_ADJUST,
  510. X        NO_SUPPRESS, padj, 0, count);
  511. X    RestoreGraphicState();
  512. X      }
  513. X      else if( !is_word(type(y)) || string(y)[0] != '\0' )
  514. X      {    Error(WARN, &fpos(x), "object deleted: cannot %s", KW_VSCALE);
  515. X      }
  516. X      back(x, dim) = xb;  fwd(x, dim) = xf;
  517. X      break;
  518. X
  519. X
  520. X    case HSCALE:
  521. X    
  522. X      debug0(DRS, DD, "FixAndPrintObject at HSCALE");
  523. X      CountChild(y, Down(x), count);
  524. X      if( dim == COL )
  525. X      {    save_mark(x) = xmk;
  526. X    bc(constraint(x)) = xb;
  527. X    fc(constraint(x)) = xf;
  528. X        if( (scale_factor = ScaleFactor(xb+xf, size(y, COL))) > 0 )
  529. X      FixAndPrintObject(y, 0, back(y, COL), fwd(y, COL), dim, LAST_ADJUST,
  530. X        NO_SUPPRESS, LAST_ADJUST, pg, count);
  531. X        else if( !is_word(type(y)) || string(y)[0] != '\0' )
  532. X      Error(WARN, &fpos(y), "object deleted: cannot %s", KW_HSCALE);
  533. X      }
  534. X      else if( (scale_factor =
  535. X    ScaleFactor(bc(constraint(x))+fc(constraint(x)), size(y, COL))) > 0 )
  536. X      {    SaveGraphicState();
  537. X    CoordTranslate(save_mark(x) - bc(constraint(x))
  538. X       + (LENGTH) (back(y, COL)*scale_factor), 0);
  539. X    CoordScale(scale_factor, 1.0);
  540. X        FixAndPrintObject(y, xmk, xb, xf, dim, LAST_ADJUST,
  541. X        NO_SUPPRESS, padj, pg, count);
  542. X    RestoreGraphicState();
  543. X      }
  544. X      back(x, dim) = xb;  fwd(x, dim) = xf;
  545. X      break;
  546. X
  547. X
  548. X    case SCALE:
  549. X
  550. X      CountChild(y, Down(x), count);
  551. X      if( dim == COL )
  552. X      {
  553. X    assert( bc(constraint(x)) > 0, "FAPO: horizontal scale factor!" );
  554. X    save_mark(x) = xmk;
  555. X    yb = xb * SF / bc(constraint(x));
  556. X    yf = xf * SF / bc(constraint(x));
  557. X        FixAndPrintObject(y, 0, yb, yf, dim, LAST_ADJUST, NO_SUPPRESS,
  558. X        padj, pg, count);
  559. X      }
  560. X      else
  561. X      {
  562. X    assert( fc(constraint(x)) > 0, "FAPO: vertical scale factor!" );
  563. X    yb = xb * SF / fc(constraint(x));
  564. X    yf = xf * SF / fc(constraint(x));
  565. X    SaveGraphicState();
  566. X    CoordTranslate(save_mark(x), pg - xmk);
  567. X    CoordScale( (float) bc(constraint(x))/SF, (float) fc(constraint(x))/SF);
  568. X        FixAndPrintObject(y, 0, yb, yf, dim, LAST_ADJUST, NO_SUPPRESS,
  569. X        padj,0,count);
  570. X    RestoreGraphicState();
  571. X      }
  572. X      back(x, dim) = xb;  fwd(x, dim) = xf;
  573. X      break;
  574. X
  575. X
  576. X    case ROTATE:
  577. X    
  578. X      CountChild(y, Down(x), count);
  579. X      if( dim == COL )
  580. X      {    save_mark(x) = xmk;
  581. X    back(x, dim) = xb;
  582. X    fwd(x, dim)  = xf;
  583. X      }
  584. X      else
  585. X      {
  586. X    CONSTRAINT colc, rowc, yc;
  587. X    back(x, dim) = xb;
  588. X    fwd(x, dim)  = xf;
  589. X    SetConstraint(colc, back(x,COL), MAX_LEN, fwd(x,COL));
  590. X    SetConstraint(rowc, back(x,ROW), MAX_LEN, fwd(x,ROW));
  591. X    RotateConstraint(&yc, y, sparec(constraint(x)), &colc, &rowc, COL);
  592. X    FixAndPrintObject(y, 0, bc(yc), fc(yc), COL, LAST_ADJUST,
  593. X        NO_SUPPRESS, padj, pg, count);
  594. X    SaveGraphicState();
  595. X    CoordTranslate(save_mark(x), pg - xmk);
  596. X    CoordRotate(sparec(constraint(x)));
  597. X    RotateConstraint(&yc, y, sparec(constraint(x)), &colc, &rowc, ROW);
  598. X    FixAndPrintObject(y, 0, bc(yc), fc(yc), ROW, LAST_ADJUST,
  599. X        NO_SUPPRESS, padj, 0, count);
  600. X    RestoreGraphicState();
  601. X      }
  602. X      back(x, dim) = xb;  fwd(x, dim) = xf;
  603. X      break;
  604. X
  605. X
  606. X    case GRAPHIC:
  607. X    
  608. X      CountChild(y, LastDown(x), count);
  609. X      if( dim == COL )
  610. X      {
  611. X    back(x, dim) = xb;
  612. X    fwd(x, dim)  = xf;
  613. X    debug2(DGP, DD, "GRAPHIC COL storing size %s, %s",
  614. X      EchoLength(back(x, dim)), EchoLength(fwd(x, dim)));
  615. X    save_mark(x) = xmk - back(x, COL);
  616. X        FixAndPrintObject(y, xb, xb, xf, dim, LAST_ADJUST,
  617. X        NO_SUPPRESS, padj, pg, count);
  618. X      }
  619. X      else
  620. X      { OBJECT tmp, pre, post;
  621. X        Child(tmp, Down(x));
  622. X        if( type(tmp) == VCAT )
  623. X        { Child(pre, Down(tmp));
  624. X          Child(post, LastDown(tmp));
  625. X        }
  626. X        else pre = tmp, post = nil;
  627. X    back(x, dim) = xb;
  628. X    fwd(x, dim)  = xf;
  629. X        SaveGraphicState();
  630. X        CoordTranslate(save_mark(x), pg - (xmk + fwd(x, ROW)));
  631. X    debug4(DGP, DD, "GRAPHIC ROW calling %s,%s %s,%s",
  632. X      EchoLength(back(x, COL)), EchoLength(fwd(x, COL)),
  633. X      EchoLength(back(x, ROW)), EchoLength(fwd(x, ROW)));
  634. X        DefineGraphicNames(x);
  635. X        SaveGraphicState();
  636. X        PrintGraphicObject(pre);
  637. X        RestoreGraphicState();
  638. X        FixAndPrintObject(y, xb, xb, xf, dim, LAST_ADJUST,
  639. X        NO_SUPPRESS, padj, xb + xf, count);
  640. X        if( post != nil )  PrintGraphicObject(post);
  641. X        RestoreGraphicState();
  642. X      }
  643. X      back(x, dim) = xb;  fwd(x, dim) = xf;
  644. X      break;
  645. X
  646. X
  647. X    case INCGRAPHIC:
  648. X    case SINCGRAPHIC:
  649. X
  650. X      CountChild(y, Down(x), count);
  651. X      if( dim == COL )
  652. X      {    save_mark(x) = xmk;
  653. X      }
  654. X      else if( sparec(constraint(x)) )
  655. X      {
  656. X    PrintGraphicInclude(x, save_mark(x), pg - xmk);
  657. X      }
  658. X      back(x, dim) = xb;  fwd(x, dim) = xf;
  659. X      break;
  660. X
  661. X
  662. X    case SPLIT:
  663. X    
  664. X      link = DownDim(x, dim);  CountChild(y, link, count);
  665. X      FixAndPrintObject(y, xmk, xb, xf, dim, adjust, suppress, padj, pg, count);
  666. X      back(x, dim) = back(y, dim);  fwd(x, dim) = fwd(y, dim);
  667. X      break;
  668. X
  669. X
  670. X    case VCAT:
  671. X    case HCAT:
  672. X
  673. X      if( (type(x) == VCAT) == (dim == ROW) )
  674. X      { 
  675. X    /* find adjustment increment if required */
  676. X    frame_size = xb + xf;
  677. X    if( adjust == ALL_ADJUST && !suppress )
  678. X      inc = FindAdjustIncrement(x, frame_size, dim);
  679. X    else inc = 0;
  680. X
  681. X    FirstDefinite(x, link, prev);
  682. X    if( link != x )
  683. X    { back_edge = xmk - back(x, dim);
  684. X      mk = back_edge + back(prev, dim);
  685. X      NextDefiniteWithGap(x, link, y, g);
  686. X      while( link != x )
  687. X      {
  688. X        FixAndPrintObject(prev, mk, back(prev, dim), fwd(prev, dim) + inc,
  689. X          dim, adjust, NO_SUPPRESS, padj, pg, count);
  690. X        /* NB fwd(prev, dim) may be changed by the call to FAPO */
  691. X        mk += ActualGap(fwd(prev, dim), back(y, dim), fwd(y, dim), &gap(g),
  692. X            frame_size, mk - back_edge);
  693. X        prev = y;
  694. X        NextDefiniteWithGap(x, link, y, g);
  695. X      }
  696. X      if( suppress )
  697. X        FixAndPrintObject(prev, mk, back(prev, dim), fwd(prev, dim),
  698. X          dim, adjust, NO_SUPPRESS, padj, pg, count);
  699. X      else
  700. X        FixAndPrintObject(prev, mk, back(prev,dim),
  701. X          max(fwd(prev, dim), back_edge+frame_size-mk),
  702. X          dim, adjust, NO_SUPPRESS, padj, pg, count);
  703. X      back(x, dim) = max(back(x, dim), xb);
  704. X      fwd(x, dim) = mk + fwd(prev, dim) - back_edge - back(x, dim);
  705. X    }
  706. X    else back(x, dim) = xb, fwd(x, dim) = xf;
  707. X      }
  708. X      else
  709. X      { OBJECT start_group, zlink, m;  BOOLEAN dble_found;  LENGTH b, f, dlen;
  710. X    start_group = nil;  dble_found = FALSE;  dlen = 0;
  711. X    debug0(DGP, DD, "  groups beginning.");
  712. X    for( link = Down(x);  link != x;  link = NextDown(link) )
  713. X    {
  714. X      Child(y, link);
  715. X      debug1(DGP, DD, "  examining %s", EchoObject(y));
  716. X      if( is_index(type(y)) )  continue;
  717. X      if( type(y) == GAP_OBJ )
  718. X      { 
  719. X        assert( start_group != nil, "FAPO: start_group!" );
  720. X        if( !join(gap(y)) )
  721. X        { 
  722. X          /* finish off and fix this group */
  723. X          debug2(DGP, DD, "  finishing group: b = %s, f = %s",
  724. X            EchoLength(b), EchoLength(f));
  725. X          FixAndPrintObject(m, xmk+b, b, xf-b, dim, adjust,
  726. X              NO_SUPPRESS, padj, pg, count);
  727. X          b = back(m, dim);  f = fwd(m, dim);
  728. X          for( zlink = start_group;  zlink != link;  zlink=NextDown(zlink) )
  729. X          {    CountChild(z, zlink, count);
  730. X        if( !is_definite(type(z)) || z == m )  continue;
  731. X        FixAndPrintObject(z, xmk + b, b, xf - b, dim,
  732. X              adjust, SUPPRESS, padj, pg, count);
  733. X        b = max(b, back(z, dim));  f = max(f, fwd(z, dim));
  734. X          }
  735. X          dlen = max(dlen, b + f);
  736. X          dble_found = TRUE;
  737. X          start_group = nil;
  738. X        }
  739. X      }
  740. X      else if( start_group == nil )
  741. X      {
  742. X        /* start new group */
  743. X        b = back(y, dim);
  744. X        f = fwd(y, dim);
  745. X        m = y;
  746. X        start_group = link;
  747. X        debug2(DGP, DD, "  starting group: b = %s, f = %s",
  748. X          EchoLength(b), EchoLength(f));
  749. X      }
  750. X      else
  751. X      {
  752. X        /* continue with current group */
  753. X        b = max(b, back(y, dim));
  754. X        f = max(f, fwd(y, dim));
  755. X        if( fwd(y, dim) > fwd(m, dim) )  m = y;
  756. X        debug2(DGP, DD, "  continuing group: b = %s, f = %s",
  757. X          EchoLength(b), EchoLength(f));
  758. X      }
  759. X    }
  760. X    assert( start_group != nil, "FAPO: final start_group!" );
  761. X
  762. X    if( dble_found )
  763. X    {
  764. X      /* finish off and fix this last group */
  765. X      debug2(DGP, DD, "  finishing last group: b = %s, f = %s",
  766. X          EchoLength(b), EchoLength(f));
  767. X      FixAndPrintObject(m, xmk + b, b, xf - b, dim, adjust,
  768. X        NO_SUPPRESS, padj, pg, count);
  769. X      b = back(m, dim);  f = fwd(m, dim);
  770. X      for( zlink = start_group;  zlink != link;  zlink = NextDown(zlink) )
  771. X      { CountChild(z, zlink, count);
  772. X        if( !is_definite(type(z)) || z == m )  continue;
  773. X        FixAndPrintObject(z, xmk + b, b, xf - b, dim, adjust,
  774. X        SUPPRESS, padj, pg, count);
  775. X        b = max(b, back(z, dim));  f = max(f, fwd(z, dim));
  776. X      }
  777. X      dlen = max(dlen, b + f);
  778. X      back(x, dim) = 0;  fwd(x, dim) = dlen;
  779. X    }
  780. X    else
  781. X    {
  782. X      /* finish off and fix this last and only group */
  783. X      debug2(DGP, DD, "  finishing last and only group: b = %s, f = %s",
  784. X          EchoLength(b), EchoLength(f));
  785. X      FixAndPrintObject(m, xmk, xb, xf, dim, adjust,
  786. X         NO_SUPPRESS, padj, pg, count);
  787. X      b = back(m, dim);  f = fwd(m, dim);
  788. X      for( zlink = start_group;  zlink != link;  zlink = NextDown(zlink) )
  789. X      { CountChild(z, zlink, count);
  790. X        if( !is_definite(type(z)) || z == m )  continue;
  791. X        FixAndPrintObject(z, xmk, xb, xf, dim, adjust,
  792. X        SUPPRESS, padj, pg, count);
  793. X        b = max(b, back(z, dim));  f = max(f, fwd(z, dim));
  794. X      }
  795. X      back(x, dim) = b;  fwd(x, dim) = f;
  796. X    }
  797. X      }
  798. X      break;
  799. X
  800. X
  801. X    case ACAT:
  802. X
  803. X      if( dim == COL )
  804. X      { BOOLEAN bad_gap;
  805. X    LENGTH actual_size,
  806. X    adjust_indent, frame_size, back_edge, adjust_inc, inc;
  807. X    int adjustable_gaps;
  808. X      
  809. X
  810. X    /*********************************************************************/
  811. X    /*                                                                   */
  812. X    /*  The first step is to calculate the following values:             */
  813. X    /*                                                                   */
  814. X    /*    bad_gap          TRUE if an adjust-preventing gap is found     */
  815. X    /*                                                                   */
  816. X    /*    actual_size      the actual size of x;                         */
  817. X    /*                                                                   */
  818. X    /*    adjustable_gaps  the number of gaps to the right of the        */
  819. X    /*                     right-most tab gap.                           */
  820. X    /*                                                                   */
  821. X    /*  These make it easy to perform adjustment on a second pass, if    */
  822. X    /*  required.                                                        */
  823. X    /*                                                                   */
  824. X    /*********************************************************************/
  825. X
  826. X    FirstDefinite(x, link, y);
  827. X    if( link == x )  break;  /* no definite children, nothing to print */
  828. X    bad_gap = FALSE;
  829. X    adjustable_gaps = 0;
  830. X    back_edge = xmk - xb;
  831. X    mk = back_edge + back(y, dim);
  832. X    frame_size = xb + xf;
  833. X    prev = y;
  834. X    NextDefiniteWithGap(x, link, y, g);
  835. X    while( link != x )
  836. X    {
  837. X      save_actual_gap(g) = ActualGap(fwd(prev, dim), back(y, dim),
  838. X        fwd(y, dim), &gap(g), frame_size, mk - back_edge);
  839. X      mk += save_actual_gap(g);
  840. X      if( mode(gap(g)) == TAB_MODE || units(gap(g)) == AVAIL_UNIT
  841. X                       || units(gap(g)) == FRAME_UNIT )
  842. X      { bad_gap = TRUE;
  843. X      }
  844. X      else if( width(gap(g)) > 0 )  adjustable_gaps += 1;
  845. X      prev = y;
  846. X      NextDefiniteWithGap(x, link, y, g);
  847. X    }
  848. X    actual_size = mk + fwd(prev, dim) - back_edge;
  849. X
  850. X    /*********************************************************************/
  851. X    /*                                                                   */
  852. X    /*  The second step is to work out whether adjusting is required     */
  853. X    /*  or not, and if so by how much, using the following variables:    */
  854. X    /*                                                                   */
  855. X    /*    adjust_inc       The amount of adjustment to apply initially.  */
  856. X    /*                                                                   */
  857. X    /*    adjust_indent    initial indent for centring etc.              */
  858. X    /*                                                                   */
  859. X    /*  NB adjust_inc may be negative, if the optimal paragraph          */
  860. X    /*  breaker has chosen to shrink some gaps.                          */
  861. X    /*                                                                   */
  862. X    /*********************************************************************/
  863. X
  864. X    adjust_indent = 0;
  865. X    switch( display_style(save_style(x)) )
  866. X    {
  867. X      case DO_ADJUST:    padj = ALL_ADJUST;
  868. X                break;
  869. X    
  870. X      case DISPLAY_CENTRE:    if( actual_size <= frame_size )
  871. X                { adjust_indent = (frame_size - actual_size)/2;
  872. X                  padj = LAST_ADJUST;
  873. X                }
  874. X                else padj = ALL_ADJUST;
  875. X                debug1(DGP, DD, "cdisp %s", EchoObject(x));
  876. X                break;
  877. X
  878. X      case DISPLAY_RIGHT:    if( actual_size <= frame_size )
  879. X                { adjust_indent = frame_size - actual_size;
  880. X                  padj = LAST_ADJUST;
  881. X                }
  882. X                else padj = ALL_ADJUST;
  883. X                debug1(DGP, DD, "rdisp %s", EchoObject(x));
  884. X                break;
  885. X    }
  886. X
  887. X    if( padj == ALL_ADJUST && adjustable_gaps > 0 && !bad_gap )
  888. X    { adjust_inc = (frame_size - actual_size) / adjustable_gaps;
  889. X      inc = max(adjust_inc, 0);
  890. X    }
  891. X    else adjust_inc = inc = 0;
  892. X
  893. X    debug2(DGP, DD, "ACAT %s %s",
  894. X      EchoStyle(&save_style(x)), EchoObject(x));
  895. X    debug3(DGP,DD,"frame_size = %s, actual_size = %s, adjustable_gaps = %d",
  896. X      EchoLength(frame_size), EchoLength(actual_size), adjustable_gaps);
  897. X    debug2(DGP,DD,"bad_gap = %s, adjust_inc = %s",
  898. X      bool(bad_gap), EchoLength(adjust_inc));
  899. X
  900. X    /*********************************************************************/
  901. X    /*                                                                   */
  902. X    /*  The third and final step is to traverse x, fixing subobjects.    */
  903. X    /*                                                                   */
  904. X    /*********************************************************************/
  905. X
  906. X    FirstDefinite(x, link, y);
  907. X    prev = y;
  908. X    mk = xmk - back(x, dim) + back(y, dim) + adjust_indent;
  909. X    NextDefiniteWithGap(x, link, y, g);
  910. X    while( link != x )
  911. X    {
  912. X      /* fix previous definite now we know it is not the last one  */
  913. X      if( width(gap(g)) > 0 )
  914. X      { FixAndPrintObject(prev, mk, back(prev, dim), fwd(prev, dim) + inc,
  915. X          dim, adjust, NO_SUPPRESS, LAST_ADJUST, pg, count);
  916. X        mk += save_actual_gap(g) + adjust_inc;
  917. X      }
  918. X      else
  919. X      { FixAndPrintObject(prev, mk, back(prev, dim), fwd(prev, dim),
  920. X          dim, adjust, NO_SUPPRESS, LAST_ADJUST, pg, count);
  921. X        mk += save_actual_gap(g);
  922. X      }
  923. X
  924. X      /* move on to next subobject */
  925. X      prev = y;
  926. X      NextDefiniteWithGap(x, link, y, g);
  927. X    }
  928. X
  929. X    /* fix the last definite subobject, prev, which must exist */
  930. X    FixAndPrintObject(prev, mk, back(prev, dim),
  931. X      frame_size - (mk - xmk) - back(x, dim),
  932. X      dim, adjust, NO_SUPPRESS, LAST_ADJUST, pg, count);
  933. X      }
  934. X      else for( link = Down(x);  link != x;  link = NextDown(link) )
  935. X      {    Child(y, link);
  936. X    if( !is_definite(type(y)) )  continue;
  937. X    FixAndPrintObject(y, xmk, xb, xf, dim, adjust, NO_SUPPRESS,
  938. X        padj,pg,count);
  939. X      }
  940. X      back(x, dim) = xb;  fwd(x, dim) = xf;
  941. X      break;
  942. X
  943. X
  944. X    case COL_THR:
  945. X    case ROW_THR:
  946. X
  947. X      /* find and delete the child number count of y */
  948. X      assert( (type(x) == COL_THR) == (dim == COL), "FixAndPrintObject: thr!" );
  949. X      for( link = Down(x), uplink = Up(x), i = 1;
  950. X    link != x && uplink != x && i < count;
  951. X    link = NextDown(link), uplink = NextUp(uplink), i++ );
  952. X      assert( link != x && uplink != x, "FixAndPrintObject: link or uplink!" );
  953. X      CountChild(y, link, count);
  954. X      MoveLink(uplink, link, CHILD);  DeleteLink(link);  /* IMPORTANT!!! */
  955. X      assert( type(y) != GAP_OBJ, "FAPO: THR!");
  956. X
  957. X      /* assign size if not done previously */
  958. X      if( thr_state(x) != FINALSIZE )
  959. X      {    back(x, dim) = xb;  fwd(x, dim) = xf;
  960. X    thr_state(x) = FINALSIZE;
  961. X      }
  962. X
  963. X      /* *** else been here before, size is already decided; do nothing
  964. X      {    if( back(x, dim) > xb || fwd(x, dim) > xf )
  965. X    { Error(WARN, &fpos(y), "wrong %s chosen (sorry!)",
  966. X        dim == COL ? "column width" : "row height");
  967. X      if( back(x, dim) > xb )  back(x, dim) = xb;
  968. X      if( fwd(x, dim)  > xf )  fwd(x, dim)  = xf;
  969. X    }
  970. X      }
  971. X      *** */
  972. X
  973. X      /* fix y */
  974. X      FixAndPrintObject(y, xmk, back(x, dim), fwd(x, dim), dim, LAST_ADJUST,
  975. X    NO_SUPPRESS, padj, pg, count);
  976. X      if( Up(x) == x )  Dispose(x);
  977. X      break;
  978. X
  979. X
  980. X    default:
  981. X    
  982. X      Error(INTERN, no_fpos, "FixAndPrint: found %s", Image(type(x)));
  983. X      break;
  984. X
  985. X  } /* end switch */
  986. X  debug2(DGP, D, "] FixAndPrintObject returning (size now %s,%s).",
  987. X    EchoLength(back(x, dim)), EchoLength(fwd(x, dim)));
  988. X} /* end FixAndPrintObject */
  989. END_OF_FILE
  990.   if test 28455 -ne `wc -c <'z23.c'`; then
  991.     echo shar: \"'z23.c'\" unpacked with wrong size!
  992.   fi
  993.   # end of 'z23.c'
  994. fi
  995. if test -f 'z24.c' -a "${1}" != "-c" ; then 
  996.   echo shar: Will not clobber existing file \"'z24.c'\"
  997. else
  998.   echo shar: Extracting \"'z24.c'\" \(33714 characters\)
  999.   sed "s/^X//" >'z24.c' <<'END_OF_FILE'
  1000. X/*@z24.c:Print Service:PrintInit()@*******************************************/
  1001. X/*                                                                           */
  1002. X/*  LOUT: A HIGH-LEVEL LANGUAGE FOR DOCUMENT FORMATTING (VERSION 2.05)       */
  1003. X/*  COPYRIGHT (C) 1993 Jeffrey H. Kingston                                   */
  1004. X/*                                                                           */
  1005. X/*  Jeffrey H. Kingston (jeff@cs.su.oz.au)                                   */
  1006. X/*  Basser Department of Computer Science                                    */
  1007. X/*  The University of Sydney 2006                                            */
  1008. X/*  AUSTRALIA                                                                */
  1009. X/*                                                                           */
  1010. X/*  This program is free software; you can redistribute it and/or modify     */
  1011. X/*  it under the terms of the GNU General Public License as published by     */
  1012. X/*  the Free Software Foundation; either version 1, or (at your option)      */
  1013. X/*  any later version.                                                       */
  1014. X/*                                                                           */
  1015. X/*  This program is distributed in the hope that it will be useful,          */
  1016. X/*  but WITHOUT ANY WARRANTY; without even the implied warranty of           */
  1017. X/*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            */
  1018. X/*  GNU General Public License for more details.                             */
  1019. X/*                                                                           */
  1020. X/*  You should have received a copy of the GNU General Public License        */
  1021. X/*  along with this program; if not, write to the Free Software              */
  1022. X/*  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.                */
  1023. X/*                                                                           */
  1024. X/*  FILE:         z24.c                                                      */
  1025. X/*  MODULE:       Print Service                                              */
  1026. X/*  EXTERNS:      PrintInit(), PrintPrologue(), PrintOriginIncrement(),      */
  1027. X/*                PrintWord(), PrintClose(), CoordTranslate(),               */
  1028. X/*                CoordRotate(), CoordScale(), SaveGraphicState(),           */
  1029. X/*                RestoreGraphicState(), PrintGraphicObject(),               */
  1030. X/*                DefineGraphicNames(), PrintGraphicInclude()                */
  1031. X/*                                                                           */
  1032. X/*  This module implements the PostScript back end.                          */
  1033. X/*                                                                           */
  1034. X/*****************************************************************************/
  1035. X#include "externs"
  1036. X#define DEFAULT_XHEIGHT 500
  1037. X#define    NO_FONT    0            /* actually stolen from z37.c        */
  1038. X
  1039. X#define printnum(x, fp)                            \
  1040. X{ char buff[20];  register int i, y;                    \
  1041. X  if( x >= 0 )  y = x;                            \
  1042. X  else { y = -x; putc(CH_MINUS, fp); }                    \
  1043. X  i = 0;                                \
  1044. X  do { buff[i++] = numtodigitchar(y % 10);                \
  1045. X     } while( y = y / 10 );                        \
  1046. X  do { putc(buff[--i], fp);                        \
  1047. X     } while( i );                            \
  1048. X}
  1049. X
  1050. Xstatic FILE    *out_fp;        /* output file                       */
  1051. Xstatic FONT_NUM    currentfont;        /* font of most recent atom          */
  1052. Xstatic short    currentxheight2;    /* half xheight in current font      */
  1053. Xstatic BOOLEAN    cpexists;        /* true if a current point exists    */
  1054. Xstatic LENGTH    currenty;        /* if cpexists, its y coordinate     */
  1055. Xstatic int    wordcount;        /* atoms printed since last newline  */
  1056. Xstatic int    pagecount;        /* total number of pages printed     */
  1057. Xstatic BOOLEAN    prologue_done;        /* TRUE after prologue is printed    */
  1058. Xstatic OBJECT    needs;            /* Resource needs of included EPSFs  */
  1059. X
  1060. X
  1061. X/*****************************************************************************/
  1062. X/*                                                                           */
  1063. X/*  PrintInit(file_ptr)                                                      */
  1064. X/*                                                                           */
  1065. X/*  Initialise this module.  Output is to go to FILE file_ptr.               */
  1066. X/*                                                                           */
  1067. X/*****************************************************************************/
  1068. X
  1069. XPrintInit(file_ptr)
  1070. XFILE *file_ptr;
  1071. X{ debug0(DFT, D, "PrintInit()");
  1072. X  out_fp = file_ptr;  prologue_done = FALSE;
  1073. X  currentfont = NO_FONT;  cpexists = FALSE;
  1074. X  wordcount = pagecount = 0;  needs = New(ACAT);
  1075. X  debug0(DFT, D, "PrintInit returning.");
  1076. X}
  1077. X
  1078. X
  1079. X/*@::PrintPrologue@***********************************************************/
  1080. X/*                                                                           */
  1081. X/*  PrintPrologue(h, v)                                                      */
  1082. X/*                                                                           */
  1083. X/*  Generate the standard PostScript prologue, augmented with any @Prologue  */
  1084. X/*  or @SysPrologue files specified by the user.                             */
  1085. X/*  The first non-empty page has width h and height v in Lout units.         */
  1086. X/*  The following PostScript operators are defined:                          */
  1087. X/*                                                                           */
  1088. X/*      scale_factor  fnt       scale and set font                           */
  1089. X/*      x_coordinate  x         move to x_coordinate, current y coordinate   */
  1090. X/*      string        s         show string                                  */
  1091. X/*      number        in        result is number inches                      */
  1092. X/*      number        cm        result is number centimetres                 */
  1093. X/*      number        pt        result is number points                      */
  1094. X/*      number        sp        result is number spaces                      */
  1095. X/*      number        vs        result is number vspaces                     */
  1096. X/*      number        ft        result is number font-sizes                  */
  1097. X/*                                                                           */
  1098. X/*  as well as LoutGraphic, for use with the @Graphic operator:              */
  1099. X/*                                                                           */
  1100. X/*      xsize ysize xmark ymark fr vs sp LoutGraphic -                       */
  1101. X/*                                                                           */
  1102. X/*  Define xmark, ymark, xsize, ysize to be the positions of                 */
  1103. X/*  these features of x, and define symbols ft, vs and sp                    */
  1104. X/*  to be the current font size, line separation, and space width.           */
  1105. X/*                                                                           */
  1106. X/*****************************************************************************/
  1107. X
  1108. XPrintPrologue(h, v)
  1109. XLENGTH h, v;
  1110. X{ FILE_NUM fnum;
  1111. X  debug2(DGP, DD, "PrintPrologue: v = %d   h = %d", v, h);
  1112. X
  1113. X  /* print header comments for PostScript DSC 3.0 output */
  1114. X  if( Encapsulated )
  1115. X    fprintf(out_fp, "%%%!PS-Adobe-3.0 EPSF-3.0\n");
  1116. X  else
  1117. X    fprintf(out_fp, "%%%!PS-Adobe-3.0\n");
  1118. X  fprintf(out_fp, "%%%%Creator: %s\n", LOUT_VERSION);
  1119. X  fprintf(out_fp, "%%%%CreationDate: %s", TimeString());
  1120. X  fprintf(out_fp, "%%%%DocumentNeededResources: (atend)\n");
  1121. X  fprintf(out_fp, "%%%%Pages: (atend)\n");
  1122. X  fprintf(out_fp, "%%%%BoundingBox: 0 0 %d %d\n", h/PT, v/PT);
  1123. X  fprintf(out_fp, "%%%%EndComments\n\n");
  1124. X
  1125. X  /* print procedure definitions part of header */
  1126. X  fprintf(out_fp, "%%%%BeginProlog\n");
  1127. X  fprintf(out_fp, "%%%%BeginResource: procset LoutStartUp\n");
  1128. X  fprintf(out_fp, "/x { currentpoint exch pop moveto } def\n");
  1129. X  fprintf(out_fp, "/s { show } def\n");
  1130. X  fprintf(out_fp, "/in { %d mul } def\n", IN);
  1131. X  fprintf(out_fp, "/cm { %d mul } def\n", CM);
  1132. X  fprintf(out_fp, "/pt { %d mul } def\n", PT);
  1133. X  fprintf(out_fp, "/em { %d mul } def\n", EM);
  1134. X  fprintf(out_fp, "/sp { louts mul } def\n");
  1135. X  fprintf(out_fp, "/vs { loutv mul } def\n");
  1136. X  fprintf(out_fp, "/ft { loutf mul } def\n");
  1137. X  fprintf(out_fp, "/dg {           } def\n\n");
  1138. X
  1139. X  fputs("/LoutGraphic {\n",                      out_fp);
  1140. X  fputs("  /louts exch def\n",                      out_fp);
  1141. X  fputs("  /loutv exch def\n",                      out_fp);
  1142. X  fputs("  /loutf exch def\n",                      out_fp);
  1143. X  fputs("  /ymark exch def\n",                      out_fp);
  1144. X  fputs("  /xmark exch def\n",                      out_fp);
  1145. X  fputs("  /ysize exch def\n",                      out_fp);
  1146. X  fputs("  /xsize exch def\n} def\n\n",                  out_fp);
  1147. X
  1148. X  /* print definition used by Lout output to recode fonts                 */
  1149. X  /* adapted from PostScript Language Reference Manual (2nd Ed), page 275 */
  1150. X  /* usage: /<fullname> <encodingvector> /<originalname> LoutRecode -     */
  1151. X
  1152. X  fputs("/LoutFont\n",                                            out_fp);
  1153. X  fputs("{ findfont exch scalefont setfont\n",                    out_fp);
  1154. X  fputs("} bind def\n\n",                      out_fp);
  1155. X
  1156. X  fputs("/LoutRecode {\n",                                        out_fp);
  1157. X  fputs("  { findfont dup length dict begin\n",                   out_fp);
  1158. X  fputs("    {1 index /FID ne {def} {pop pop} ifelse} forall\n",  out_fp);
  1159. X  fputs("    /Encoding exch def\n",                               out_fp);
  1160. X  fputs("    currentdict end definefont pop\n",                   out_fp);
  1161. X  fputs("  }\n",                                                  out_fp);
  1162. X  fputs("  stopped {}\n",                                         out_fp);
  1163. X  fputs("} bind def\n\n",                                         out_fp);
  1164. X
  1165. X  /* print definitions used by Lout output when including EPSF files      */
  1166. X  /* copied from PostScript Language Reference Manual (2nd Ed.), page 726 */
  1167. X
  1168. X  fputs("/BeginEPSF {\n",                      out_fp);
  1169. X  fputs("  /LoutEPSFState save def\n",                  out_fp);
  1170. X  fputs("  /dict_count countdictstack def\n",              out_fp);
  1171. X  fputs("  /op_count count 1 sub def\n",              out_fp);
  1172. X  fputs("  userdict begin\n",                      out_fp);
  1173. X  fputs("  /showpage { } def\n",                  out_fp);
  1174. X  fputs("  0 setgray 0 setlinecap\n",                  out_fp);
  1175. X  fputs("  1 setlinewidth 0 setlinejoin\n",              out_fp);
  1176. X  fputs("  10 setmiterlimit [] 0 setdash newpath\n",          out_fp);
  1177. X  fputs("  /languagelevel where\n",                  out_fp);
  1178. X  fputs("  { pop languagelevel\n",                  out_fp);
  1179. X  fputs("    1 ne\n",                          out_fp);
  1180. X  fputs("    { false setstrokeadjust false setoverprint\n",      out_fp);
  1181. X  fputs("    } if\n",                          out_fp);
  1182. X  fputs("  } if\n",                          out_fp);
  1183. X  fputs("} bind def\n\n",                      out_fp);
  1184. X
  1185. X  fputs("/EndEPSF {\n",                          out_fp);
  1186. X  fputs("  count op_count sub { pop } repeat\n",          out_fp);
  1187. X  fputs("  countdictstack dict_count sub { end } repeat\n",      out_fp);
  1188. X  fputs("  LoutEPSFState restore\n",                  out_fp);
  1189. X  fputs("} bind def\n",                          out_fp);
  1190. X
  1191. X  fputs("%%EndResource\n\n",                      out_fp);
  1192. X
  1193. X  /* print encoding vectors and font recoding commands */
  1194. X  EvPrintAll(out_fp);
  1195. X  FontPrintAll(out_fp);
  1196. X
  1197. X  /* print prepend files (assumed to be organized as DSC 3.0 Resources) */
  1198. X  for( fnum=FirstFile(PREPEND_FILE);  fnum != NO_FILE;  fnum=NextFile(fnum) )
  1199. X  { FULL_CHAR buff[MAX_LINE];  FILE *fp;
  1200. X    if( (fp = OpenFile(fnum, FALSE, FALSE)) == null )
  1201. X      Error(WARN, PosOfFile(fnum), "cannot open %s file %s",
  1202. X    KW_PREPEND, FileName(fnum));
  1203. X    else if( StringFGets(buff, MAX_LINE, fp) == NULL )
  1204. X      Error(WARN, PosOfFile(fnum), "%s file %s is empty",
  1205. X    KW_PREPEND, FileName(fnum));
  1206. X    else
  1207. X    {
  1208. X      if( !StringBeginsWith(buff, AsciiToFull("%%BeginResource:")) )
  1209. X    Error(WARN, PosOfFile(fnum),
  1210. X      "%s file %s lacks PostScript DSC 3.0 \"%%%%BeginResource:\" comment",
  1211. X      KW_PREPEND, FileName(fnum));
  1212. X      StringFPuts(buff, out_fp);
  1213. X      fprintf(out_fp, "\n%% %s file %s\n", KW_PREPEND, FileName(fnum));
  1214. X      while( StringFGets(buff, MAX_LINE, fp) != NULL )
  1215. X    StringFPuts(buff, out_fp);
  1216. X    }
  1217. X  }
  1218. X
  1219. X  fputs("\n%%EndProlog\n\n", out_fp);
  1220. X  fprintf(out_fp, "%%%%Page: ? %d\n", ++pagecount);
  1221. X  fprintf(out_fp, "%%%%BeginPageSetup\n");
  1222. X  fprintf(out_fp, "/pgsave save def\n");
  1223. X  fprintf(out_fp, "%.4f dup scale %d setlinewidth\n", 1.0 / PT, PT/2);
  1224. X  fprintf(out_fp, "%%%%EndPageSetup\n");
  1225. X  prologue_done = TRUE;
  1226. X} /* end PrintPrologue */
  1227. X
  1228. X
  1229. X/*@::PrintOriginIncrement(), EightBitsToPrintForm[]@**************************/
  1230. X/*                                                                           */
  1231. X/*  PrintOriginIncrement(y)                                                  */
  1232. X/*                                                                           */
  1233. X/*  Move current vertical origin down by y.                                  */
  1234. X/*                                                                           */
  1235. X/*****************************************************************************/
  1236. X
  1237. XPrintOriginIncrement(y)
  1238. XLENGTH y;
  1239. X{ debug1(DGP, D, "PrintOriginIncrement( %d )", y );
  1240. X  fprintf(out_fp, "\npgsave restore\nshowpage\n");
  1241. X  cpexists = FALSE;
  1242. X  currentfont = NO_FONT;
  1243. X  if( Encapsulated )
  1244. X  { PrintClose();
  1245. X    Error(FATAL, no_fpos, "truncating -EPS document at end of first page");
  1246. X  }
  1247. X  fprintf(out_fp, "\n%%%%Page: ? %d\n", ++pagecount);
  1248. X  fprintf(out_fp, "%%%%BeginPageSetup\n");
  1249. X  fprintf(out_fp, "/pgsave save def\n");
  1250. X  fprintf(out_fp, "%.4f dup scale %d setlinewidth\n", 1.0 / PT, PT/2);
  1251. X  fprintf(out_fp, "%%%%EndPageSetup\n");
  1252. X  wordcount = 0;
  1253. X}
  1254. X
  1255. X/*@::EightBitToPrintForm()@***************************************************/
  1256. X/*                                                                           */
  1257. X/*  static char *EightBitToPrintForm[]                                       */
  1258. X/*                                                                           */
  1259. X/*  Given 8-bit character i, returns a string of characters that will be     */
  1260. X/*  interpreted by PostScript as character i when read within a string.      */
  1261. X/*                                                                           */
  1262. X/*      CHAR_OUT==1    Printable ASCII literal, others as escape sequences   */
  1263. X/*      CHAR_OUT==2    Printable ISO-LATIN-1 literal, others escaped         */
  1264. X/*                                                                           */
  1265. X/*****************************************************************************/
  1266. X
  1267. Xstatic char *EightBitToPrintForm[] = {
  1268. X#if CHAR_OUT==0
  1269. X    "",      "\\001", "\\002", "\\003", "\\004", "\\005", "\\006", "\\007",
  1270. X    "\\010", "\\011", "\\012", "\\013", "\\014", "\\015", "\\016", "\\017",
  1271. X    "\\020", "\\021", "\\022", "\\023", "\\024", "\\025", "\\026", "\\027",
  1272. X    "\\030", "\\031", "\\032", "\\033", "\\034", "\\035", "\\036", "\\037",
  1273. X    " ",     "!",     "\"",    "#",     "$",     "%",     "&",     "'",
  1274. X    "\\(",   "\\)",   "*",     "+",     ",",     "-",     ".",     "/",
  1275. X    "0",     "1",     "2",     "3",     "4",     "5",     "6",     "7",
  1276. X    "8",     "9",     ":",     ";",     "<",     "=",     ">",     "?",
  1277. X    "@",     "A",     "B",     "C",     "D",     "E",     "F",     "G",
  1278. X    "H",     "I",     "J",     "K",     "L",     "M",     "N",     "O",
  1279. X    "P",     "Q",     "R",     "S",     "T",     "U",     "V",     "W",
  1280. X    "X",     "Y",     "Z",     "[",     "\\\\",  "]",     "^",     "_",
  1281. X    "`",     "a",     "b",     "c",     "d",     "e",     "f",     "g",
  1282. X    "h",     "i",     "j",     "k",     "l",     "m",     "n",     "o",
  1283. X    "p",     "q",     "r",     "s",     "t",     "u",     "v",     "w",
  1284. X    "x",     "y",     "z",     "{",     "|",     "}",     "~",     "\\177",
  1285. X    "\\200", "\\201", "\\202", "\\203", "\\204", "\\205", "\\206", "\\207",
  1286. X    "\\210", "\\211", "\\212", "\\213", "\\214", "\\215", "\\216", "\\217",
  1287. X    "\\220", "\\221", "\\222", "\\223", "\\224", "\\225", "\\226", "\\227",
  1288. X    "\\230", "\\231", "\\232", "\\233", "\\234", "\\235", "\\236", "\\237",
  1289. X    "\\240", "\\241", "\\242", "\\243", "\\244", "\\245", "\\246", "\\247",
  1290. X    "\\250", "\\251", "\\252", "\\253", "\\254", "\\255", "\\256", "\\257",
  1291. X    "\\260", "\\261", "\\262", "\\263", "\\264", "\\265", "\\266", "\\267",
  1292. X    "\\270", "\\271", "\\272", "\\273", "\\274", "\\275", "\\276", "\\277",
  1293. X    "\\300", "\\301", "\\302", "\\303", "\\304", "\\305", "\\306", "\\307",
  1294. X    "\\310", "\\311", "\\312", "\\313", "\\314", "\\315", "\\316", "\\317",
  1295. X    "\\320", "\\321", "\\322", "\\323", "\\324", "\\325", "\\326", "\\327",
  1296. X    "\\330", "\\331", "\\332", "\\333", "\\334", "\\335", "\\336", "\\337",
  1297. X    "\\340", "\\341", "\\342", "\\343", "\\344", "\\345", "\\346", "\\347",
  1298. X    "\\350", "\\351", "\\352", "\\353", "\\354", "\\355", "\\356", "\\357",
  1299. X    "\\360", "\\361", "\\362", "\\363", "\\364", "\\365", "\\366", "\\367",
  1300. X    "\\370", "\\371", "\\372", "\\373", "\\374", "\\375", "\\376", "\\377"
  1301. X#else
  1302. X#if CHAR_OUT==1
  1303. X    "",      "\\001", "\\002", "\\003", "\\004", "\\005", "\\006", "\\007",
  1304. X    "\\010", "\\011", "\\012", "\\013", "\\014", "\\015", "\\016", "\\017",
  1305. X    "\\020", "\\021", "\\022", "\\023", "\\024", "\\025", "\\026", "\\027",
  1306. X    "\\030", "\\031", "\\032", "\\033", "\\034", "\\035", "\\036", "\\037",
  1307. X    " ",     "!",     "\"",    "#",     "$",     "%",     "&",     "'",
  1308. X    "\\(",   "\\)",   "*",     "+",     ",",     "-",     ".",     "/",
  1309. X    "0",     "1",     "2",     "3",     "4",     "5",     "6",     "7",
  1310. X    "8",     "9",     ":",     ";",     "<",     "=",     ">",     "?",
  1311. X    "@",     "A",     "B",     "C",     "D",     "E",     "F",     "G",
  1312. X    "H",     "I",     "J",     "K",     "L",     "M",     "N",     "O",
  1313. X    "P",     "Q",     "R",     "S",     "T",     "U",     "V",     "W",
  1314. X    "X",     "Y",     "Z",     "[",     "\\\\",  "]",     "^",     "_",
  1315. X    "`",     "a",     "b",     "c",     "d",     "e",     "f",     "g",
  1316. X    "h",     "i",     "j",     "k",     "l",     "m",     "n",     "o",
  1317. X    "p",     "q",     "r",     "s",     "t",     "u",     "v",     "w",
  1318. X    "x",     "y",     "z",     "{",     "|",     "}",     "~",     "\\177",
  1319. X    "\\200", "\\201", "\\202", "\\203", "\\204", "\\205", "\\206", "\\207",
  1320. X    "\\210", "\\211", "\\212", "\\213", "\\214", "\\215", "\\216", "\\217",
  1321. X    "\220",  "\221",  "\222",  "\223",  "\224",  "\225",  "\226",  "\227",
  1322. X    "\230",  "\\231", "\232",  "\233",  "\\234", "\235",  "\236",  "\237",
  1323. X    "\240",  "\241",  "\242",  "\243",  "\244",  "\245",  "\246",  "\247",
  1324. X    "\250",  "\251",  "\252",  "\253",  "\254",  "\255",  "\256",  "\257",
  1325. X    "\260",  "\261",  "\262",  "\263",  "\264",  "\265",  "\266",  "\267",
  1326. X    "\270",  "\271",  "\272",  "\273",  "\274",  "\275",  "\276",  "\277",
  1327. X    "\300",  "\301",  "\302",  "\303",  "\304",  "\305",  "\306",  "\307",
  1328. X    "\310",  "\311",  "\312",  "\313",  "\314",  "\315",  "\316",  "\317",
  1329. X    "\320",  "\321",  "\322",  "\323",  "\324",  "\325",  "\326",  "\327",
  1330. X    "\330",  "\331",  "\332",  "\333",  "\334",  "\335",  "\336",  "\337",
  1331. X    "\340",  "\341",  "\342",  "\343",  "\344",  "\345",  "\346",  "\347",
  1332. X    "\350",  "\351",  "\352",  "\353",  "\354",  "\355",  "\356",  "\357",
  1333. X    "\360",  "\361",  "\362",  "\363",  "\364",  "\365",  "\366",  "\367",
  1334. X    "\370",  "\371",  "\372",  "\373",  "\374",  "\375",  "\376",  "\377"
  1335. X#else
  1336. XIf you are trying to compile this you have the wrong CHAR_OUT value!
  1337. X#endif
  1338. X#endif
  1339. X};
  1340. X
  1341. X/*@::PrintWord()@*************************************************************/
  1342. X/*                                                                           */
  1343. X/*  PrintWord(x, hpos, vpos)                                                 */
  1344. X/*                                                                           */
  1345. X/*  Print word x; its marks cross at the point (hpos, vpos).                 */
  1346. X/*                                                                           */
  1347. X/*****************************************************************************/
  1348. X
  1349. XPrintWord(x, hpos, vpos)
  1350. XOBJECT x;  int hpos, vpos;
  1351. X{ FULL_CHAR *p;
  1352. X
  1353. X  debug4(DGP, DD, "PrintWord( %s, %d, %d ) font %d", string(x),
  1354. X    hpos, vpos, word_font(x));
  1355. X
  1356. X  /* if font is different to previous word then print change */
  1357. X  if( word_font(x) != currentfont )
  1358. X  { currentfont = word_font(x);
  1359. X    currentxheight2 = FontHalfXHeight(currentfont);
  1360. X    fprintf(out_fp, "\n%hd %s\n", FontSize(currentfont, x), FontName(currentfont));
  1361. X  }
  1362. X
  1363. X  /* move to coordinate of x */
  1364. X  debug1(DGP, DDD, "  currentxheight2 = %d", currentxheight2);
  1365. X  vpos = vpos - currentxheight2;
  1366. X  if( cpexists && currenty == vpos )
  1367. X  { printnum(hpos, out_fp);
  1368. X    fputs(" x", out_fp);
  1369. X  }
  1370. X  else
  1371. X  { currenty = vpos;
  1372. X    printnum(hpos, out_fp);
  1373. X    fputs(" ", out_fp);
  1374. X    printnum(currenty, out_fp);
  1375. X    fputs(" moveto", out_fp);
  1376. X    cpexists = TRUE;
  1377. X  }
  1378. X
  1379. X  /* show string(x) */
  1380. X  fputs("(", out_fp);
  1381. X  for( p = string(x);  *p;  p++ )  fputs(EightBitToPrintForm[*p], out_fp);
  1382. X  if( ++wordcount >= 5 )
  1383. X  { fputs(")s\n", out_fp);  wordcount = 0;
  1384. X  }
  1385. X  else fputs(")s ", out_fp);
  1386. X
  1387. X  debug0(DGP, DDD, "PrintWord returning");
  1388. X} /* end PrintWord */
  1389. X
  1390. X
  1391. X/*@::PrintClose(), CoordTranslate()@******************************************/
  1392. X/*                                                                           */
  1393. X/*  PrintClose()                                                             */
  1394. X/*                                                                           */
  1395. X/*  Clean up this module and close output stream.                            */
  1396. X/*                                                                           */
  1397. X/*****************************************************************************/
  1398. X
  1399. XPrintClose()
  1400. X{ OBJECT x, link;  BOOLEAN first_need;
  1401. X  if( prologue_done )
  1402. X  { fprintf(out_fp, "\npgsave restore\nshowpage\n");
  1403. X    fprintf(out_fp, "%%%%Trailer\n");
  1404. X
  1405. X    /* print document fonts line */
  1406. X    /* *** obsolete DSC 1.0 version
  1407. X    fprintf(out_fp, "%%%%DocumentFonts:");
  1408. X    for( link = Down(font_root); link != font_root; link = NextDown(link) )
  1409. X    { OBJECT flink, family, face;
  1410. X      Child(family, link);
  1411. X      for( flink = Down(family);  flink != family;  flink = NextDown(flink) )
  1412. X      {    Child(face, flink);
  1413. X    if( LastDown(face) != Down(face) )
  1414. X    { Child(x, LastDown(face));
  1415. X      fprintf(out_fp, " %s", string(x));
  1416. X    }
  1417. X      }
  1418. X    }
  1419. X    fprintf(out_fp, "\n");
  1420. X    *** */
  1421. X
  1422. X    /* print resource requirements (DSC 3.0 version) - fonts */
  1423. X    first_need = FontNeeded(out_fp);
  1424. X
  1425. X    /* print resource requirements (DSC 3.0 version) - included EPSFs  */
  1426. X    for( link = Down(needs); link != needs; link = NextDown(link) )
  1427. X    { Child(x, link);
  1428. X      assert(is_word(type(x)), "PrintClose: needs!" );
  1429. X      fprintf(out_fp, "%s %s",
  1430. X    first_need ? "%%DocumentNeededResources:" : "%%+", string(x));
  1431. X      first_need = FALSE;
  1432. X    }
  1433. X
  1434. X    fprintf(out_fp, "%%%%Pages: %d\n", pagecount);
  1435. X    fprintf(out_fp, "%%%%EOF\n");
  1436. X  }
  1437. X} /* end PrintClose */
  1438. X
  1439. X
  1440. X/*****************************************************************************/
  1441. X/*                                                                           */
  1442. X/*  CoordTranslate(xdist, ydist)                                             */
  1443. X/*                                                                           */
  1444. X/*  Translate coordinate system by the given x and y distances.              */
  1445. X/*                                                                           */
  1446. X/*****************************************************************************/
  1447. X
  1448. XCoordTranslate(xdist, ydist)
  1449. XLENGTH xdist, ydist;
  1450. X{ debug2(DRS,D,"CoordTranslate(%s, %s)",
  1451. X    EchoLength(xdist), EchoLength(ydist));
  1452. X  fprintf(out_fp, "%d %d translate\n", xdist, ydist);
  1453. X  cpexists = FALSE;  currentfont = NO_FONT;
  1454. X  debug0(DRS, D, "CoordTranslate returning.");
  1455. X} /* end CoordTranslate */
  1456. X
  1457. X/*@::CoordRotate(), CoordScale(), SaveGraphicsState(), etc.@******************/
  1458. X/*                                                                           */
  1459. X/*  CoordRotate(amount)                                                      */
  1460. X/*                                                                           */
  1461. X/*  Rotate coordinate system by given amount (in internal DG units)          */
  1462. X/*                                                                           */
  1463. X/*****************************************************************************/
  1464. X
  1465. XCoordRotate(amount)
  1466. XLENGTH amount;
  1467. X{ debug1(DRS, D, "CoordRotate(%.1f degrees)", (float) amount / DG);
  1468. X  fprintf(out_fp, "%.4f rotate\n", (float) amount / DG);
  1469. X  cpexists = FALSE;
  1470. X  currentfont = NO_FONT;
  1471. X  debug0(DRS, D, "CoordRotate returning.");
  1472. X} /* end CoordRotate */
  1473. X
  1474. X
  1475. X/*****************************************************************************/
  1476. X/*                                                                           */
  1477. X/*  CoordScale(ratio, dim)                                                   */
  1478. X/*                                                                           */
  1479. X/*  Scale coordinate system by ratio in the given dimension.                 */
  1480. X/*                                                                           */
  1481. X/*****************************************************************************/
  1482. X
  1483. XCoordScale(hfactor, vfactor)
  1484. Xfloat hfactor, vfactor;
  1485. X{ char buff[20];
  1486. X  ifdebug(DRS, D, sprintf(buff, "%.3f, %.3f", hfactor, vfactor));
  1487. X  debug1(DRS, D, "CoordScale(%s)", buff);
  1488. X  fprintf(out_fp, "%.4f %.4f scale\n", hfactor, vfactor);
  1489. X  cpexists = FALSE;
  1490. X  currentfont = NO_FONT;
  1491. X  debug0(DRS, D, "CoordScale returning.");
  1492. X} /* end CoordScale */
  1493. X
  1494. X
  1495. X/*****************************************************************************/
  1496. X/*                                                                           */
  1497. X/*  SaveGraphicState()                                                       */
  1498. X/*                                                                           */
  1499. X/*  Save current coord system on stack for later restoration.                */
  1500. X/*                                                                           */
  1501. X/*****************************************************************************/
  1502. X
  1503. XSaveGraphicState()
  1504. X{ debug0(DRS, D, "SaveGraphicState()");
  1505. X  fprintf(out_fp, "gsave\n");
  1506. X  debug0(DRS, D, "SaveGraphicState returning.");
  1507. X} /* end SaveGraphicState */
  1508. X
  1509. X
  1510. X/*****************************************************************************/
  1511. X/*                                                                           */
  1512. X/*  RestoreGraphicState()                                                    */
  1513. X/*                                                                           */
  1514. X/*  Restore previously saved coordinate system.  NB we normally assume that  */
  1515. X/*  no white space is needed before any item of output, but since this       */
  1516. X/*  procedure is sometimes called immediately after PrintGraphicObject(),    */
  1517. X/*  which does not append a concluding space, we prepend one here.           */
  1518. X/*                                                                           */
  1519. X/*****************************************************************************/
  1520. X
  1521. XRestoreGraphicState()
  1522. X{ debug0(DRS, D, "RestoreGraphicState()");
  1523. X  fprintf(out_fp, "\ngrestore\n");
  1524. X  cpexists = FALSE;
  1525. X  currentfont = NO_FONT;
  1526. X  debug0(DRS, D, "RestoreGraphicState returning.");
  1527. X} /* end RestoreGraphicState */
  1528. X
  1529. X
  1530. X/*@::PrintGraphicObject(), DefineGraphicNames()@******************************/
  1531. X/*                                                                           */
  1532. X/*  PrintGraphicObject(x)                                                    */
  1533. X/*                                                                           */
  1534. X/*  Print object x on out_fp                                                 */
  1535. X/*                                                                           */
  1536. X/*****************************************************************************/
  1537. X
  1538. XPrintGraphicObject(x)
  1539. XOBJECT x;
  1540. X{ OBJECT y, link;
  1541. X  switch( type(x) )
  1542. X  {
  1543. X    case WORD:
  1544. X    case QWORD:
  1545. X    
  1546. X      StringFPuts(string(x), out_fp);
  1547. X      break;
  1548. X    
  1549. X
  1550. X    case ACAT:
  1551. X    
  1552. X      for( link = Down(x);  link != x;  link = NextDown(link) )
  1553. X      {    Child(y, link);
  1554. X    if( type(y) == GAP_OBJ )
  1555. X    { if( vspace(y) > 0 )  fputs("\n", out_fp);
  1556. X      else if( hspace(y) > 0 ) fputs(" ", out_fp);
  1557. X    }
  1558. X    else if( is_word(type(y)) || type(y) == ACAT )  PrintGraphicObject(y);
  1559. X    else if( type(y) != WIDE && !is_index(type(y)) )
  1560. X        /* @Wide, indexes are sometimes inserted by Manifest */
  1561. X    { Error(WARN, &fpos(x), "error in left parameter of %s", KW_GRAPHIC);
  1562. X      debug1(DGP, D, "  type(y) = %s, y =", Image(type(y)));
  1563. X      ifdebug(DGP, D, DebugObject(y));
  1564. X    }
  1565. X      }
  1566. X      break;
  1567. X
  1568. X
  1569. X    default:
  1570. X    
  1571. X      Error(WARN, &fpos(x), "error in left parameter of %s", KW_GRAPHIC);
  1572. X      debug1(DGP, D, "  type(x) = %s, x =", Image(type(x)));
  1573. X      ifdebug(DGP, D, DebugObject(x));
  1574. X      break;
  1575. X  }
  1576. X} /* end PrintGraphicObject */
  1577. X
  1578. X
  1579. X/*****************************************************************************/
  1580. X/*                                                                           */
  1581. X/*  DefineGraphicNames(x)                                                    */
  1582. X/*                                                                           */
  1583. X/*  Generate PostScript for xsize, ysize etc. names of graphic object.       */
  1584. X/*                                                                           */
  1585. X/*****************************************************************************/
  1586. X
  1587. XDefineGraphicNames(x)
  1588. XOBJECT x;
  1589. X{ assert( type(x) == GRAPHIC, "PrintGraphic: type(x) != GRAPHIC!" );
  1590. X  debug1(DRS, D, "DefineGraphicNames( %s )", EchoObject(x));
  1591. X  debug1(DRS, DD, "  style = %s", EchoStyle(&save_style(x)));
  1592. X
  1593. X  fprintf(out_fp, "%d %d %d %d %d %d %d LoutGraphic\n",
  1594. X    size(x, COL), size(x, ROW), back(x, COL), fwd(x, ROW),
  1595. X    font(save_style(x)) <= 0 ? 12*PT : FontSize(font(save_style(x)), x),
  1596. X    width(line_gap(save_style(x))), width(space_gap(save_style(x))));
  1597. X
  1598. X  debug0(DRS, D, "DefineGraphicNames returning.");
  1599. X} /* end DefineGraphicNames */
  1600. X
  1601. X
  1602. X/*@::PrintGraphicIncldue()@***************************************************/
  1603. X/*                                                                           */
  1604. X/*  PrintGraphicInclude(x, colmark, rowmark)                                 */
  1605. X/*                                                                           */
  1606. X/*  Print graphic include file, with appropriate surrounds.  This code       */
  1607. X/*  closely follows the PostScript Language Reference Manual, 2n ed.,        */
  1608. X/*  pages 733-5, except we do not clip the included EPSF.                    */
  1609. X/*                                                                           */
  1610. X/*  Note to porters: Version 3.0 of the EPSF standard is not compatible      */
  1611. X/*  with previous versions.  Thus, this output may crash your system.        */
  1612. X/*  If you can find out which comment line(s) are causing the trouble,       */
  1613. X/*  you can add to procedure strip_out to strip them out during the          */
  1614. X/*  file inclusion step.  e.g. on my system %%EOF causes problems, so I      */
  1615. X/*  strip it out.                                                            */
  1616. X/*                                                                           */
  1617. X/*****************************************************************************/
  1618. X#define    SKIPPING    0
  1619. X#define    READING_DNR    1
  1620. X#define FINISHED    2
  1621. X
  1622. Xstatic BOOLEAN strip_out(buff)
  1623. XFULL_CHAR *buff;
  1624. X{ if( StringBeginsWith(buff, AsciiToFull("%%EOF")) )  return TRUE;
  1625. X  return FALSE;
  1626. X} /* end strip_out */
  1627. X
  1628. XPrintGraphicInclude(x, colmark, rowmark)
  1629. XOBJECT x; LENGTH colmark, rowmark;
  1630. X{ OBJECT y, full_name;  FULL_CHAR buff[MAX_LINE];
  1631. X  FILE *fp;  int state;
  1632. X  debug0(DRS, D, "PrintGraphicInclude(x)");
  1633. X  assert(type(x)==INCGRAPHIC || type(x)==SINCGRAPHIC, "PrintGraphicInclude!");
  1634. X  assert(sparec(constraint(x)), "PrintGraphicInclude: sparec(constraint(x))!");
  1635. X
  1636. X  /* open the include file and get its full path name */
  1637. X  Child(y, Down(x));
  1638. X  fp = OpenIncGraphicFile(string(y), type(x), &full_name, &fpos(y));
  1639. X  assert( fp != NULL, "PrintGraphicInclude: fp!" );
  1640. X
  1641. X  /* generate appropriate header code */
  1642. X  fprintf(out_fp, "BeginEPSF\n");
  1643. X  CoordTranslate(colmark - back(x, COL), rowmark - fwd(x, ROW));
  1644. X  CoordScale( (float) PT, (float) PT );
  1645. X  CoordTranslate(-back(y, COL), -back(y, ROW));
  1646. X  fprintf(out_fp, "%%%%BeginDocument: %s\n", string(full_name));
  1647. X
  1648. X  /* copy through the include file, except divert resources lines to needs */
  1649. X  /* and strip out some comment lines that cause problems                  */
  1650. X  state = (StringFGets(buff, MAX_LINE, fp) == NULL) ? FINISHED : SKIPPING;
  1651. X  while( state != FINISHED ) switch(state)
  1652. X  {
  1653. X    case SKIPPING:
  1654. X
  1655. X      if( StringBeginsWith(buff, AsciiToFull("%%DocumentNeededResources:")) &&
  1656. X      !StringContains(buff, AsciiToFull("(atend)")) )
  1657. X      { x = MakeWord(WORD, &buff[StringLength("%%DocumentNeededResources:")],
  1658. X          no_fpos);
  1659. X        Link(needs, x);
  1660. X    state = (StringFGets(buff,MAX_LINE,fp)==NULL) ? FINISHED : READING_DNR;
  1661. X      }
  1662. X      else
  1663. X      { if( StringBeginsWith(buff, AsciiToFull("%%LanguageLevel:")) )
  1664. X      Error(WARN, &fpos(x), "ignoring \"%%%%LanguageLevel\" in %s file %s",
  1665. X        KW_INCGRAPHIC, string(full_name));
  1666. X    if( StringBeginsWith(buff, AsciiToFull("%%Extensions:")) )
  1667. X      Error(WARN, &fpos(x), "ignoring \"%%%%Extensions\" in %s file %s",
  1668. X        KW_INCGRAPHIC, string(full_name));
  1669. X    if( !strip_out(buff) )  StringFPuts(buff, out_fp);
  1670. X    state = (StringFGets(buff, MAX_LINE, fp) == NULL) ? FINISHED : SKIPPING;
  1671. X      }
  1672. X      break;
  1673. X
  1674. X    case READING_DNR:
  1675. X
  1676. X      if( StringBeginsWith(buff, AsciiToFull("%%+")) )
  1677. X      {    x = MakeWord(WORD, &buff[StringLength(AsciiToFull("%%+"))], no_fpos);
  1678. X    Link(needs, x);
  1679. X    state = (StringFGets(buff,MAX_LINE,fp)==NULL) ? FINISHED : READING_DNR;
  1680. X      }
  1681. X      else
  1682. X      { if( !strip_out(buff) )  StringFPuts(buff, out_fp);
  1683. X    state = (StringFGets(buff, MAX_LINE, fp) == NULL) ? FINISHED : SKIPPING;
  1684. X      }
  1685. X      break;
  1686. X  }
  1687. X
  1688. X  /* wrapup */
  1689. X  DisposeObject(full_name);
  1690. X  fclose(fp);
  1691. X  fprintf(out_fp, "%%%%EndDocument\nEndEPSF\n");
  1692. X  debug0(DRS, D, "PrintGraphicInclude returning.");
  1693. X} /* end PrintGraphicInclude */
  1694. END_OF_FILE
  1695.   if test 33714 -ne `wc -c <'z24.c'`; then
  1696.     echo shar: \"'z24.c'\" unpacked with wrong size!
  1697.   fi
  1698.   # end of 'z24.c'
  1699. fi
  1700. echo shar: End of archive 10 \(of 35\).
  1701. cp /dev/null ark10isdone
  1702. MISSING=""
  1703. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 ; do
  1704.     if test ! -f ark${I}isdone ; then
  1705.     MISSING="${MISSING} ${I}"
  1706.     fi
  1707. done
  1708. if test "${MISSING}" = "" ; then
  1709.     echo You have unpacked all 35 archives.
  1710.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  1711. else
  1712.     echo You still must unpack the following archives:
  1713.     echo "        " ${MISSING}
  1714. fi
  1715. exit 0
  1716. exit 0 # Just in case...
  1717.