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

  1. Newsgroups: comp.sources.misc
  2. From: jeff@joyce.cs.su.oz.au (Jeff Kingston)
  3. Subject: v38i082:  lout - Lout document formatting system, v2.05, Part14/35
  4. Message-ID: <1993Aug10.032706.17135@sparky.sterling.com>
  5. X-Md4-Signature: 43915ad4b3147f619d5cf1c49d1d6426
  6. Sender: kent@sparky.sterling.com (Kent Landfield)
  7. Organization: Sterling Software
  8. Date: Tue, 10 Aug 1993 03:27:06 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 82
  13. Archive-name: lout/part14
  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:  doc/tr.impl/s4.0 include/fig_prepend z19.c z25.c
  22. # Wrapped by kent@sparky on Sun Aug  8 12:29:25 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 14 (of 35)."'
  26. if test -f 'doc/tr.impl/s4.0' -a "${1}" != "-c" ; then 
  27.   echo shar: Will not clobber existing file \"'doc/tr.impl/s4.0'\"
  28. else
  29.   echo shar: Extracting \"'doc/tr.impl/s4.0'\" \(4101 characters\)
  30.   sed "s/^X//" >'doc/tr.impl/s4.0' <<'END_OF_FILE'
  31. X@Section
  32. X    @Tag { functional }
  33. X    @Title { Implementation of the functional subset }
  34. X@Begin
  35. X@PP
  36. XThe objects and definitions of Lout are very similar to those found in
  37. Xother functional languages, and they form a natural subset of the
  38. Xlanguage.  So we pause here and present an overview of the Basser Lout
  39. Xobject evaluation algorithm.
  40. X@PP
  41. XThe problem is to take an unsized object (pure parse tree), its
  42. Xenvironment (Section {@NumberOf defs.impl}), and its style
  43. X(Section {@NumberOf style}), and to produce a PostScript file for
  44. Xrendering the object on an output device.  This file is essentially a
  45. Xsequence of instructions to print a given string of characters in a
  46. Xgiven font at a given point.
  47. X@PP
  48. XBefore the algorithm begins, the parse tree must be obtained, either by
  49. Xparsing input or by copying from the symbol table.  Afterwards the data
  50. Xstructure must be disposed.  The algorithm proper consists of five
  51. Xpasses, each a recursive traversal of the structure from the root down
  52. Xto the leaves and back.
  53. X@DP
  54. X@I {1.  Evaluation of unsized objects.}  On the way down, calculate
  55. Xenvironments and replace non-recursive, non-receptive symbols by their
  56. Xbodies (Section {@NumberOf defs.impl}); broadcast fonts to the leaves,
  57. Xand paragraph breaking and spacing styles to the paragraph nodes.  On the
  58. Xway back up, delete @Eq { FONT }, @Eq { BREAK }, and @Eq { SPACE } nodes,
  59. Xand insert @Eq { SPLIT }, @Eq { COL }, and @Eq { ROW } nodes
  60. X(Section {@NumberOf objects}).
  61. X@DP
  62. X@I {2.  Width calculations and breaking.}  Calculate the width of every
  63. Xsubobject from the bottom up.  As described in Section {@NumberOf objects},
  64. X@Eq { WIDE } nodes may trigger object breaking sub-traversals during this pass.
  65. X@DP
  66. X@I {3.  Height calculations.}  Calculate the height of every subobject,
  67. Xfrom the bottom up.
  68. X@DP
  69. X@I {4.  Horizontal coordinates.}  Calculate the horizontal coordinate of
  70. Xeach subobject from the top down, and store each leaf's coordinate in
  71. Xthe leaf.
  72. X@DP
  73. X@I {5.  Vertical coordinates and PostScript generation.}  Calculate the
  74. Xvertical coordinate of every subobject from the top down, and at each
  75. Xleaf, retrieve the character string, font, and horizontal coordinate,
  76. Xand print the PostScript instruction for rendering that leaf.
  77. X@DP
  78. XFigure {@NumberOf components} gives the amount of code required for each
  79. X
  80. X@Figure
  81. X    @Tag { components }
  82. X    @Caption { Major components of the Basser Lout interpreter, showing
  83. Xthe approximate number of lines of C code.  }
  84. X@Begin
  85. X@Tab
  86. X   vmargin { 0.5vx }
  87. X   @Fmta { @Col @RR A ! @Col B ! @Col @RR C }
  88. X   @Fmtb { @Col @RR A ! @Col B ! @Col     C }
  89. X{
  90. X   @Rowa A { 1. } B { Initialization } C { 200 }
  91. X   @Rowa A { 2. } B { Memory allocation, ordered dag operations } C { 400 }
  92. X   @Rowa A { 3. } B { Lexical analysis, macros, file handling } C { 1,350 }
  93. X   @Rowa A { 4. } B { Parsing of objects and definitions } C { 1,150 }
  94. X   @Rowa A { 5. } B { Symbol table and call graph } C { 600 }
  95. X   @Rowa A { 6. } B { Evaluation of pure parse trees } C { 1,650 }
  96. X   @Rowa A { 7. } B { Reading, storing, and scaling of fonts } C { 600 }
  97. X   @Rowa A { 8. } B { Cross references and databases } C { 1,000 }
  98. X   @Rowa A { 9. } B { Width and height calculations, and breaking } C { 700 }
  99. X   @Rowa A { 10. } B { @I Constrained and @I AdjustSize } C { 700 }
  100. X   @Rowa A { 11. } B { Transfer of sized objects into galley tree } C { 450 }
  101. X   @Rowa A { 12. } B { Galley flushing algorithm } C { 1,500 }
  102. X   @Rowa A { 13. } B { Coordinate calculations and PostScript output } C { 700 }
  103. X   @Rowa A { 14. } B { Debugging and error handling } C { 1,200 }
  104. X   @Rowb vmargin { 0.1c } C { @Line }
  105. X   @Rowa C { 12,200 }
  106. X}
  107. X@End @Figure
  108. X
  109. Xpass.  Symmetry between horizontal and vertical is exploited throughout
  110. XBasser Lout, and passes 2 and 3, as well as 4 and 5, are executed on
  111. Xshared code.
  112. X@PP
  113. XThe author can see no simple way to reduce the number of passes.  The
  114. Xintroduction of horizontal galleys (Section {@NumberOf horizontal})
  115. Xwould remove the need for the object breaking transformations within this
  116. Xalgorithm that are the principal obstacles in the way of the merging of
  117. Xpasses 2 and 3.
  118. X@End @Section
  119. END_OF_FILE
  120.   if test 4101 -ne `wc -c <'doc/tr.impl/s4.0'`; then
  121.     echo shar: \"'doc/tr.impl/s4.0'\" unpacked with wrong size!
  122.   fi
  123.   # end of 'doc/tr.impl/s4.0'
  124. fi
  125. if test -f 'include/fig_prepend' -a "${1}" != "-c" ; then 
  126.   echo shar: Will not clobber existing file \"'include/fig_prepend'\"
  127. else
  128.   echo shar: Extracting \"'include/fig_prepend'\" \(22299 characters\)
  129.   sed "s/^X//" >'include/fig_prepend' <<'END_OF_FILE'
  130. X%%BeginResource: procset LoutFigPrependGraphic
  131. X%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  132. X%                                                                    %
  133. X%  PostScript @SysPrependGraphic file for @Fig  Jeffrey H. Kingston  %
  134. X%  Version 2.0 (includes CIRCUM label)                 January 1992  %
  135. X%                                                                    %
  136. X%  To assist in avoiding name clashes, the names of all symbols      %
  137. X%  defined here begin with "lfig".  However, this is not feasible    %
  138. X%  with user-defined labels and some labels used by users.           %
  139. X%                                                                    %
  140. X%  <point>      is two numbers, a point.                             %
  141. X%  <length>     is one number, a length                              %
  142. X%  <angle>      is one number, an angle in degrees                   %
  143. X%  <dashlength> is one number, the preferred length of a dash        %
  144. X%                                                                    %
  145. X%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  146. X
  147. Xerrordict begin
  148. X   /handleerror
  149. X   {
  150. X      {  /Times-Roman findfont 8 pt scalefont setfont
  151. X     0 setgray 4 pt 4 pt moveto
  152. X     $error /errorname get
  153. X     dup lfigdict exch known
  154. X     { lfigdict exch get }
  155. X     { 30 string cvs } ifelse
  156. X     show
  157. X     (  Command: ) show
  158. X     $error /command get 30 string cvs show
  159. X      } stopped {} if
  160. X      showpage stop
  161. X   } def
  162. Xend
  163. X
  164. X% concat strings: <string> <string> lfigconcat <string>
  165. X% must be defined outside lfigdict since used in lfigpromotelabels
  166. X/lfigconcat
  167. X{ 2 copy length exch length add string
  168. X  dup 0 4 index putinterval
  169. X  dup 3 index length 3 index putinterval
  170. X  3 1 roll pop pop
  171. X} def
  172. X
  173. X% <string> lfigdebugprint -
  174. X% must be defined outside lfigdict since used in arbitrary places
  175. X% /lfigdebugprint
  176. X% { print
  177. X%   (;  operand stack:\n) print
  178. X%   count copy
  179. X%   count 2 idiv
  180. X%   { ==
  181. X%     (\n) print
  182. X%   } repeat
  183. X%   (\n) print
  184. X% } def
  185. X
  186. X/lfigdict 120 dict def
  187. Xlfigdict begin
  188. X
  189. X% error messages
  190. X/dictfull (dictfull error:  too many labels?) def
  191. X/dictstackoverflow (dictstackoverflow error:  labels nested too deeply?) def
  192. X/execstackoverflow (execstackoverflow error:  figure nested too deeply?) def
  193. X/limitcheck (limitcheck error:  figure nested too deeply or too large?) def
  194. X/syntaxerror (syntaxerror error:  syntax error in text of figure?) def
  195. X/typecheck (typecheck error:  syntax error in text of figure?) def
  196. X/undefined (undefined error:  unknown or misspelt label?) def
  197. X/VMError (VMError error:  run out of memory?) def
  198. X
  199. X% push pi onto stack:  - lfigpi <num>
  200. X/lfigpi 3.14159 def
  201. X
  202. X% arc directions
  203. X/clockwise     false def
  204. X/anticlockwise true  def
  205. X
  206. X% maximum of two numbers:  <num> <num> lfigmax <num>
  207. X/lfigmax { 2 copy gt { pop } { exch pop } ifelse } def
  208. X
  209. X% minimum of two numbers:  <num> <num> lfigmin <num>
  210. X/lfigmin { 2 copy lt { pop } { exch pop } ifelse } def
  211. X
  212. X% add two points:  <point> <point> lfigpadd <point>
  213. X/lfigpadd { exch 3 1 roll add 3 1 roll add exch } def
  214. X
  215. X% subtract first point from second:  <point> <point> lfigpsub <point>
  216. X/lfigpsub { 3 2 roll sub 3 1 roll exch sub exch } def
  217. X
  218. X% max two points:  <point> <point> lfigpmax <point>
  219. X/lfigpmax { exch 3 1 roll lfigmax 3 1 roll lfigmax exch } def
  220. X
  221. X% min two points:  <point> <point> lfigpmin <point>
  222. X/lfigpmin { exch 3 1 roll lfigmin 3 1 roll lfigmin exch } def
  223. X
  224. X% scalar multiplication: <point> <num> lfigpmul <point>
  225. X/lfigpmul { dup 3 1 roll mul 3 1 roll mul exch } def
  226. X
  227. X% point at angle and distance:  <point> <length> <angle> lfigatangle <point>
  228. X/lfigatangle { 2 copy cos mul 3 1 roll sin mul lfigpadd } def
  229. X
  230. X% angle from one point to another:  <point> <point> lfigangle <angle>
  231. X/lfigangle { lfigpsub 2 copy 0 eq exch 0 eq and {pop} {exch atan} ifelse } def
  232. X
  233. X% distance between two points:  <point> <point> lfigdistance <length>
  234. X/lfigdistance { lfigpsub dup mul exch dup mul add sqrt } def
  235. X
  236. X% difference in x coords: <point> <point> lfigxdistance <length>
  237. X/lfigxdistance { pop 3 1 roll pop sub } def
  238. X
  239. X%difference in y coords: <point> <point> lfigydistance <length>
  240. X/lfigydistance { 3 1 roll pop sub exch pop } def
  241. X
  242. X% stroke a solid line:  <length> <dashlength> lfigsolid -
  243. X/lfigsolid
  244. X{  pop pop [] 0 setdash stroke
  245. X} def
  246. X
  247. X% stroke a lfigdashed line:   <length> <dashlength> lfigdashed -
  248. X/lfigdashed
  249. X{  2 copy div 2 le 1 index 0 le or
  250. X   {  exch pop 1 pt lfigmax [ exch dup ] 0 setdash }
  251. X   {  dup [ exch 4 2 roll 2 copy div
  252. X      1 sub 2 div ceiling dup 4 1 roll
  253. X      1 add mul sub exch div ] 0 setdash
  254. X   } ifelse stroke
  255. X} def
  256. X
  257. X% stroke a lfigcdashed line:  <length> <dashlength> lfigcdashed -
  258. X/lfigcdashed
  259. X{  2 copy le 1 index 0 le or
  260. X   {  exch pop 1 pt lfigmax [ exch dup ] copy 0 get 2 div setdash }
  261. X   { dup [ 4 2 roll exch 2 copy exch div
  262. X     2 div ceiling div 1 index sub
  263. X     ] exch 2 div setdash
  264. X   } ifelse stroke
  265. X} def
  266. X
  267. X% stroke a dotted line:  <length> <dashlength> lfigdotted -
  268. X/lfigdotted
  269. X{  dup 0 le
  270. X   {  exch pop 1 pt lfigmax [ exch 0 exch ] 0 setdash }
  271. X   { 1 index exch div ceiling div
  272. X     [ 0 3 2 roll ] 0 setdash
  273. X   } ifelse stroke
  274. X} def
  275. X
  276. X% stroke a noline line:  <length> <dashlength> lfignoline -
  277. X/lfignoline
  278. X{ pop pop
  279. X} def
  280. X
  281. X% painting (i.e. filling): - lfigwhite - (etc.)
  282. X/lfigwhite   { 1.0  setgray fill } def
  283. X/lfiglight   { 0.95 setgray fill } def
  284. X/lfiggrey    { 0.9  setgray fill } def
  285. X/lfiggray    { 0.9  setgray fill } def
  286. X/lfigdark    { 0.7  setgray fill } def
  287. X/lfigblack   { 0.0  setgray fill } def
  288. X/lfignopaint {                   } def
  289. X
  290. X% line caps (and joins, not currently used)
  291. X/lfigbutt       0 def
  292. X/lfiground      1 def
  293. X/lfigprojecting 2 def
  294. X/lfigmiter      0 def
  295. X/lfigbevel      2 def
  296. X
  297. X% shape and labels of the @Box symbol
  298. X/lfigbox
  299. X{
  300. X   0     0     /SW  lfigpointdef
  301. X   xsize 0     /SE  lfigpointdef
  302. X   xsize ysize /NE  lfigpointdef
  303. X   0     ysize /NW  lfigpointdef
  304. X   SE 0.5 lfigpmul /S   lfigpointdef
  305. X   NW 0.5 lfigpmul /W   lfigpointdef
  306. X   W SE lfigpadd   /E   lfigpointdef
  307. X   S NW lfigpadd   /N   lfigpointdef
  308. X   NE 0.5 lfigpmul /CTR lfigpointdef
  309. X   [ CTR NE lfigpsub /lfigboxcircum cvx ] lfigcircumdef
  310. X   SW SE NE NW SW
  311. X} def
  312. X
  313. X% shape and labels of the @Square symbol
  314. X/lfigsquare
  315. X{
  316. X   xsize ysize 0.5 lfigpmul /CTR lfigpointdef
  317. X   CTR xsize xsize ysize ysize lfigpmax 0.5 lfigpmul lfigpadd /NE lfigpointdef
  318. X   CTR 0 0 CTR NE lfigdistance 135 lfigatangle lfigpadd /NW lfigpointdef
  319. X   CTR 0 0 CTR NE lfigdistance 225 lfigatangle lfigpadd /SW lfigpointdef
  320. X   CTR 0 0 CTR NE lfigdistance 315 lfigatangle lfigpadd /SE lfigpointdef
  321. X   SW 0.5 lfigpmul SE 0.5 lfigpmul lfigpadd /S lfigpointdef
  322. X   NW 0.5 lfigpmul NE 0.5 lfigpmul lfigpadd /N lfigpointdef
  323. X   SW 0.5 lfigpmul NW 0.5 lfigpmul lfigpadd /W lfigpointdef
  324. X   SE 0.5 lfigpmul NE 0.5 lfigpmul lfigpadd /E lfigpointdef
  325. X   [ CTR NE lfigpsub /lfigboxcircum cvx ] lfigcircumdef
  326. X   SW SE NE NW SW
  327. X} def
  328. X
  329. X% shape and labels of the @Diamond symbol
  330. X/lfigdiamond
  331. X{
  332. X   xsize 0 0.5 lfigpmul /S   lfigpointdef
  333. X   0 ysize 0.5 lfigpmul /W   lfigpointdef
  334. X   S W         lfigpadd /CTR lfigpointdef
  335. X   CTR W       lfigpadd /N   lfigpointdef
  336. X   CTR S       lfigpadd /E   lfigpointdef
  337. X   [ xsize ysize 0.5 lfigpmul /lfigdiamondcircum cvx ] lfigcircumdef
  338. X   S E N W S
  339. X} def
  340. X
  341. X% shape and labels of the @Ellipse symbol
  342. X/lfigellipse
  343. X{
  344. X   xsize 0 0.5 lfigpmul /S   lfigpointdef
  345. X   0 ysize 0.5 lfigpmul /W   lfigpointdef
  346. X   S W         lfigpadd /CTR lfigpointdef
  347. X   CTR W       lfigpadd /N   lfigpointdef
  348. X   CTR S       lfigpadd /E   lfigpointdef
  349. X   CTR xsize 0 0.3536 lfigpmul lfigpadd 0 ysize 0.3536 lfigpmul lfigpadd /NE lfigpointdef
  350. X   0 ysize 0.3536 lfigpmul CTR xsize 0 0.3536 lfigpmul lfigpadd lfigpsub /SE lfigpointdef
  351. X   xsize 0 0.3536 lfigpmul CTR lfigpsub 0 ysize 0.3536 lfigpmul lfigpadd /NW lfigpointdef
  352. X   0 ysize 0.3536 lfigpmul xsize 0 0.3536 lfigpmul CTR lfigpsub lfigpsub /SW lfigpointdef
  353. X   [ xsize ysize 0.5 lfigpmul /lfigellipsecircum cvx ] lfigcircumdef
  354. X   S [ CTR ] E [ CTR ] N [ CTR ] W [ CTR ] S
  355. X} def
  356. X
  357. X% shape and labels of the @Circle symbol
  358. X/lfigcircle
  359. X{
  360. X   xsize ysize 0.5 lfigpmul /CTR lfigpointdef
  361. X   CTR xsize 0 ysize 0 lfigpmax 0.5 lfigpmul lfigpadd /E lfigpointdef
  362. X   CTR 0 0 CTR E lfigdistance 45 lfigatangle lfigpadd /NE lfigpointdef
  363. X   CTR 0 0 CTR E lfigdistance 90 lfigatangle lfigpadd /N lfigpointdef
  364. X   CTR 0 0 CTR E lfigdistance 135 lfigatangle lfigpadd /NW lfigpointdef
  365. X   CTR 0 0 CTR E lfigdistance 180 lfigatangle lfigpadd /W lfigpointdef
  366. X   CTR 0 0 CTR E lfigdistance 225 lfigatangle lfigpadd /SW lfigpointdef
  367. X   CTR 0 0 CTR E lfigdistance 270 lfigatangle lfigpadd /S lfigpointdef
  368. X   CTR 0 0 CTR E lfigdistance 315 lfigatangle lfigpadd /SE lfigpointdef
  369. X   [ S E lfigpsub /lfigellipsecircum cvx ] lfigcircumdef
  370. X   S [ CTR ] E [ CTR ] N [ CTR ] W [ CTR ] S
  371. X} def
  372. X
  373. X% shape and labels of the @HLine and @HArrow symbols
  374. X/lfighline
  375. X{
  376. X   0 ymark lfigprevious /FROM lfigpointdef
  377. X   xsize ymark lfigprevious /TO lfigpointdef
  378. X} def
  379. X
  380. X% shape and labels of the @VLine and @VArrow symbols
  381. X/lfigvline
  382. X{
  383. X   xmark ysize lfigprevious /FROM lfigpointdef
  384. X   xmark 0 lfigprevious /TO lfigpointdef
  385. X} def
  386. X
  387. X% points of a polygon around base with given no of sides, vert init angle:
  388. X% <sides> <angle> figpolygon <point> ... <point>
  389. X/lfigpolygon
  390. X{  xsize ysize 0.5 lfigpmul /CTR lfigpointdef
  391. X   90 sub CTR 2 copy lfigmax 5 3 roll
  392. X   [ 4 copy pop /lfigpolycircum cvx ] lfigcircumdef
  393. X   exch dup 360 exch div exch
  394. X   1 1  3 2 roll
  395. X   {  4 string cvs (P) exch lfigconcat cvn
  396. X      6 copy pop pop lfigatangle 2 copy 10 2 roll
  397. X      3 2 roll lfigpointdef
  398. X      dup 3 1 roll add exch
  399. X   }  for
  400. X   pop lfigatangle
  401. X} def
  402. X
  403. X% next array element:  <array> <index> lfiggetnext <array> <index> <any> true
  404. X%                                               or <array> <index> false
  405. X/lfiggetnext
  406. X{  2 copy exch length ge
  407. X   { false }
  408. X   { 2 copy get exch 1 add exch true } ifelse
  409. X} def
  410. X
  411. X% check whether thing is number:  <any> lfigisnumbertype <any> <bool>
  412. X/lfigisnumbertype
  413. X{  dup type dup
  414. X   /integertype eq exch /realtype eq or
  415. X} def
  416. X
  417. X% check whether thing is an array:  <any> lfigisarraytype <any> <bool>
  418. X/lfigisarraytype { dup type /arraytype eq } def
  419. X
  420. X% get next item:  <array> <index> lfiggetnextitem <array> <index> 0
  421. X%                                              or <array> <index> <array> 1
  422. X%                                              or <array> <index> <point> 2
  423. X/lfiggetnextitem
  424. X{   lfiggetnext
  425. X    {    lfigisarraytype
  426. X    {   1
  427. X    }
  428. X    {   lfigisnumbertype
  429. X        {    3 1 roll
  430. X        lfiggetnext
  431. X        {   lfigisnumbertype
  432. X            {    4 3 roll exch  2
  433. X            }
  434. X            {    pop 3 2 roll pop  0
  435. X            } ifelse
  436. X        }
  437. X        {   3 2 roll pop  0
  438. X        } ifelse
  439. X        }
  440. X        {    pop 0
  441. X        } ifelse
  442. X    } ifelse
  443. X    }
  444. X    {    0
  445. X    } ifelse
  446. X} def
  447. X
  448. X% set arc path:  bool x1 y1  x2 y2  x0 y0  lfigsetarc  <angle> <angle> <dist>
  449. X% the path goes from x1 y1 to x2 y2 about centre x0 y0,
  450. X% anticlockwise if bool is true else clockwise.
  451. X% The orientations of backwards pointing and forwards pointing
  452. X% arrowheads are returned in the two angles, and
  453. X% the length of the arc is returned in <dist>.
  454. X/lfigsetarc
  455. X{
  456. X  20 dict begin
  457. X     matrix currentmatrix 8 1 roll
  458. X     2 copy translate 2 copy 8 2 roll
  459. X     4 2 roll lfigpsub 6 2 roll lfigpsub
  460. X     dup /y1 exch def dup mul /y1s exch def
  461. X     dup /x1 exch def dup mul /x1s exch def
  462. X     dup /y2 exch def dup mul /y2s exch def
  463. X     dup /x2 exch def dup mul /x2s exch def
  464. X
  465. X     y1s y2s eq
  466. X     {    -1
  467. X     }
  468. X     {    y1s x2s mul y2s x1s mul sub y1s y2s sub div
  469. X     } ifelse
  470. X     /da exch def
  471. X
  472. X     x1s x2s eq
  473. X     {    -1
  474. X     }
  475. X     {    x1s y2s mul x2s y1s mul sub x1s x2s sub div
  476. X     } ifelse
  477. X     /db exch def
  478. X
  479. X     da 0 gt db 0 gt and
  480. X     {    /LMax da sqrt db sqrt lfigmax def
  481. X    /scalex da sqrt LMax div def
  482. X    /scaley db sqrt LMax div def
  483. X    scalex scaley scale
  484. X    0 0 LMax
  485. X    0 0 x1 scalex mul y1 scaley mul lfigangle
  486. X    0 0 x2 scalex mul y2 scaley mul lfigangle
  487. X    2 copy eq { 360 add } if
  488. X    2 copy 8 2 roll
  489. X    5 index { arc } { arcn } ifelse
  490. X    2 index 1 index
  491. X    { 90 sub } { 90 add } ifelse
  492. X    dup sin scaley mul exch cos scalex mul atan
  493. X    2 index 2 index
  494. X    { 90 add } { 90 sub } ifelse
  495. X    dup sin scaley mul exch cos scalex mul atan
  496. X    5 2 roll  % res1 res2 ang1 ang2 anticlockwise
  497. X    { exch sub } { sub } ifelse
  498. X    dup 0 le { 360 add } if  lfigpi mul LMax mul 180 div
  499. X     }
  500. X     {    0 0 x1 y1 lfigdistance 0 0 x2 y2 lfigdistance eq
  501. X    0 0 x1 y1 lfigdistance 0 gt and
  502. X    {    0 0
  503. X        0 0 x1 y1 lfigdistance
  504. X        0 0 x1 y1 lfigangle
  505. X        0 0 x2 y2 lfigangle
  506. X        2 copy eq { 360 add } if
  507. X        2 copy 8 2 roll
  508. X        5 index { arc } { arcn } ifelse
  509. X        2 index 1 index
  510. X        { 90 sub } { 90 add } ifelse
  511. X        2 index 2 index
  512. X        { 90 add } { 90 sub } ifelse
  513. X        5 2 roll % res1 res2 ang1 ang2 clockwise
  514. X        { exch sub } { sub } ifelse
  515. X        dup 0 le { 360 add } if lfigpi mul 0 0 x1 y1 lfigdistance mul 180 div
  516. X    }
  517. X    {    x2 y2 lineto pop
  518. X        x2 y2 x1 y1 lfigangle
  519. X        x1 y1 x2 y2 lfigangle
  520. X        x1 y1 x2 y2 lfigdistance
  521. X    } ifelse
  522. X     } ifelse
  523. X     4 -1 roll setmatrix
  524. X   end
  525. X} def
  526. X
  527. X% lfigsetcurve: set up a Bezier curve from x0 y0 to x3 y3
  528. X% and return arrowhead angles and length of curve (actually 0)
  529. X% x0 y0 x1 y1 x2 y2 x3 y3 lfigsetcurve <angle> <angle> <length>
  530. X/lfigsetcurve
  531. X{ 8 copy curveto pop pop
  532. X  lfigangle
  533. X  5 1 roll
  534. X  4 2 roll lfigangle
  535. X  exch
  536. X  0
  537. X} def
  538. X
  539. X% lfigpaintpath: paint a path of the given shape
  540. X% /paint [ shape ] lfigpaintpath -
  541. X/lfigpaintpath
  542. X{
  543. X  10 dict begin
  544. X    0 newpath
  545. X    /prevseen false def
  546. X    /curveseen false def
  547. X    { lfiggetnextitem
  548. X      dup 0 eq { pop exit }
  549. X      { 1 eq
  550. X        { /curveseen true def
  551. X      /curve exch def
  552. X      curve length 0 eq { /curveseen false def } if
  553. X        }
  554. X        { /ycurr exch def
  555. X      /xcurr exch def
  556. X      prevseen
  557. X      { curveseen
  558. X        { curve length 4 eq
  559. X          { xprev yprev
  560. X        curve 0 get curve 1 get
  561. X        curve 2 get curve 3 get
  562. X        xcurr ycurr
  563. X        lfigsetcurve pop pop pop
  564. X          }
  565. X          { xprev yprev xcurr ycurr
  566. X            curve length 1 ge { curve 0 get } { 0 } ifelse
  567. X            curve length 2 ge { curve 1 get } { 0 } ifelse
  568. X            curve length 3 ge { curve 2 get } { true } ifelse
  569. X            7 1 roll
  570. X            lfigsetarc pop pop pop
  571. X          } ifelse
  572. X        }
  573. X        { xcurr ycurr lineto
  574. X        } ifelse
  575. X      }
  576. X      { xcurr ycurr moveto
  577. X      } ifelse
  578. X      /xprev xcurr def
  579. X      /yprev ycurr def
  580. X      /prevseen true def
  581. X      /curveseen false def
  582. X        } ifelse
  583. X      } ifelse
  584. X    } loop pop pop cvx exec
  585. X  end
  586. X} def
  587. X
  588. X% stroke a path of the given shape in the given linestyle and dash length.
  589. X% Return the origin and angle of the backward and forward arrow heads.
  590. X% dashlength /linestyle [shape] lfigdopath  [<point> <angle>] [<point> <angle>] 
  591. X/lfigdopath
  592. X{
  593. X  10 dict begin
  594. X    0
  595. X    /prevseen  false def
  596. X    /curveseen false def
  597. X    /backarrow []    def
  598. X    /fwdarrow  []    def
  599. X    {
  600. X    lfiggetnextitem
  601. X    dup 0 eq { pop exit }
  602. X    {
  603. X        1 eq
  604. X        {    /curveseen true def
  605. X        /curve exch def
  606. X        curve length 0 eq { /prevseen false def } if
  607. X        }
  608. X        {    /ycurr exch def
  609. X        /xcurr exch def
  610. X        prevseen
  611. X        {   newpath xprev yprev moveto
  612. X            curveseen
  613. X            {    curve length 4 eq
  614. X            {   xprev yprev
  615. X                curve 0 get curve 1 get
  616. X                curve 2 get curve 3 get
  617. X                xcurr ycurr lfigsetcurve
  618. X            }
  619. X            {   xprev yprev xcurr ycurr
  620. X                curve length 1 ge { curve 0 get } { 0 } ifelse
  621. X                curve length 2 ge { curve 1 get } { 0 } ifelse
  622. X                curve length 3 ge { curve 2 get } { true } ifelse
  623. X                7 1 roll
  624. X                lfigsetarc
  625. X            } ifelse
  626. X            }
  627. X            {    xcurr ycurr lineto
  628. X            xcurr ycurr xprev yprev lfigangle dup 180 sub
  629. X            xprev yprev xcurr ycurr lfigdistance
  630. X            } ifelse
  631. X            6 index 6 index cvx exec
  632. X            [ xprev yprev 5 -1 roll ]
  633. X            backarrow length 0 eq
  634. X            { /backarrow exch def }
  635. X            { pop } ifelse
  636. X            [ xcurr ycurr 4 -1 roll ] /fwdarrow exch def
  637. X        } if
  638. X        /xprev xcurr def
  639. X        /yprev ycurr def
  640. X        /prevseen true def
  641. X        /curveseen false def
  642. X        } ifelse
  643. X    } ifelse
  644. X    } loop
  645. X    pop pop pop pop
  646. X    backarrow length 0 eq { [ 0 0 0 ] } { backarrow } ifelse
  647. X    fwdarrow  length 0 eq { [ 0 0 0 ] } { fwdarrow  } ifelse
  648. X  end
  649. X} def
  650. X
  651. X% lfigdoarrow: draw an arrow head of given form
  652. X% dashlength /lstyle /pstyle hfrac height width [ <point> <angle> ] lfigdoarrow -
  653. X/lfigdoarrow
  654. X{  matrix currentmatrix 8 1 roll
  655. X   dup 0 get 1 index 1 get translate
  656. X   2 get rotate
  657. X   [ 2 index neg 2 index 0 0
  658. X     3 index 3 index neg
  659. X     1 index 10 index mul 0
  660. X     7 index 7 index ]
  661. X   4 1 roll pop pop pop
  662. X   dup 3 1 roll
  663. X   gsave lfigpaintpath grestore lfigdopath pop pop
  664. X   setmatrix
  665. X} def
  666. X
  667. X% arrow head styles
  668. X/lfigopen     0.0 def
  669. X/lfighalfopen 0.5 def
  670. X/lfigclosed   1.0 def
  671. X
  672. X% stroke no arrows, forward, back, and both
  673. X/lfignoarrow { pop pop pop pop pop pop pop pop                        } def
  674. X/lfigforward { 7 -1 roll lfigdoarrow pop                              } def
  675. X/lfigback    { 8 -2 roll pop lfigdoarrow                              } def
  676. X/lfigboth    { 8 -1 roll 7 copy lfigdoarrow pop 7 -1 roll lfigdoarrow } def
  677. X
  678. X% lfigprevious: return previous point on path
  679. X/lfigprevious
  680. X{ lfigisnumbertype
  681. X  { 2 copy }
  682. X  { lfigisarraytype
  683. X    { 2 index 2 index }
  684. X    { 0 0 }
  685. X    ifelse
  686. X  } ifelse
  687. X} def
  688. X
  689. X% label a point in 2nd top dictionary:  <point> /name lfigpointdef -
  690. X/lfigpointdef
  691. X{
  692. X  % (Entering lfigpointdef) lfigdebugprint
  693. X  [ 4 2 roll transform
  694. X    /itransform cvx ] cvx
  695. X    currentdict end
  696. X    3 1 roll
  697. X    % currentdict length currentdict maxlength lt
  698. X    % { def }
  699. X    % { exec moveto (too many labels) show stop }
  700. X    % ifelse
  701. X    def
  702. X    begin
  703. X  % (Leaving lfigpointdef) lfigdebugprint
  704. X} def
  705. X
  706. X% promote labels from second top to third top dictionary
  707. X% <string> lfigpromotelabels -
  708. X/lfigpromotelabels
  709. X{
  710. X  % (Entering lfigpromotelabels) lfigdebugprint
  711. X  currentdict end exch currentdict end
  712. X  { exch 20 string cvs 2 index
  713. X    (@) lfigconcat exch lfigconcat cvn exch def
  714. X  } forall pop begin
  715. X  % (Leaving lfigpromotelabels) lfigdebugprint
  716. X} def
  717. X
  718. X% show labels (except CIRCUM): - lfigshowlabels -
  719. X/lfigshowlabels
  720. X{
  721. X  % (Entering lfigshowlabels) lfigdebugprint
  722. X  currentdict end
  723. X    currentdict
  724. X    { 1 index 20 string cvs (CIRCUM) search % if CIRCUM in key
  725. X      { pop pop pop pop pop }
  726. X      { pop cvx exec 2 copy
  727. X        newpath 1.5 pt 0 360 arc
  728. X        0 setgray fill
  729. X        /Times-Roman findfont 8 pt scalefont setfont
  730. X        moveto 0.2 cm 0.1 cm rmoveto 20 string cvs show
  731. X      }
  732. X      ifelse
  733. X    } forall
  734. X  begin
  735. X  % (Leaving lfigshowlabels) lfigdebugprint
  736. X} def
  737. X
  738. X% fix an angle to between 0 and 360 degrees:  <angle> lfigfixangle <angle>
  739. X/lfigfixangle
  740. X{
  741. X  % (Entering lfigfixangle) lfigdebugprint
  742. X  { dup 0 ge { exit } if
  743. X    360 add
  744. X  } loop
  745. X  { dup 360 lt { exit } if
  746. X    360 sub
  747. X  } loop
  748. X  % (Leaving lfigfixangle) lfigdebugprint
  749. X} def
  750. X
  751. X% find point on circumference of box:  alpha a b lfigboxcircum x y
  752. X/lfigboxcircum
  753. X{
  754. X  % (Entering lfigboxcircum) lfigdebugprint
  755. X  4 dict begin
  756. X    /b exch def
  757. X    /a exch def
  758. X    lfigfixangle /alpha exch def
  759. X    0 0 a b lfigangle /theta exch def
  760. X
  761. X    % if alpha <= theta, return (a, a*tan(alpha))
  762. X    alpha theta le
  763. X    { a  a alpha sin mul alpha cos div }
  764. X    {
  765. X      % else if alpha <= 180 - theta, return (b*cot(alpha), b)
  766. X      alpha 180 theta sub le
  767. X      { b alpha cos mul alpha sin div  b }
  768. X      {
  769. X        % else if alpha <= 180 + theta, return (-a, -a*tan(alpha))
  770. X        alpha 180 theta add le
  771. X        { a neg  a neg alpha sin mul alpha cos div }
  772. X        {
  773. X      % else if alpha <= 360 - theta, return (-b*cot(alpha), -b)
  774. X      alpha 360 theta sub le
  775. X          { b neg alpha cos mul alpha sin div  b neg }
  776. X      {
  777. X        % else 360 - theta <= alpha, return (a, a*tan(alpha))
  778. X        a  a alpha sin mul alpha cos div
  779. X      } ifelse
  780. X        } ifelse
  781. X      } ifelse
  782. X    } ifelse
  783. X  end
  784. X  % (Leaving lfigboxcircum) lfigdebugprint
  785. X} def
  786. X
  787. X% find point on circumference of diamond:  alpha a b lfigdiamondcircum x y
  788. X/lfigdiamondcircum
  789. X{
  790. X  % (Entering lfigdiamondcircum) lfigdebugprint
  791. X  4 dict begin
  792. X    /b exch def
  793. X    /a exch def
  794. X    lfigfixangle /alpha exch def
  795. X    b alpha cos abs mul  a alpha sin abs mul  add  /denom exch def
  796. X    a b mul alpha cos mul denom div
  797. X    a b mul alpha sin mul denom div
  798. X  end
  799. X  % (Leaving lfigdiamondcircum) lfigdebugprint
  800. X} def
  801. X
  802. X% find point on circumference of ellipse:  alpha a b lfigellipsecircum x y
  803. X/lfigellipsecircum
  804. X{
  805. X  % (Entering lfigellipsecircum) lfigdebugprint
  806. X  4 dict begin
  807. X    /b exch def
  808. X    /a exch def
  809. X    lfigfixangle /alpha exch def
  810. X    b alpha cos mul dup mul  a alpha sin mul dup mul  add sqrt /denom exch def
  811. X    a b mul alpha cos mul denom div
  812. X    a b mul alpha sin mul denom div
  813. X  end
  814. X  % (Leaving lfigellipsecircum) lfigdebugprint
  815. X} def
  816. X
  817. X% find point of intersection of two lines each defined by two points
  818. X% x1 y1 x2 y2  x3 y3 x4 y4  lfiglineintersect x y
  819. X/lfiglineintersect
  820. X{
  821. X  % (Entering lfiglineintersect) lfigdebugprint
  822. X  13 dict begin
  823. X    /y4 exch def
  824. X    /x4 exch def
  825. X    /y3 exch def
  826. X    /x3 exch def
  827. X    /y2 exch def
  828. X    /x2 exch def
  829. X    /y1 exch def
  830. X    /x1 exch def
  831. X    x2 x1 sub /x21 exch def
  832. X    x4 x3 sub /x43 exch def
  833. X    y2 y1 sub /y21 exch def
  834. X    y4 y3 sub /y43 exch def
  835. X    y21 x43 mul y43 x21 mul sub /det exch def
  836. X  
  837. X    % calculate x 
  838. X    y21 x43 mul x1 mul
  839. X    y43 x21 mul x3 mul sub
  840. X    y3 y1 sub x21 mul x43 mul add
  841. X    det div
  842. X
  843. X    % calculate y
  844. X    x21 y43 mul y1 mul
  845. X    x43 y21 mul y3 mul sub
  846. X    x3 x1 sub y21 mul y43 mul add
  847. X    det neg div
  848. X
  849. X  end
  850. X  % (Leaving lfiglineintersect) lfigdebugprint
  851. X} def
  852. X
  853. X% find point on circumference of polygon
  854. X% alpha radius num theta lfigpolycircum x y
  855. X/lfigpolycircum
  856. X{
  857. X  % (Entering lfigpolycircum) lfigdebugprint
  858. X  13 dict begin
  859. X    /theta exch def
  860. X    /num exch def
  861. X    /radius exch def
  862. X    /alpha exch def
  863. X
  864. X    % calculate delta, the angle from theta to alpha
  865. X    alpha theta sub lfigfixangle
  866. X
  867. X    % calculate the angle which is the multiple of 360/num closest to delta
  868. X    360 num div div truncate 360 num div mul theta add /anglea exch def
  869. X
  870. X    % calculate the next multiple of 360/num after anglea
  871. X    anglea 360 num div add /angleb exch def
  872. X
  873. X    % intersect the line through these two points with the alpha line
  874. X    anglea cos anglea sin  angleb cos angleb sin
  875. X    0 0  alpha cos 2 mul alpha sin 2 mul
  876. X    lfiglineintersect radius lfigpmul
  877. X
  878. X  end
  879. X  % (Leaving lfigpolycircum) lfigdebugprint
  880. X} def
  881. X
  882. X% add CIRCUM operator with this body:  <array> lfigcircumdef -
  883. X/lfigcircumdef
  884. X{   % (Entering lfigcircumdef) lfigdebugprint
  885. X    /CIRCUM exch cvx
  886. X    currentdict end
  887. X    3 1 roll
  888. X    % currentdict length currentdict maxlength lt
  889. X    % { def }
  890. X    % { exec moveto (too many labels) show stop }
  891. X    % ifelse
  892. X    def
  893. X    begin
  894. X    % (Leaving lfigcircumdef) lfigdebugprint
  895. X} def
  896. X
  897. Xend
  898. X%%EndResource
  899. END_OF_FILE
  900.   if test 22299 -ne `wc -c <'include/fig_prepend'`; then
  901.     echo shar: \"'include/fig_prepend'\" unpacked with wrong size!
  902.   fi
  903.   # end of 'include/fig_prepend'
  904. fi
  905. if test -f 'z19.c' -a "${1}" != "-c" ; then 
  906.   echo shar: Will not clobber existing file \"'z19.c'\"
  907. else
  908.   echo shar: Extracting \"'z19.c'\" \(22103 characters\)
  909.   sed "s/^X//" >'z19.c' <<'END_OF_FILE'
  910. X/*@z19.c:Galley Attaching:DetachGalley()@*************************************/
  911. X/*                                                                           */
  912. X/*  LOUT: A HIGH-LEVEL LANGUAGE FOR DOCUMENT FORMATTING (VERSION 2.05)       */
  913. X/*  COPYRIGHT (C) 1993 Jeffrey H. Kingston                                   */
  914. X/*                                                                           */
  915. X/*  Jeffrey H. Kingston (jeff@cs.su.oz.au)                                   */
  916. X/*  Basser Department of Computer Science                                    */
  917. X/*  The University of Sydney 2006                                            */
  918. X/*  AUSTRALIA                                                                */
  919. X/*                                                                           */
  920. X/*  This program is free software; you can redistribute it and/or modify     */
  921. X/*  it under the terms of the GNU General Public License as published by     */
  922. X/*  the Free Software Foundation; either version 1, or (at your option)      */
  923. X/*  any later version.                                                       */
  924. X/*                                                                           */
  925. X/*  This program is distributed in the hope that it will be useful,          */
  926. X/*  but WITHOUT ANY WARRANTY; without even the implied warranty of           */
  927. X/*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            */
  928. X/*  GNU General Public License for more details.                             */
  929. X/*                                                                           */
  930. X/*  You should have received a copy of the GNU General Public License        */
  931. X/*  along with this program; if not, write to the Free Software              */
  932. X/*  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.                */
  933. X/*                                                                           */
  934. X/*  FILE:         z19.c                                                      */
  935. X/*  MODULE:       Galley Attaching                                           */
  936. X/*  EXTERNS:      SearchGalley(), AttachGalley(), DetachGalley()             */
  937. X/*                                                                           */
  938. X/*****************************************************************************/
  939. X#include "externs"
  940. X
  941. X
  942. X/*****************************************************************************/
  943. X/*                                                                           */
  944. X/*  DetachGalley(hd)                                                         */
  945. X/*                                                                           */
  946. X/*  Detach galley hd from its target.                                        */
  947. X/*                                                                           */
  948. X/*****************************************************************************/
  949. X
  950. XDetachGalley(hd)
  951. XOBJECT hd;
  952. X{ OBJECT prnt, index;
  953. X  debug1(DGA, D, "DetachGalley( %s )", EchoObject(hd));
  954. X  assert( type(hd) == HEAD && Up(hd) != hd, "DetachGalley: precondition!" );
  955. X  Parent(prnt, Up(hd));
  956. X  assert( Up(prnt) != prnt, "DetachGalley: parent!" );
  957. X  index = New(UNATTACHED);
  958. X  MoveLink(Up(hd), index, PARENT);
  959. X  Link(NextDown(Up(prnt)), index);
  960. X  debug0(DGA, D, "DetachGalley returning.");
  961. X} /* end DetachGalley */
  962. X
  963. X
  964. X/*@::SearchGalley()@**********************************************************/
  965. X/*                                                                           */
  966. X/*  OBJECT SearchGalley(start, sym, forwards, subgalleys, closures, input)   */
  967. X/*                                                                           */
  968. X/*  Search a galley and its sub-galleys for a target which uses sym.  The    */
  969. X/*  meanings of the flags are as follows:                                    */
  970. X/*                                                                           */
  971. X/*    forwards     If TRUE, search forwards from just after start, else      */
  972. X/*                 search backwards from just before start                   */
  973. X/*    subgalleys   If TRUE, search down into sub-galleys of this galley      */
  974. X/*    closures     If TRUE, closures in this galley are acceptable results   */
  975. X/*    input        If TRUE, InputSym is an acceptable result                 */
  976. X/*                                                                           */
  977. X/*****************************************************************************/
  978. X
  979. XOBJECT SearchGalley(start, sym, forwards, subgalleys, closures, input)
  980. XOBJECT start, sym;  BOOLEAN forwards, subgalleys, closures, input;
  981. X{ OBJECT y, res, z, zlink, link;
  982. X  debug5(DGA, D, "[SearchGalley( start, %s, %s, %s, %s, %s )", SymName(sym),
  983. X    forwards ? "fwd" : "back", subgalleys ? "subgalleys" : "nosubgalleys",
  984. X    closures ? "closures" : "noclosures", input ? "input" : "noinput");
  985. X  assert( type(start) == LINK || type(start) == HEAD, "SearchGalley: start!" );
  986. X
  987. X  link = forwards ? NextDown(start) : PrevDown(start);
  988. X  res = nil;
  989. X  while( res == nil && type(link) != HEAD )
  990. X  { Child(y, link);
  991. X    debug1(DGA, DD, "  examining %s", EchoObject(y));
  992. X    switch( type(y) )
  993. X    {
  994. X      case UNATTACHED:
  995. X      case RECEIVING:
  996. X    
  997. X    if( subgalleys )
  998. X    for( zlink = Down(y); zlink!=y && res==nil;  zlink = NextDown(zlink) )
  999. X    { Child(z, zlink);
  1000. X      res = SearchGalley(z, sym, TRUE, TRUE, TRUE, input);
  1001. X    }
  1002. X    if( !res && input && type(y)==RECEIVING && actual(actual(y))==InputSym )
  1003. X      res = y;
  1004. X    break;
  1005. X
  1006. X
  1007. X      case RECEPTIVE:
  1008. X    
  1009. X    if( closures && type(actual(y)) == CLOSURE
  1010. X             && SearchUses(actual(actual(y)), sym) )  res = y;
  1011. X    else if( input && actual(actual(y)) == InputSym )  res = y;
  1012. X    break;
  1013. X
  1014. X
  1015. X      default:
  1016. X    
  1017. X    break;
  1018. X
  1019. X    }
  1020. X    link = forwards ? NextDown(link) : PrevDown(link);
  1021. X  }
  1022. X  debug1(DGA, D, "]SearchGalley returning %s", EchoObject(res));
  1023. X  return res;
  1024. X} /* end SearchGalley */
  1025. X
  1026. X
  1027. X/*@@**************************************************************************/
  1028. X/*                                                                           */
  1029. X/*  AttachGalley(hd, inners)                                                 */
  1030. X/*                                                                           */
  1031. X/*  Attach galley hd, which may be unsized, to a destination.  This involves */
  1032. X/*  searching for a destination forward or back from the attachment point of */
  1033. X/*  hd and promoting up to and including the first definite component of hd. */
  1034. X/*                                                                           */
  1035. X/*  Although AttachGalley never flushes any galleys, it may identify some    */
  1036. X/*  galleys which should be flushed, even if the attach is itself not        */
  1037. X/*  successful.  These are returned in *inners, or nil if none.              */
  1038. X/*                                                                           */
  1039. X/*****************************************************************************/
  1040. X
  1041. XAttachGalley(hd, inners)
  1042. XOBJECT hd, *inners;
  1043. X{ OBJECT index;            /* the index of hd in the enclosing galley   */
  1044. X  OBJECT hd_inners;        /* inner galleys of hd, if unsized           */
  1045. X  OBJECT dest;            /* the target @Galley hd empties into        */
  1046. X  OBJECT dest_index;        /* the index of dest                         */
  1047. X  OBJECT target;        /* the target indefinite containing dest     */
  1048. X  OBJECT target_index;        /* the index of target                       */
  1049. X  OBJECT target_galley;        /* the body of target, made into a galley    */
  1050. X  OBJECT tg_inners;        /* inner galleys of target_galley            */
  1051. X  BOOLEAN need_precedes;    /* true if destination lies before galley    */
  1052. X  OBJECT recs;            /* list of recursive definite objects        */
  1053. X  OBJECT link, y;        /* for scanning through the components of hd */
  1054. X  CONSTRAINT c;            /* temporary variable holding a constraint   */
  1055. X  OBJECT env, n1, tmp, zlink, z, sym;    /* placeholders and temporaries         */
  1056. X  BOOLEAN was_sized;        /* true if sized(hd) initially               */
  1057. X
  1058. X  debug2(DGA, D, "[AttachGalley(Galley %s into %s)",
  1059. X    SymName(actual(hd)), SymName(whereto(hd)));
  1060. X  ifdebug(DGA, DD, DebugObject(hd));
  1061. X  assert( Up(hd) != hd, "AttachGalley: no index!" );
  1062. X  Parent(index, Up(hd));
  1063. X  assert( type(index) == UNATTACHED, "AttachGalley: not UNATTACHED!" );
  1064. X  *inners = hd_inners = tg_inners = nil;
  1065. X  was_sized = sized(hd);
  1066. X
  1067. X  for(;;)
  1068. X  {
  1069. X    /*************************************************************************/
  1070. X    /*                                                                       */
  1071. X    /*  Search for a destination for hd.  If hd is unsized, search for       */
  1072. X    /*  inner galleys preceding it first of all, then for receptive objects  */
  1073. X    /*  following it, possibly in inner galleys.  If no luck, exit.          */
  1074. X    /*  If hd is sized, search only for receptive objects in the current     */
  1075. X    /*  galley below the current spot, and fail if cannot find any.          */
  1076. X    /*                                                                       */
  1077. X    /*************************************************************************/
  1078. X
  1079. X    sym = whereto(hd);
  1080. X    if( sized(hd) )
  1081. X    {
  1082. X      /* sized galley case: search on from current spot */
  1083. X      target_index = SearchGalley(Up(index), sym, TRUE, FALSE, TRUE, TRUE);
  1084. X      if( target_index == nil )
  1085. X      {    
  1086. X    /* search failed to find any new target, so kill the galley */
  1087. X    for( link = Down(hd); link != hd; link = NextDown(link) )
  1088. X    { Child(y, link);
  1089. X      if( type(y) == SPLIT )  Child(y, DownDim(y, ROW));
  1090. X      if( is_definite(type(y)) )  break;
  1091. X    }
  1092. X    if( link != hd )
  1093. X        Error(WARN, &fpos(y), "galley %s deleted from here: no target",
  1094. X        SymName(actual(hd)));
  1095. X    debug0(DGA, D, "calling KillGalley from AttachGalley (a)");
  1096. X    KillGalley(hd);
  1097. X    debug0(DGA, D, "]AttachGalley returning: no target for sized galley");
  1098. X    return;
  1099. X      }
  1100. X      else if( actual(actual(target_index)) == InputSym )
  1101. X      {
  1102. X    /* search found input object, so suspend on that */
  1103. X    DeleteNode(index);
  1104. X    Link(target_index, hd);
  1105. X    debug0(DGA, D, "]AttachGalley returning: InputSym");
  1106. X    return;
  1107. X      }
  1108. X
  1109. X    }
  1110. X    else /* unsized galley, either backwards or normal */
  1111. X    {
  1112. X      if( backward(hd) )
  1113. X      {    target_index= SearchGalley(Up(index), sym, FALSE, TRUE, TRUE, FALSE);
  1114. X    need_precedes = FALSE;
  1115. X      }
  1116. X      else
  1117. X      {    target_index = SearchGalley(Up(index), sym, FALSE, TRUE, FALSE, FALSE);
  1118. X    need_precedes = (target_index != nil);
  1119. X    if( target_index == nil )
  1120. X      target_index = SearchGalley(Up(index), sym, TRUE, TRUE, TRUE, FALSE);
  1121. X      }
  1122. X
  1123. X      /* if no luck, exit without error */
  1124. X      if( target_index == nil )
  1125. X      {    debug0(DGA, D, "]AttachGalley returning: no target for unsized galley");
  1126. X    return;
  1127. X      }
  1128. X    }
  1129. X    assert( type(target_index) == RECEPTIVE, "AttachGalley: target_index!" );
  1130. X    target = actual(target_index);
  1131. X    assert( type(target) == CLOSURE, "AttachGalley: target!" );
  1132. X
  1133. X    /* set target_galley to the expanded value of target */
  1134. X    EnterErrorBlock(FALSE);
  1135. X    target_galley = New(HEAD);
  1136. X    FposCopy(fpos(target_galley), fpos(target));
  1137. X    actual(target_galley) = actual(target);
  1138. X    whereto(target_galley) = ready_galls(target_galley) = nil;
  1139. X    backward(target_galley) = must_expand(target_galley) = FALSE;
  1140. X    sized(target_galley) = FALSE;
  1141. X    Constrained(target, &c, COL);
  1142. X    if( !constrained(c) )  Error(FATAL, &fpos(target),
  1143. X       "receptive symbol %s has unconstrained width", SymName(actual(target)));
  1144. X    debug2(DSC, D, "Constrained( %s, COL ) = %s",
  1145. X    EchoObject(target), EchoConstraint(&c));
  1146. X    debug1(DGA, DD, "  expanding %s", EchoObject(target));
  1147. X    tmp = CopyObject(target, no_fpos);
  1148. X    Link(target_galley, tmp);
  1149. X    if( !FitsConstraint(0, 0, c) )
  1150. X    { debug0(DGA, D, "  reject: target_galley horizontal constraint is -1");
  1151. X      goto REJECT;
  1152. X    }
  1153. X    env = DetachEnv(tmp);
  1154. X    SizeGalley(target_galley, env, external(target), threaded(target),
  1155. X    non_blocking(target_index), trigger_externs(target_index),
  1156. X    &save_style(target), &c, whereto(hd), &dest_index, &recs, &tg_inners);
  1157. X    if( recs != nil )  ExpandRecursives(recs);
  1158. X    dest = actual(dest_index);
  1159. X
  1160. X    /* verify that hd satisfies any horizontal constraint on dest */
  1161. X    debug1(DGA, DD, "  checking COL fit of hd in %s", SymName(actual(dest)));
  1162. X    Constrained(dest, &c, COL);
  1163. X    debug2(DSC, D, "Constrained( %s, COL ) = %s",
  1164. X    EchoObject(dest), EchoConstraint(&c));
  1165. X    assert( constrained(c), "AttachGalley: dest unconstrained!" );
  1166. X    if( !sized(hd) )
  1167. X    { EnterErrorBlock(TRUE);
  1168. X      if( !FitsConstraint(0, 0, c) )
  1169. X      {    debug0(DGA, D, "  reject: hd horizontal constraint is -1");
  1170. X    goto REJECT;
  1171. X      }
  1172. X      n1 = nil;
  1173. X      Child(y, Down(hd));
  1174. X      env = DetachEnv(y);
  1175. X      /*** to set non_blocking() to FALSE seems doubtful!
  1176. X      SizeGalley(hd, env, TRUE, threaded(dest), FALSE, TRUE,
  1177. X        &save_style(dest), &c, nil, &n1, &recs, &hd_inners);
  1178. X      *** */
  1179. X      SizeGalley(hd, env, TRUE, threaded(dest), non_blocking(target_index),
  1180. X    TRUE, &save_style(dest), &c, nil, &n1, &recs, &hd_inners);
  1181. X      if( recs != nil )  ExpandRecursives(recs);
  1182. X      if( need_precedes )        /* need an ordering constraint */
  1183. X      {    OBJECT index1 = New(PRECEDES);
  1184. X    OBJECT index2 = New(FOLLOWS);
  1185. X    blocked(index2) = FALSE;
  1186. X    tmp = MakeWord(WORD, STR_EMPTY, no_fpos);
  1187. X    Link(index1, tmp);  Link(index2, tmp);
  1188. X    Link(Up(index), index1);
  1189. X    Link(Down(hd), index2);
  1190. X    debug0(DGA, D, "  inserting PRECEDES and FOLLOWS");
  1191. X      }
  1192. X      LeaveErrorBlock(TRUE);
  1193. X    }
  1194. X    if( !FitsConstraint(back(hd, COL), fwd(hd, COL), c) )
  1195. X    { debug3(DGA, D, "  reject: hd %s,%s does not fit target_galley %s",
  1196. X    EchoLength(back(hd, COL)), EchoLength(fwd(hd, COL)),
  1197. X    EchoConstraint(&c));
  1198. X      Error(WARN, &fpos(hd),"too little horizontal space for galley %s at %s",
  1199. X    SymName(actual(hd)), SymName(actual(dest)));
  1200. X      goto REJECT;
  1201. X    }
  1202. X
  1203. X    /* check status of first component of hd */
  1204. X    debug0(DGA, DD, "  now ready to attach; hd =");
  1205. X    ifdebug(DGA, DD, DebugObject(hd));
  1206. X    for( link = Down(hd);  link != hd;  link = NextDown(link) )
  1207. X    {
  1208. X      Child(y, link);
  1209. X      debug1(DGA, DD, "  examining %s", EchoObject(y));
  1210. X      if( type(y) == SPLIT )  Child(y, DownDim(y, ROW));
  1211. X      switch( type(y) )
  1212. X      {
  1213. X
  1214. X    case EXPAND_IND:
  1215. X    case GALL_PREC:
  1216. X    case GALL_FOLL:
  1217. X    case GALL_TARG:
  1218. X    case CROSS_PREC:
  1219. X    case CROSS_FOLL:
  1220. X    case CROSS_TARG:
  1221. X        
  1222. X      break;
  1223. X
  1224. X
  1225. X    case PRECEDES:
  1226. X    case UNATTACHED:
  1227. X        
  1228. X      if( was_sized )
  1229. X      { /* SizeGalley was not called, so hd_inners was not set by it */
  1230. X        if( hd_inners == nil )  hd_inners = New(ACAT);
  1231. X        Link(hd_inners, y);
  1232. X      }
  1233. X      break;
  1234. X
  1235. X
  1236. X    case RECEPTIVE:
  1237. X
  1238. X      if( non_blocking(y) )
  1239. X      { link = PrevDown(link);
  1240. X        DeleteNode(y);
  1241. X      }
  1242. X      else goto SUSPEND;
  1243. X      break;
  1244. X
  1245. X
  1246. X    case RECEIVING:
  1247. X        
  1248. X      if( non_blocking(y) )
  1249. X      { while( Down(y) != y )
  1250. X        { Child(z, Down(y));
  1251. X          DetachGalley(z);
  1252. X          KillGalley(z);
  1253. X        }
  1254. X        link = PrevDown(link);
  1255. X        DeleteNode(y);
  1256. X      }
  1257. X      else goto SUSPEND;
  1258. X      break;
  1259. X
  1260. X
  1261. X    case FOLLOWS:
  1262. X        
  1263. X      Child(tmp, Down(y));
  1264. X      if( Up(tmp) == LastUp(tmp) )
  1265. X      { link = pred(link, CHILD);
  1266. X        debug0(DGA, DD, "  disposing FOLLOWS");
  1267. X        DisposeChild(NextDown(link));
  1268. X        break;
  1269. X      }
  1270. X      Parent(tmp, Up(tmp));
  1271. X      assert(type(tmp) == PRECEDES, "Attach: PRECEDES!");
  1272. X      switch( CheckConstraint(tmp, target_index) )
  1273. X      {
  1274. X        case CLEAR:        DeleteNode(tmp);
  1275. X                link = pred(link, CHILD);
  1276. X                DisposeChild(NextDown(link));
  1277. X                break;
  1278. X
  1279. X        case PROMOTE:    break;
  1280. X
  1281. X        case BLOCK:        debug0(DGA, DD, "CheckContraint: BLOCK");
  1282. X                goto SUSPEND;
  1283. X
  1284. X        case CLOSE:        debug0(DGA, D, "  reject: CheckContraint");
  1285. X                goto REJECT;
  1286. X      }
  1287. X      break;
  1288. X
  1289. X
  1290. X    case GAP_OBJ:
  1291. X
  1292. X      if( !join(gap(y)) )  seen_nojoin(hd) = TRUE;
  1293. X      break;
  1294. X
  1295. X
  1296. X    case CLOSURE:
  1297. X    case NULL_CLOS:
  1298. X    case CROSS:
  1299. X
  1300. X      break;
  1301. X
  1302. X
  1303. X    case WORD:
  1304. X    case QWORD:
  1305. X    case ONE_COL:
  1306. X    case ONE_ROW:
  1307. X    case WIDE:
  1308. X    case HIGH:
  1309. X    case HSCALE:
  1310. X    case VSCALE:
  1311. X    case HCONTRACT:
  1312. X    case VCONTRACT:
  1313. X    case HEXPAND:
  1314. X    case VEXPAND:
  1315. X    case PADJUST:
  1316. X    case HADJUST:
  1317. X    case VADJUST:
  1318. X    case ROTATE:
  1319. X    case SCALE:
  1320. X    case INCGRAPHIC:
  1321. X    case SINCGRAPHIC:
  1322. X    case GRAPHIC:
  1323. X    case ACAT:
  1324. X    case HCAT:
  1325. X    case ROW_THR:
  1326. X        
  1327. X      /* make sure y is not joined to a target below */
  1328. X      for( zlink = NextDown(link);  zlink != hd;  zlink = NextDown(zlink) )
  1329. X      { Child(z, zlink);
  1330. X        switch( type(z) )
  1331. X        {
  1332. X          case RECEPTIVE:    if( non_blocking(z) )
  1333. X                { zlink = PrevDown(zlink);
  1334. X                  DeleteNode(z);
  1335. X                }
  1336. X                else
  1337. X                { y = z;
  1338. X                  goto SUSPEND;
  1339. X                }
  1340. X                break;
  1341. X
  1342. X          case RECEIVING:    if( non_blocking(z) )
  1343. X                { zlink = PrevDown(zlink);
  1344. X                  while( Down(z) != z )
  1345. X                  { Child(tmp, Down(y));
  1346. X                    DetachGalley(tmp);
  1347. X                    KillGalley(tmp);
  1348. X                  }
  1349. X                  DeleteNode(z);
  1350. X                }
  1351. X                else
  1352. X                { y = z;
  1353. X                  goto SUSPEND;
  1354. X                }
  1355. X                break;
  1356. X
  1357. X          case GAP_OBJ:    if( !join(gap(z)) )  zlink = PrevDown(hd);
  1358. X                break;
  1359. X
  1360. X          default:        break;
  1361. X        }
  1362. X      }
  1363. X
  1364. X      /* check availability of vertical space for the first component */
  1365. X      if( !external(dest) )
  1366. X      { Constrained(dest, &c, ROW);
  1367. X        debug2(DSC, D, "Constrained( %s, ROW ) = %s",
  1368. X          EchoObject(dest), EchoConstraint(&c));
  1369. X        if( !FitsConstraint(back(y, ROW), fwd(y, ROW), c) )
  1370. X        { Error(WARN, &fpos(y),
  1371. X        "this component of %s did not fit into its nearest target",
  1372. X        SymName(actual(hd)));
  1373. X          debug3(DGA, D, "  reject: vsize %s,%s in %s; y=",
  1374. X        EchoLength(back(y, ROW)), EchoLength(fwd(y, ROW)),
  1375. X        EchoConstraint(&c));
  1376. X          ifdebug(DGA, D, DebugObject(y));
  1377. X          goto REJECT;
  1378. X        }
  1379. X        debug0(DSA, D, "calling AdjustSize from AttachGalley (a)");
  1380. X        AdjustSize(dest, back(y, ROW), fwd(y, ROW), ROW);
  1381. X      }
  1382. X      if( !external(target) )
  1383. X      { Constrained(target, &c, ROW);
  1384. X        debug2(DSC, D, "Constrained( %s, ROW ) = %s",
  1385. X            EchoObject(target), EchoConstraint(&c));
  1386. X        Child(z, LastDown(target_galley));
  1387. X        assert( !is_index(type(z)), "AttachGalley: is_index(z)!" );
  1388. X        assert( back(z, ROW) >= 0 && fwd(z, ROW) >= 0,
  1389. X            "AttachGalley: negative z sizes!" );
  1390. X        if( !FitsConstraint(back(z, ROW), fwd(z, ROW), c) )
  1391. X        { Error(WARN, &fpos(y),
  1392. X        "this component of %s did not fit into its nearest target",
  1393. X        SymName(actual(hd)));
  1394. X          debug3(DGA, D, "  reject: size was %s,%s in %s; y =",
  1395. X        EchoLength(back(z, ROW)), EchoLength(fwd(z, ROW)),
  1396. X        EchoConstraint(&c));
  1397. X          ifdebug(DGA, D, DebugObject(y));
  1398. X          goto REJECT;
  1399. X        }
  1400. X        debug0(DSA, D, "calling AdjustSize from AttachGalley (b)");
  1401. X        AdjustSize(target, back(z, ROW), fwd(z, ROW), ROW);
  1402. X      }
  1403. X      goto ACCEPT;
  1404. X
  1405. X
  1406. X    default:
  1407. X        
  1408. X      Error(INTERN, &fpos(y), "AttachGalley: %s", Image(type(y)));
  1409. X      break;
  1410. X
  1411. X      } /* end switch */
  1412. X    } /* end for */
  1413. X
  1414. X    /* empty galley; promote any indexes, kill the galley, and exit */
  1415. X    /* this bypasses target_galley, which is not expanded in the empty case */
  1416. X    debug0(DGA, D, "  empty galley");
  1417. X    if( tg_inners != nil )  DisposeObject(tg_inners), tg_inners = nil;
  1418. X    DisposeObject(target_galley);
  1419. X    LeaveErrorBlock(FALSE);
  1420. X    if( LastDown(hd) != hd )  Promote(hd, hd, target_index);
  1421. X    debug0(DGA, D, "calling KillGalley from AttachGalley (b)");
  1422. X    KillGalley(hd);
  1423. X
  1424. X    /* return; only hd_inners needs to be flushed now */
  1425. X    *inners = hd_inners;
  1426. X    debug0(DGA, D, "]AttachGalley returning killed: empty galley");
  1427. X    return;
  1428. X
  1429. X
  1430. X    REJECT:
  1431. X    
  1432. X      /* reject first component */
  1433. X      LeaveErrorBlock(TRUE);
  1434. X      if( tg_inners != nil )  DisposeObject(tg_inners), tg_inners = nil;
  1435. X      DisposeObject(target_galley);
  1436. X      if( backward(hd) && !sized(hd) )
  1437. X      {
  1438. X    /* move to just before the failed target */
  1439. X    MoveLink(Up(index), Up(target_index), PARENT);
  1440. X      }
  1441. X      else
  1442. X      {
  1443. X    /* move to just after the failed target */
  1444. X    MoveLink(Up(index), NextDown(Up(target_index)), PARENT);
  1445. X      }
  1446. X      continue;
  1447. X
  1448. X
  1449. X    SUSPEND:
  1450. X    
  1451. X      /* suspend at first component */
  1452. X      debug1(DGA, D, "  suspend %s", EchoObject(y));
  1453. X      blocked(y) = TRUE;
  1454. X      LeaveErrorBlock(FALSE);
  1455. X      if( tg_inners != nil )  DisposeObject(tg_inners), tg_inners = nil;
  1456. X      DisposeObject(target_galley);
  1457. X      MoveLink(Up(index), Up(target_index), PARENT);
  1458. X      if( was_sized )
  1459. X      { /* nothing new to flush if suspending and already sized */
  1460. X    if( hd_inners != nil )  DisposeObject(hd_inners), hd_inners = nil;
  1461. X      }
  1462. X      else
  1463. X      { /* flush newly discovered inners if not sized before */
  1464. X    *inners = hd_inners;
  1465. X      }
  1466. X      debug0(DGA, D, "]AttachGalley returning: suspending.");
  1467. X      return;
  1468. X
  1469. X
  1470. X    ACCEPT:
  1471. X    
  1472. X      /* accept first component; now committed to the attach */
  1473. X      debug1(DGA, D, "  accept %s", EchoObject(y));
  1474. X      LeaveErrorBlock(TRUE);
  1475. X
  1476. X      /* adjust horizontal sizes */
  1477. X      debug0(DSA, D, "calling AdjustSize from AttachGalley (c)");
  1478. X      AdjustSize(dest, back(hd, COL), fwd(hd, COL), COL);
  1479. X      debug0(DSA, D, "calling AdjustSize from AttachGalley (d)");
  1480. X      AdjustSize(target, back(target_galley, COL),
  1481. X                fwd(target_galley, COL), COL);
  1482. X        
  1483. X      /* attach hd to dest */
  1484. X      MoveLink(Up(hd), dest_index, PARENT);
  1485. X      assert( type(index) == UNATTACHED, "AttachGalley: type(index)!" );
  1486. X      DeleteNode(index);
  1487. X
  1488. X      /* move first component of hd into dest */
  1489. X      /* nb Interpose must be done after all AdjustSize calls */
  1490. X      if( !external(dest) )   Interpose(dest, VCAT, hd, y);
  1491. X      Promote(hd, NextDown(link), dest_index);
  1492. X
  1493. X      /* move target_galley into target */
  1494. X      /* nb Interpose must be done after all AdjustSize calls */
  1495. X      if( !external(target) )
  1496. X      {    Child(z, LastDown(target_galley));
  1497. X    Interpose(target, VCAT, z, z);
  1498. X      }
  1499. X      Promote(target_galley, target_galley, target_index);
  1500. X      DeleteNode(target_galley);
  1501. X      assert(Down(target_index)==target_index, "AttachGalley: target_ind");
  1502. X      if( blocked(target_index) )  blocked(dest_index) = TRUE;
  1503. X      DeleteNode(target_index);
  1504. X
  1505. X      /* return; both tg_inners and hd_inners need to be flushed now;        */
  1506. X      /* if was_sized, hd_inners contains the inners of the first component; */
  1507. X      /* otherwise it contains the inners of all components, from SizeGalley */
  1508. X      if( tg_inners == nil ) *inners = hd_inners;
  1509. X      else if( hd_inners == nil ) *inners = tg_inners;
  1510. X      else
  1511. X      {    TransferLinks(Down(hd_inners), hd_inners, tg_inners);
  1512. X    DeleteNode(hd_inners);
  1513. X    *inners = tg_inners;
  1514. X      }
  1515. X      debug0(DGA, D, "]AttachGalley returning (accept)");
  1516. X      return;
  1517. X
  1518. X  } /* end for */
  1519. X} /* end AttachGalley */
  1520. END_OF_FILE
  1521.   if test 22103 -ne `wc -c <'z19.c'`; then
  1522.     echo shar: \"'z19.c'\" unpacked with wrong size!
  1523.   fi
  1524.   # end of 'z19.c'
  1525. fi
  1526. if test -f 'z25.c' -a "${1}" != "-c" ; then 
  1527.   echo shar: Will not clobber existing file \"'z25.c'\"
  1528. else
  1529.   echo shar: Extracting \"'z25.c'\" \(21404 characters\)
  1530.   sed "s/^X//" >'z25.c' <<'END_OF_FILE'
  1531. X/*@z25.c:Object Echo:aprint(), cprint(), printnum()@**************************/
  1532. X/*                                                                           */
  1533. X/*  LOUT: A HIGH-LEVEL LANGUAGE FOR DOCUMENT FORMATTING (VERSION 2.05)       */
  1534. X/*  COPYRIGHT (C) 1993 Jeffrey H. Kingston                                   */
  1535. X/*                                                                           */
  1536. X/*  Jeffrey H. Kingston (jeff@cs.su.oz.au)                                   */
  1537. X/*  Basser Department of Computer Science                                    */
  1538. X/*  The University of Sydney 2006                                            */
  1539. X/*  AUSTRALIA                                                                */
  1540. X/*                                                                           */
  1541. X/*  This program is free software; you can redistribute it and/or modify     */
  1542. X/*  it under the terms of the GNU General Public License as published by     */
  1543. X/*  the Free Software Foundation; either version 1, or (at your option)      */
  1544. X/*  any later version.                                                       */
  1545. X/*                                                                           */
  1546. X/*  This program is distributed in the hope that it will be useful,          */
  1547. X/*  but WITHOUT ANY WARRANTY; without even the implied warranty of           */
  1548. X/*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            */
  1549. X/*  GNU General Public License for more details.                             */
  1550. X/*                                                                           */
  1551. X/*  You should have received a copy of the GNU General Public License        */
  1552. X/*  along with this program; if not, write to the Free Software              */
  1553. X/*  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.                */
  1554. X/*                                                                           */
  1555. X/*  FILE:         z25.c                                                      */
  1556. X/*  MODULE:       Object Echo                                                */
  1557. X/*  EXTERNS:      EchoObject(), PrintObject()                                */
  1558. X/*                                                                           */
  1559. X/*****************************************************************************/
  1560. X#include "externs"
  1561. X#if DEBUG_ON
  1562. X
  1563. Xstatic    int    limit;            /* column where newline is needed    */
  1564. Xstatic    int    indent;            /* current indent                    */
  1565. Xstatic    int    col;            /* current output column             */
  1566. Xstatic    FILE    *fp;            /* current output file               */
  1567. X
  1568. X#define    moveright()    (indent += 3)
  1569. X#define    moveleft()    (indent -= 3)
  1570. X
  1571. X
  1572. X/*****************************************************************************/
  1573. X/*                                                                           */
  1574. X/*  static aprint(x)                                                         */
  1575. X/*  static cprint(x)                                                         */
  1576. X/*                                                                           */
  1577. X/*  Print the ASCII or FULL_CHAR string x onto the appropriate output.       */
  1578. X/*                                                                           */
  1579. X/*****************************************************************************/
  1580. X
  1581. Xstatic cprint(x)
  1582. XFULL_CHAR *x;
  1583. X{ col += StringLength(x);
  1584. X  if( fp == null ) AppendString(x);
  1585. X  else StringFPuts(x, fp);
  1586. X} /* end print */
  1587. X
  1588. Xstatic aprint(x)
  1589. Xchar *x;
  1590. X{ cprint(AsciiToFull(x));
  1591. X} /* end aprint */
  1592. X
  1593. X
  1594. X/*****************************************************************************/
  1595. X/*                                                                           */
  1596. X/*  static printnum(x)                                                       */
  1597. X/*                                                                           */
  1598. X/*  Print the number x onto the appropriate output.                          */
  1599. X/*                                                                           */
  1600. X/*****************************************************************************/
  1601. X
  1602. Xstatic printnum(x)
  1603. Xint x;
  1604. X{ cprint(StringInt(x));
  1605. X} /* end printnum */
  1606. X
  1607. X
  1608. X/*@::tab(), newline(), space()@***********************************************/
  1609. X/*                                                                           */
  1610. X/*  static tab(x)                                                            */
  1611. X/*                                                                           */
  1612. X/*  Tab to column x, or anyway insert at least one space.                    */
  1613. X/*                                                                           */
  1614. X/*****************************************************************************/
  1615. X
  1616. Xstatic tab(x)
  1617. Xint x;
  1618. X{  do
  1619. X     aprint(" ");
  1620. X   while( col < x );
  1621. X} /* end tab */
  1622. X
  1623. X
  1624. X/*****************************************************************************/
  1625. X/*                                                                           */
  1626. X/*  static newline()                                                         */
  1627. X/*                                                                           */
  1628. X/*  Echo a newline to the appropriate output (unless output is a string).    */
  1629. X/*  Correct indenting and right limits are maintained, if possible.          */
  1630. X/*                                                                           */
  1631. X/*****************************************************************************/
  1632. X
  1633. Xstatic newline()
  1634. X{ if( fp == null )  AppendString(STR_SPACE);
  1635. X  else
  1636. X  { fputs("\n", fp);
  1637. X    fflush(fp);
  1638. X    for( col = 0;  col < indent;  col++ )  fputs(" ", fp);
  1639. X  }
  1640. X} /* end newline */
  1641. X
  1642. X
  1643. X/*****************************************************************************/
  1644. X/*                                                                           */
  1645. X/*  static space(n)                                                          */
  1646. X/*                                                                           */
  1647. X/*  Echo n spaces to the appropriate output.                                 */
  1648. X/*  Correct indenting and right limits are maintained, if possible.          */
  1649. X/*                                                                           */
  1650. X/*****************************************************************************/
  1651. X
  1652. Xstatic space(n)
  1653. Xint n;
  1654. X{ int i;
  1655. X  if( fp == null )
  1656. X    for( i = 0;  i < n;  i++ )  AppendString(STR_SPACE);
  1657. X  else if( col + n > limit )
  1658. X  { fputs("\n", fp);
  1659. X    for( col = 0;  col < n-1;  col++ )  fputs(" ", fp);
  1660. X  }
  1661. X  else for( i = 0;  i < n;  col++, i++ )  fputs(" ", fp);
  1662. X} /* end space */
  1663. X
  1664. X
  1665. X/*@::echo()@******************************************************************/
  1666. X/*                                                                           */
  1667. X/*  static echo(x, outer_prec)                                               */
  1668. X/*                                                                           */
  1669. X/*  Echo x.  The result will be enclosed in braces only if its precedence    */
  1670. X/*  is less than or equal to outer_prec (words and parameterless closures    */
  1671. X/*  are taken to have infinite precedence, i.e. never enclosed in braces).   */
  1672. X/*                                                                           */
  1673. X/*****************************************************************************/
  1674. X
  1675. Xstatic echo(x, outer_prec)
  1676. XOBJECT x;  unsigned outer_prec;
  1677. X{ OBJECT link, y, tmp, sym;
  1678. X  char *op;  int prec, i;
  1679. X  BOOLEAN npar_seen, name_printed, lbr_printed, braces_needed;
  1680. X
  1681. X  switch( type(x) )
  1682. X  {
  1683. X
  1684. X    case DEAD:
  1685. X
  1686. X    aprint("#dead");
  1687. X    break;
  1688. X
  1689. X    case UNATTACHED:
  1690. X    
  1691. X    aprint( "#unattached " );
  1692. X    moveright();
  1693. X    if( Down(x) != x )
  1694. X    { Child(y, Down(x));
  1695. X      if( y != x ) echo(y, NO_PREC);
  1696. X      else aprint("<child is self!>");
  1697. X    }
  1698. X    else aprint("<no child!>");
  1699. X    moveleft();
  1700. X    break;
  1701. X
  1702. X
  1703. X    case EXPAND_IND:
  1704. X    case GALL_PREC:
  1705. X    case GALL_FOLL:
  1706. X    case GALL_TARG:
  1707. X    case CROSS_PREC:
  1708. X    case CROSS_FOLL:
  1709. X    case CROSS_TARG:
  1710. X    case RECURSIVE:
  1711. X    
  1712. X    aprint("#"); cprint(Image(type(x))); aprint(" ");
  1713. X    echo(actual(x), NO_PREC);
  1714. X    break;
  1715. X
  1716. X        
  1717. X    case RECEPTIVE:
  1718. X    case RECEIVING:
  1719. X    
  1720. X    aprint(type(x) == RECEIVING ? "#receiving " : "#receptive ");
  1721. X    if( external(actual(x)) )  aprint("(external) ");
  1722. X    if( threaded(actual(x)) )  aprint("(threaded) ");
  1723. X    if( blocked(x) )           aprint("(blocked) " );
  1724. X    if( trigger_externs(x) )   aprint("(trigger_externs) " );
  1725. X    if( non_blocking(x) )      aprint("(non_blocking) " );
  1726. X    cprint( type(actual(x)) == CLOSURE ?
  1727. X        SymName(actual(actual(x))) : Image(type(actual(x))) );
  1728. X    aprint(" ");
  1729. X    for( link = Down(x);  link != x;  link = NextDown(link) )
  1730. X    { Child(y, link);
  1731. X      moveright();
  1732. X      echo(y, NO_PREC);
  1733. X      moveleft();
  1734. X    }
  1735. X    break;
  1736. X
  1737. X
  1738. X    case PRECEDES:
  1739. X    
  1740. X    aprint("#precedes");
  1741. X    break;
  1742. X
  1743. X
  1744. X    case FOLLOWS:
  1745. X    
  1746. X    aprint("#follows");
  1747. X    if( blocked(x) )  aprint(" (blocked)");
  1748. X    Child(y, Down(x));
  1749. X    if( Up(y) == LastUp(y) )  aprint(" (no precedes!)");
  1750. X    break;
  1751. X
  1752. X
  1753. X    case HEAD:
  1754. X    
  1755. X    aprint("Galley ");  cprint(SymName(actual(x)));
  1756. X    aprint(" into ");   cprint(SymName(whereto(x)));
  1757. X    for( link = Down(x);  link != x;  link = NextDown(link) )
  1758. X    { Child(y, link);
  1759. X      newline();
  1760. X      echo(y, type(y) == GAP_OBJ ? VCAT : VCAT_PREC);
  1761. X    }
  1762. X    break;
  1763. X
  1764. X
  1765. X    case ROW_THR:
  1766. X
  1767. X    aprint("{R ");
  1768. X    for( link = Down(x);  link != x;  link = NextDown(link) )
  1769. X    { Child(y, link);
  1770. X      echo(y, VCAT_PREC);
  1771. X      newline();
  1772. X      if( NextDown(link) != x )  aprint("/R ");
  1773. X    }
  1774. X    aprint("R}");
  1775. X    break;
  1776. X
  1777. X
  1778. X    case COL_THR:
  1779. X
  1780. X    aprint("{C ");
  1781. X    for( link = Down(x);  link != x;  link = NextDown(link) )
  1782. X    { Child(y, link);
  1783. X      echo(y, HCAT_PREC);
  1784. X      newline();
  1785. X      if( NextDown(link) != x )  aprint("|C ");
  1786. X    }
  1787. X    aprint("C}");
  1788. X    break;
  1789. X
  1790. X
  1791. X    case VCAT: op = "/", prec = VCAT_PREC;  goto ETC;
  1792. X    case HCAT: op = "|", prec = HCAT_PREC;  goto ETC;
  1793. X    case ACAT: op = "&", prec = ACAT_PREC;  goto ETC;
  1794. X    
  1795. X    ETC:
  1796. X    if( Down(x) == x )
  1797. X    { aprint(op);
  1798. X      aprint("<empty>");
  1799. X      break;
  1800. X    }
  1801. X    if( prec <= outer_prec ) aprint("{ ");
  1802. X    /* *** if( Down(x) == LastDown(x) )  aprint(op);  must be manifested */
  1803. X    for( link = Down(x);  link != x;  link = NextDown(link) )
  1804. X    { Child(y, link);
  1805. X      if( is_index(type(y)) )
  1806. X        newline();
  1807. X      else if( (type(y) == GAP_OBJ && type(x) != ACAT) )
  1808. X        newline();
  1809. X      if( type(y) == GAP_OBJ )  echo(y, type(x));
  1810. X      else echo(y, prec);
  1811. X    }
  1812. X    if( prec <= outer_prec )  aprint(" }");
  1813. X    break;
  1814. X
  1815. X
  1816. X    case GAP_OBJ:
  1817. X
  1818. X    /* in this case the outer_prec argument is VCAT, HCAT or ACAT */
  1819. X    if( Down(x) != x )
  1820. X    { if( outer_prec == ACAT )  aprint(" ");
  1821. X      cprint( EchoCatOp(outer_prec, mark(gap(x)), join(gap(x))) );
  1822. X      Child(y, Down(x));
  1823. X      echo(y, FORCE_PREC);
  1824. X      aprint(" ");
  1825. X    }
  1826. X    else if( outer_prec == ACAT )
  1827. X    { for( i = 1;  i <= vspace(x);  i++ )  newline();
  1828. X      for( i = 1;  i <= hspace(x);  i++ )  aprint(" ");
  1829. X    }
  1830. X    else
  1831. X    { cprint( EchoCatOp(outer_prec, mark(gap(x)), join(gap(x))) );
  1832. X      cprint( EchoGap(&gap(x)) );
  1833. X      aprint(" ");
  1834. X    }
  1835. X    break;
  1836. X
  1837. X
  1838. X    case WORD:
  1839. X    
  1840. X    if( StringLength(string(x)) == 0 )
  1841. X      aprint("{}");
  1842. X    else cprint( string(x) );
  1843. X    break;
  1844. X
  1845. X
  1846. X    case QWORD:
  1847. X    
  1848. X    cprint( StringQuotedWord(x) );
  1849. X    break;
  1850. X
  1851. X
  1852. X    case ENV:
  1853. X    
  1854. X    /* debug only */
  1855. X    aprint("<");
  1856. X    for( link = Down(x);  link != x;  link = NextDown(link) )
  1857. X    { Child(y, link);
  1858. X      if( type(y) == CLOSURE )
  1859. X      { cprint( SymName(actual(y)) );
  1860. X        echo(GetEnv(y), NO_PREC);
  1861. X      }
  1862. X      else if( type(y) == ENV )  echo(y, NO_PREC);
  1863. X      else cprint(Image(type(y)));
  1864. X      if( NextDown(link) != x )  aprint(" ");
  1865. X    }
  1866. X    aprint(">");
  1867. X    break;
  1868. X
  1869. X
  1870. X    case CROSS:
  1871. X
  1872. X    assert( Down(x) != x, "echo: CROSS Down(x)!" );
  1873. X    Child(y, Down(x));
  1874. X    if( type(y) == CLOSURE )  cprint(SymName(actual(y)));
  1875. X    else
  1876. X    { cprint(KW_LBR);
  1877. X      echo(y, NO_PREC);
  1878. X      cprint(KW_RBR);
  1879. X    }
  1880. X    cprint(KW_CROSS);
  1881. X    if( NextDown(Down(x)) != x )
  1882. X    { Child(y, NextDown(Down(x)));
  1883. X      echo(y, NO_PREC);
  1884. X    }
  1885. X    else aprint("??");
  1886. X    break;
  1887. X
  1888. X
  1889. X    case CLOSURE:
  1890. X    
  1891. X    sym = actual(x);
  1892. X    braces_needed =
  1893. X        precedence(sym) <= outer_prec && (has_lpar(sym) || has_rpar(sym));
  1894. X
  1895. X    /* print brace if needed */
  1896. X    if( braces_needed )  aprint("{ ");
  1897. X
  1898. X    npar_seen = FALSE;  name_printed = FALSE;
  1899. X    for( link = Down(x); link != x;  link = NextDown(link) )
  1900. X    { Child(y, link);
  1901. X      if( type(y) == PAR )
  1902. X      { assert( Down(y) != y, "EchoObject: Down(PAR)!" );
  1903. X        switch( type(actual(y)) )
  1904. X        {
  1905. X         case LPAR:    Child(tmp, Down(y));
  1906. X            echo(tmp, (unsigned) precedence(sym));
  1907. X            aprint(" ");
  1908. X            break;
  1909. X
  1910. X         case NPAR:    if( !name_printed )
  1911. X            { cprint(SymName(sym));
  1912. X              if( external(x) || threaded(x) )
  1913. X              { aprint(" #");
  1914. X                if( external(x) )  aprint(" external");
  1915. X                if( threaded(x) )  aprint(" threaded");
  1916. X                newline();
  1917. X              }
  1918. X              name_printed = TRUE;
  1919. X            }
  1920. X            newline();  aprint("  ");
  1921. X            cprint( SymName(actual(y)) );
  1922. X            aprint(" { ");
  1923. X            Child(tmp, Down(y));
  1924. X            echo(tmp, NO_PREC);
  1925. X            aprint(" }");
  1926. X            npar_seen = TRUE;
  1927. X            break;
  1928. X
  1929. X         case RPAR:    if( !name_printed )
  1930. X            { cprint(SymName(sym));
  1931. X              if( external(x) || threaded(x) )
  1932. X              { aprint(" #");
  1933. X                if( external(x) )  aprint(" external");
  1934. X                if( threaded(x) )  aprint(" threaded");
  1935. X                newline();
  1936. X              }
  1937. X              name_printed = TRUE;
  1938. X            }
  1939. X            if( npar_seen ) newline();
  1940. X            else aprint(" ");
  1941. X            Child(tmp, Down(y));
  1942. X            if( has_body(sym) )
  1943. X            { aprint("{ ");
  1944. X              echo(tmp, NO_PREC);
  1945. X              aprint(" }");
  1946. X            }
  1947. X            else echo(tmp, (unsigned) precedence(sym));
  1948. X            break;
  1949. X    
  1950. X         default:    Error(INTERN, &fpos(y), "echo: %s",
  1951. X                    Image(type(actual(y))) );
  1952. X            break;
  1953. X
  1954. X        }
  1955. X      }
  1956. X    }
  1957. X    if( !name_printed )
  1958. X    { cprint( SymName(sym) );
  1959. X      if( external(x) || threaded(x) )
  1960. X      { aprint(" #");
  1961. X        if( external(x) )  aprint(" external");
  1962. X        if( threaded(x) )  aprint(" threaded");
  1963. X        newline();
  1964. X      }
  1965. X    }
  1966. X
  1967. X    /* print closing brace if needed */
  1968. X    if( braces_needed ) aprint(" }");
  1969. X    break;
  1970. X
  1971. X
  1972. X    case SPLIT:
  1973. X    
  1974. X    /* this should occur only in debug output case */
  1975. X    cprint(KW_SPLIT);  moveright();
  1976. X    Child(y, DownDim(x, COL));
  1977. X    aprint(" ");
  1978. X    echo(y, FORCE_PREC);
  1979. X    moveleft();
  1980. X    break;
  1981. X
  1982. X
  1983. X    case PAR:
  1984. X    
  1985. X    /* this should occur only in debug output case */
  1986. X    aprint("par ");  cprint(SymName(actual(x)));
  1987. X    break;
  1988. X
  1989. X
  1990. X    case CR_LIST:
  1991. X
  1992. X    aprint("(");
  1993. X    for( link = Down(x);  link != x;  link = NextDown(link) )
  1994. X    { Child(y, link);
  1995. X      echo(y, NO_PREC);
  1996. X      if( NextDown(link) != x )  aprint(", ");
  1997. X    }
  1998. X    aprint(")");
  1999. X    break;
  2000. X
  2001. X
  2002. X    case MACRO:
  2003. X    
  2004. X    newline();  cprint(KW_MACRO);
  2005. X    aprint(" ");  cprint(SymName(x));
  2006. X    if( sym_body(x) != nil )
  2007. X    { newline();  cprint(KW_LBR);
  2008. X      y = sym_body(x);
  2009. X      do
  2010. X      { for( i = 1;  i <= vspace(y);  i++ )  newline();
  2011. X        for( i = 1;  i <= hspace(y);  i++ )  aprint(" ");
  2012. X        cprint(EchoToken(y));
  2013. X        y = succ(y, PARENT);
  2014. X      } while( y != sym_body(x) );
  2015. X      newline();  aprint(KW_RBR);
  2016. X    }
  2017. X    else aprint(" {}");
  2018. X    if( visible(x) )  aprint(" # (visible)");
  2019. X    break;
  2020. X
  2021. X
  2022. X    case NPAR:
  2023. X    case LOCAL:
  2024. X    
  2025. X    /* print predefined operators in abbreviated form */
  2026. X    if( sym_body(x) == nil && enclosing(x) != nil )
  2027. X    { tab(3); aprint("# sys ");
  2028. X      cprint(SymName(x));
  2029. X      break;
  2030. X    }
  2031. X
  2032. X    /* print def line and miscellaneous debug info */
  2033. X    if( type(x) == LOCAL ) newline();
  2034. X    cprint(type(x) == NPAR ? KW_NAMED : KW_DEF);
  2035. X    aprint(" ");  cprint( SymName(x) );
  2036. X    if( recursive(x) || indefinite(x) || visible(x) ||
  2037. X        is_extern_target(x) || uses_extern_target(x) || uses_galley(x) )
  2038. X    { tab(25);  aprint("#");
  2039. X      if( visible(x)  )  aprint(" visible");
  2040. X      if( recursive(x)  )  aprint(" recursive");
  2041. X      if( indefinite(x) )  aprint(" indefinite");
  2042. X      if( is_extern_target(x) )  aprint(" is_extern_target");
  2043. X      if( uses_extern_target(x) )  aprint(" uses_extern_target");
  2044. X      if( uses_galley(x) )  aprint(" uses_galley");
  2045. X    }
  2046. X
  2047. X    /* print uses list, if necessary */
  2048. X    if( uses(x) != nil || dirty(x) )
  2049. X    { newline();  aprint("   # ");
  2050. X      if( dirty(x) ) aprint("dirty, ");
  2051. X      aprint("uses");
  2052. X      if( uses(x) != nil )
  2053. X      { tmp = next(uses(x));
  2054. X        do
  2055. X        { aprint(" "), cprint( SymName(item(tmp)) );
  2056. X          tmp = next(tmp);
  2057. X        } while( tmp != next(uses(x)) );
  2058. X      }
  2059. X      /* ***
  2060. X      for( tmp = uses(x);  tmp != nil;  tmp = next(tmp) )
  2061. X      { aprint(" "), cprint( SymName(item(tmp)) );
  2062. X      }
  2063. X      *** */
  2064. X    }
  2065. X
  2066. X    /* print precedence, if necessary */
  2067. X    if( precedence(x) != DEFAULT_PREC )
  2068. X    { newline();  aprint("   ");  cprint(KW_PRECEDENCE);
  2069. X      aprint(" ");  printnum(precedence(x));
  2070. X    }
  2071. X
  2072. X    /* print associativity, if necessary */
  2073. X    if( !right_assoc(x) )
  2074. X    { newline();  aprint("   ");
  2075. X      cprint(KW_ASSOC);  aprint(" ");  cprint(KW_LEFT);
  2076. X    }
  2077. X
  2078. X    /* print named parameters and local objects */
  2079. X    lbr_printed = FALSE;
  2080. X    for( link = Down(x);  link != x;  link = NextDown(link) )
  2081. X    { Child(y, link);
  2082. X      assert( enclosing(y) == x, "echo: enclosing(y) != x!" );
  2083. X      switch( type(y) )
  2084. X      {
  2085. X        case LPAR:
  2086. X        case RPAR:    newline();  aprint("   ");
  2087. X            cprint( type(y) == LPAR ? KW_LEFT :
  2088. X                has_body(x) ? KW_BODY : KW_RIGHT);
  2089. X            aprint(" ");
  2090. X            cprint( SymName(y) );
  2091. X            aprint("   # uses_count = ");
  2092. X            printnum(uses_count(y));
  2093. X            if( visible(y) )  aprint(" (visible)");
  2094. X            break;
  2095. X
  2096. X        case NPAR:    moveright();  newline();
  2097. X            echo(y, NO_PREC);
  2098. X            aprint("   # uses_count = ");
  2099. X            printnum(uses_count(y));
  2100. X            moveleft();
  2101. X            break;
  2102. X
  2103. X        case MACRO:
  2104. X        case LOCAL:    if( !lbr_printed )
  2105. X            { newline();
  2106. X              cprint(KW_LBR);
  2107. X              lbr_printed = TRUE;
  2108. X            }
  2109. X            moveright();
  2110. X            echo(y, NO_PREC);
  2111. X            moveleft();  newline();
  2112. X            break;
  2113. X
  2114. X        default:    Error(FATAL, &fpos(y), "echo: type(y) = %s",
  2115. X                    Image(type(y)));
  2116. X            break;
  2117. X      }
  2118. X    }
  2119. X    if( type(x) == NPAR && Down(x) == x )  aprint(" ");
  2120. X    else newline();
  2121. X    if( !lbr_printed )
  2122. X    { cprint(KW_LBR);  aprint("  ");
  2123. X      lbr_printed = TRUE;
  2124. X    }
  2125. X    else aprint("   ");
  2126. X
  2127. X    /* print body */
  2128. X    moveright();
  2129. X    if( sym_body(x) != nil )  echo(sym_body(x), NO_PREC);
  2130. X    moveleft();  if( type(x) == LOCAL ) newline();
  2131. X    cprint(KW_RBR);
  2132. X    break;
  2133. X
  2134. X
  2135. X    case ONE_COL:
  2136. X    case ONE_ROW:
  2137. X    case HCONTRACT:
  2138. X    case VCONTRACT:
  2139. X    case HEXPAND:
  2140. X    case VEXPAND:
  2141. X    case PADJUST:
  2142. X    case HADJUST:
  2143. X    case VADJUST:
  2144. X    case HSCALE:
  2145. X    case VSCALE:
  2146. X    case NEXT:
  2147. X    case WIDE:
  2148. X    case HIGH:
  2149. X    case INCGRAPHIC:
  2150. X    case SINCGRAPHIC:
  2151. X    case GRAPHIC:
  2152. X    case ROTATE:
  2153. X    case SCALE:
  2154. X    case CASE:
  2155. X    case YIELD:
  2156. X    case XCHAR:
  2157. X    case FONT:
  2158. X    case SPACE:
  2159. X    case BREAK:
  2160. X    case OPEN:
  2161. X    case TAGGED:
  2162. X    
  2163. X    /* print enclosing left brace if needed */
  2164. X    braces_needed = (DEFAULT_PREC <= outer_prec);
  2165. X    if( braces_needed )  cprint(KW_LBR), aprint(" ");
  2166. X
  2167. X    /* print left parameter */
  2168. X    if( Down(x) != LastDown(x) )
  2169. X    { Child(y, Down(x));
  2170. X      echo(y, max(outer_prec, DEFAULT_PREC));
  2171. X      aprint(" ");
  2172. X    }
  2173. X
  2174. X    cprint(Image(type(x)));
  2175. X
  2176. X    /* print right parameter */
  2177. X    assert( LastDown(x) != x, "echo: right parameter of predefined!" );
  2178. X    aprint(" ");
  2179. X    Child(y, LastDown(x));
  2180. X    echo(y, type(x)==OPEN ? FORCE_PREC : max(outer_prec,DEFAULT_PREC));
  2181. X    if( braces_needed )  aprint(" "), cprint(KW_RBR);
  2182. X    break;
  2183. X
  2184. X
  2185. X    case NULL_CLOS:
  2186. X    
  2187. X    cprint(Image(type(x)));
  2188. X    break;
  2189. X
  2190. X
  2191. X    case CR_ROOT:
  2192. X
  2193. X    for( link = Down(x);  link != x;  link = NextDown(link) )
  2194. X    { Child(y, link);
  2195. X      echo(y, NO_PREC);  newline();
  2196. X    }
  2197. X    break;
  2198. X
  2199. X
  2200. X    case CROSS_SYM:
  2201. X
  2202. X    aprint("Cross-references for ");
  2203. X    cprint(SymName(symb(x)));  newline();
  2204. X    switch( target_state(x) )
  2205. X    {
  2206. X      case 0:    aprint("NO_TARGET");
  2207. X            break;
  2208. X
  2209. X      case 1:    aprint("SEEN_TARGET ");
  2210. X            printnum(target_seq(x));
  2211. X            aprint(": ");
  2212. X            echo(target_val(x), NO_PREC);
  2213. X            break;
  2214. X
  2215. X      case 2:    aprint("WRITTEN_TARGET ");
  2216. X            printnum(target_seq(x));
  2217. X            aprint(": to file ");
  2218. X            cprint(FileName(target_file(x)));
  2219. X            aprint(" at ");
  2220. X            printnum(target_pos(x));
  2221. X            break;
  2222. X    
  2223. X      default:    aprint("ILLEGAL!");
  2224. X            break;
  2225. X    }
  2226. X    newline();
  2227. X    for( link = Down(x);  link != x;  link = NextDown(link) )
  2228. X    { Child(y, link);
  2229. X      aprint("   ");
  2230. X      if( gall_rec(y) )  aprint("gall_rec!");
  2231. X      else cprint(string(y));
  2232. X      newline();
  2233. X    }
  2234. X    break;
  2235. X
  2236. X
  2237. X    default:
  2238. X    
  2239. X    Error(INTERN, no_fpos, "echo found %s", Image(type(x)));
  2240. X    break;
  2241. X
  2242. X  } /* end switch */
  2243. X} /* end echo */
  2244. X
  2245. X
  2246. X/*@::EchoObject(), DebugObject()@*********************************************/
  2247. X/*                                                                           */
  2248. X/*  FULL_CHAR *EchoObject(x)                                                 */
  2249. X/*                                                                           */
  2250. X/*  Return an image of unsized object x in result.                           */
  2251. X/*                                                                           */
  2252. X/*****************************************************************************/
  2253. X
  2254. XFULL_CHAR *EchoObject(x)
  2255. XOBJECT x;
  2256. X{ debug0(DOE, D, "EchoObject()");
  2257. X  fp = null;;
  2258. X  col = 0;
  2259. X  indent = 0;
  2260. X  limit  = 60;
  2261. X  if( fp == null )
  2262. X  BeginString();
  2263. X  if( x == nil )  AppendString(AsciiToFull("<nil>"));
  2264. X  else echo(x, type(x) == GAP_OBJ ? VCAT : 0);
  2265. X  debug0(DOE, D, "EchoObject returning");
  2266. X  return EndString();
  2267. X} /* end EchoObject */
  2268. X
  2269. X
  2270. X/*****************************************************************************/
  2271. X/*                                                                           */
  2272. X/*  DebugObject(x)                                                           */
  2273. X/*                                                                           */
  2274. X/*  Send an image of unsized object x to result.                             */
  2275. X/*                                                                           */
  2276. X/*****************************************************************************/
  2277. X
  2278. XDebugObject(x)
  2279. XOBJECT x;
  2280. X{ debug0(DOE, D, "DebugObject()");
  2281. X  fp = stderr;
  2282. X  col = 0;
  2283. X  indent = 0;
  2284. X  limit  = 60;
  2285. X  if( x == nil )  fprintf(stderr, "<nil>");
  2286. X  else echo(x, type(x) == GAP_OBJ ? VCAT : 0);
  2287. X  fprintf(stderr, "\n");
  2288. X  debug0(DOE, D, "DebugObject returning");
  2289. X} /* end DebugObject */
  2290. X#endif
  2291. END_OF_FILE
  2292.   if test 21404 -ne `wc -c <'z25.c'`; then
  2293.     echo shar: \"'z25.c'\" unpacked with wrong size!
  2294.   fi
  2295.   # end of 'z25.c'
  2296. fi
  2297. echo shar: End of archive 14 \(of 35\).
  2298. cp /dev/null ark14isdone
  2299. MISSING=""
  2300. 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
  2301.     if test ! -f ark${I}isdone ; then
  2302.     MISSING="${MISSING} ${I}"
  2303.     fi
  2304. done
  2305. if test "${MISSING}" = "" ; then
  2306.     echo You have unpacked all 35 archives.
  2307.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  2308. else
  2309.     echo You still must unpack the following archives:
  2310.     echo "        " ${MISSING}
  2311. fi
  2312. exit 0
  2313. exit 0 # Just in case...
  2314.