home *** CD-ROM | disk | FTP | other *** search
/ Turbo Toolbox / Turbo_Toolbox.iso / 1991 / 01 / pictex / pictex.tex < prev    next >
Encoding:
Text File  |  1989-04-02  |  126.7 KB  |  3,680 lines

  1. % This is PiCTeX, Version 1.1   9/21/87
  2.  
  3. % CAVEAT: The PiCTeX manual often has a more lucid explanation
  4. %   of any given topic than you will find in the internal documentation
  5. %   of the macros.
  6.  
  7. % PiCTeX's commands can be classified into two groups: (1) public (or
  8. %   external), and (2) private (or internal). The public macros are
  9. %   discussed at length in the manual. The only discussion of the private
  10. %   macros is the internal documentation. The private macros all have
  11. %   names beginning with an exclamation point (!) of category code 11. 
  12. %   Since in normal usage "!" has category code 12, these macros can't
  13. %   be accessed or modified by the general user.
  14.  
  15. % The macros are organized into thematically related groups. For example,
  16. %   the macros dealing with dots & dashes are all in the DASHPATTERN group.
  17. %   The table below shows which macros are in which groups. The table
  18. %   covers all public macros, and many (but not all) of PiCTeX's upper level
  19. %   private macros. Following the table, the various groups are listed
  20. %   in the order in which they appear in the table.
  21.  
  22. % *********************** TABLE OF GROUPS OF MACROS **********************
  23.  
  24. % HACKS:  Utility macros
  25. %    \PiC
  26. %    \PiCTeX
  27. %    \placevalueinpts 
  28. %    \!!loop 
  29. %    \!cfor
  30. %    \!copylist
  31. %    \!ecfor
  32. %    \!etfor
  33. %    \!getnext
  34. %    \!getnextvalueof
  35. %    \!ifempty
  36. %    \!ifnextchar
  37. %    \!leftappend
  38. %    \!listaddon 
  39. %    \!loop
  40. %    \!lop
  41. %    \!mlap
  42. %    \!not
  43. %    \!removept
  44. %    \!rightappend
  45. %    \!tfor 
  46. %    \!vmlap
  47. %    \!wlet
  48.  
  49. % ALLOCATION:  Allocates registers
  50.  
  51. % AREAS: Deals with plot areas 
  52. %    \axis
  53. %    \grid 
  54. %    \invisibleaxes
  55. %    \normalgraphs 
  56. %    \plotheading 
  57. %    \setplotarea
  58. %    \visibleaxes
  59.  
  60. % ARROWS:  Draws arrows
  61. %    \arrow
  62. %    \betweenarrows
  63.  
  64. % BARS:  Draws bars
  65. %    \putbar 
  66. %    \setbars
  67.  
  68. % BOXES:  Draws rectangles
  69. %    \frame
  70. %    \putrectangle 
  71. %    \rectangle
  72. %    \shaderectangleson
  73. %    \shaderectanglesoff
  74.  
  75. % CURVES:  Upper level plot commands
  76. %    \hshade 
  77. %    \plot 
  78. %    \sethistograms
  79. %    \setlinear
  80. %    \setquadratic
  81. %    \vshade
  82.  
  83. % DASHPATTERNS:  Sets up dash patterns
  84. %    \findlength 
  85. %    \setdashes 
  86. %    \setdashesnear
  87. %    \setdashpattern
  88. %    \setdots 
  89. %    \setdotsnear 
  90. %    \setsolid
  91. %    \!dashingoff
  92. %    \!dashingon
  93.  
  94. % DIVISION:  Does long division of dimension registers
  95. %    \Divide 
  96. %    \!divide
  97.  
  98. % ELLIPSES:  Draws ellipses and circles
  99. %    \circulararc 
  100. %    \ellipticalarc 
  101.  
  102. % RULES:  Draws rules, i.e., horizontal & vertical lines
  103. %    \putrule 
  104. %    \!putdashedhline
  105. %    \!putdashedvline
  106. %    \!puthline 
  107. %    \!putsolidhline  
  108. %    \!putsolidvline  
  109. %    \!putvline
  110.  
  111. % LINEAR ARC:  Draws straight lines -- solid and dashed
  112. %    \inboundscheckoff
  113. %    \inboundscheckon
  114. %    \!advancedashing 
  115. %    \!drawlinearsegment
  116. %    \!initinboundscheck
  117. %    \!linearsolid
  118. %    \!lineardashed
  119. %    \!ljoin
  120. %    \!plotifinbounds     
  121. %    \!start 
  122.  
  123. % LOGTEN:  Log_10 function
  124. %    \!logten
  125.  
  126. % PICTURES:  Basic setups for PiCtures; \put commands
  127. %    \accountingoff
  128. %    \accountingon
  129. %    \beginpicture
  130. %    \endpicture    
  131. %    \endpicturesave 
  132. %    \lines
  133. %    \multiput
  134. %    \put 
  135. %    \setcoordinatemode
  136. %    \setcoordinatesystem
  137. %    \setdimensionmode
  138. %    \stack 
  139. %    \Lines
  140. %    \Xdistance
  141. %    \Ydistance
  142. %    \!dimenput
  143. %    \!ifcoordmode
  144. %    \!ifdimenmode
  145. %    \!setcoordmode
  146. %    \!setdimenmode
  147. %    \!setputobject
  148.    
  149. % PLOTTING:  Things to do with plotting
  150. %    \dontsavelinesandcurves
  151. %    \replot
  152. %    \savelinesandcurves 
  153. %    \setplotsymbol
  154. %    \writesavefile 
  155. %    \!plot
  156.  
  157. % PYTHAGORAS:  Euclidean distance function
  158. %    \placehypotenuse 
  159. %    \!Pythag
  160.  
  161. % QUADRATIC ARC:  Draws a quadratic arc
  162. %    \!qjoin 
  163.  
  164. % ROTATIONS:  Handles rotations
  165. %    \startrotation 
  166. %    \stoprotation
  167. %    \!rotateaboutpivot
  168. %    \!rotateonly
  169.  
  170. % SHADING:  Handles shading
  171. %    \setshadegrid 
  172. %    \setshadesymbol
  173. %    \!lshade
  174. %    \!qshade
  175. %    \!starthshade
  176. %    \!startvshade  
  177.  
  178. % TICKS:  Draws ticks on graphs
  179. %    \gridlines
  180. %    \loggedticks
  181. %    \nogridlines
  182. %    \ticksin
  183. %    \ticksout
  184. %    \unloggesticks
  185.  
  186. % ***************** END OF TABLE OF GROUPS OF MACROS ********************
  187.  
  188.  
  189. \catcode`!=11 %  ***** THIS MUST NEVER BE OMITTED
  190. % *******************************
  191. % *** HACKS  (Utility macros) ***
  192. % *******************************
  193.  
  194. % ** User commands
  195. % **   \PiC{P\kern-.12em\lower.5ex\hbox{I}\kern-.075emC}
  196. % **   \PiCTeX{\PiC\kern-.11em\TeX}
  197. % **   \placevalueinpts of <DIMENSION REGISTER> in {CONTROL SEQUENCE}
  198.   
  199. % ** Internal commands
  200. % **   \!ifnextchar{CHARACTER}{TRUE ACTION}{FALSE ACTION}
  201. % **   \!tfor NAME := LIST \do {BODY}
  202. % **   \!etfor NAME:= LIST \do {BODY}
  203. % **   \!cfor NAME := LIST \do {BODY}
  204. % **   \!ecfor NAME:= LIST \do {BODY}
  205. % **   \!ifempty{MACRO}{TRUE ACTION}{FALSE ACTION}
  206. % **   \!getnext\\ITEMfrom\LIST
  207. % **   \!getnextvalueof\DIMEN\from\LIST
  208. % **   \!copylist\LISTMACRO_A\to\LISTMACRO_B
  209. % **   \!wlet\CONTROL_SEQUENCE_A=\CONTROL_SEQUENCE_B
  210. % **   \!listaddon ITEM LIST
  211. % **   \!rightappendITEM\withCS\to\LISTMACRO
  212. % **   \!leftappendITEM\withCS\to\LISTMACRO
  213. % **   \!lop\LISTMACRO\to\ITEM
  214. % **   \!loop ... repeat
  215. % **   \!!loop ... repeat
  216. % **   \!removept{DIMENSION REGISTER}{CONTROL SEQUENCE}
  217. % **   \!mlap{...}  
  218. % **   \!vmlap{...}
  219. % **   \!not{TEK if-CONDITION}
  220.  
  221. % ** First, here are the the PiCTeX logo, and the syllable PiC:
  222. \def\PiC{P\kern-.12em\lower.5ex\hbox{I}\kern-.075emC}
  223. \def\PiCTeX{\PiC\kern-.11em\TeX}
  224.  
  225. % ** The following macro expands to parameter #2 or parameter #3 according to
  226. % ** whether the next non-blank character following the macro is or is not #1. 
  227. % ** Blanks following the macro are gobbled.
  228. \def\!ifnextchar#1#2#3{%
  229.   \let\!testchar=#1%
  230.   \def\!first{#2}%
  231.   \def\!second{#3}%
  232.   \futurelet\!nextchar\!testnext}
  233. \def\!testnext{%
  234.   \ifx \!nextchar \!spacetoken 
  235.     \let\!next=\!skipspacetestagain
  236.   \else
  237.     \ifx \!nextchar \!testchar
  238.       \let\!next=\!first
  239.     \else 
  240.       \let\!next=\!second 
  241.     \fi 
  242.   \fi
  243.   \!next}
  244. \def\\{\!skipspacetestagain} 
  245.   \expandafter\def\\ {\futurelet\!nextchar\!testnext} 
  246. \def\\{\let\!spacetoken= } \\  %  ** set \spacetoken to a space token
  247.  
  248.  
  249. % ** Borrow the "tfor" macro from Latex:
  250. % **   \!tfor NAME := LIST \do {BODY}
  251. % **   if, before expansion, LIST = T1 ... Tn,  where each  Ti  is a token
  252. % **   or  {...},  then executes  BODY  n  times, with  NAME = Ti  on the
  253. % **   i-th iteration.  Works for  n=0.
  254. \def\!tfor#1:=#2\do#3{%
  255.   \edef\!fortemp{#2}%
  256.   \ifx\!fortemp\!empty 
  257.     \else
  258.     \!tforloop#2\!nil\!nil\!!#1{#3}%
  259.   \fi}
  260. \def\!tforloop#1#2\!!#3#4{%
  261.   \def#3{#1}%
  262.   \ifx #3\!nnil
  263.     \let\!nextwhile=\!fornoop
  264.   \else
  265.     #4\relax
  266.     \let\!nextwhile=\!tforloop
  267.   \fi 
  268.   \!nextwhile#2\!!#3{#4}}
  269.  
  270.  
  271. % **   \!etfor NAME:= LIST\do {BODY}
  272. % **   This is like \!cfor, but LIST is any balanced token list whose complete
  273. % **     expansion has the form  T1 ... Tn
  274. \def\!etfor#1:=#2\do#3{%
  275.   \def\!!tfor{\!tfor#1:=}%
  276.   \edef\!!!tfor{#2}%
  277.   \expandafter\!!tfor\!!!tfor\do{#3}}
  278.  
  279.  
  280. % **   modify the Latex \tfor (token-for) loop to a \cfor (comma-for) loop.
  281. % **   \!cfor NAME := LIST \do {BODY}
  282. % **     if, before expansion, LIST = a1,a2,...an, then executes  BODY n times,
  283. % **     with  NAME = ai  on the i-th iteration.  Works for  n=0.
  284. \def\!cfor#1:=#2\do#3{%
  285.   \edef\!fortemp{#2}%
  286.   \ifx\!fortemp\!empty 
  287.   \else
  288.     \!cforloop#2,\!nil,\!nil\!!#1{#3}%
  289.   \fi}
  290. \def\!cforloop#1,#2\!!#3#4{%
  291.   \def#3{#1}%
  292.   \ifx #3\!nnil
  293.     \let\!nextwhile=\!fornoop 
  294.   \else
  295.     #4\relax
  296.     \let\!nextwhile=\!cforloop
  297.   \fi
  298.   \!nextwhile#2\!!#3{#4}}
  299.  
  300.  
  301. % **   \!ecfor NAME:= LIST\do {BODY}
  302. % **   This is like \!cfor, but LIST is any balanced token list whose complete
  303. % **     expansion has the form  a1,a2,...,an.
  304. \def\!ecfor#1:=#2\do#3{%
  305.   \def\!!cfor{\!cfor#1:=}%
  306.   \edef\!!!cfor{#2}%
  307.   \expandafter\!!cfor\!!!cfor\do{#3}}
  308.  
  309.  
  310. \def\!empty{}
  311. \def\!nnil{\!nil}
  312. \def\!fornoop#1\!!#2#3{}
  313.  
  314.  
  315. % **  \!ifempty{ARG}{TRUE ACTION}{FALSE ACTION}
  316. \def\!ifempty#1#2#3{%
  317.   \edef\!emptyarg{#1}%
  318.   \ifx\!emptyarg\!empty
  319.     #2%
  320.   \else
  321.     #3%
  322.   \fi}
  323.  
  324. % **  \!getnext\\ITEMfrom\LIST
  325. % **    \LIST has the form \\{item1}\\{item2}\\{item3}...\\{itemk}
  326. % **    This routine sets \ITEM to item1, and cycles \LIST to
  327. % **    \\{item2}\\{item3}...\\{itemk}\\{item1}
  328. \def\!getnext#1\from#2{%
  329.   \expandafter\!gnext#2\!#1#2}%
  330. \def\!gnext\\#1#2\!#3#4{%
  331.   \def#3{#1}%
  332.   \def#4{#2\\{#1}}%
  333.   \ignorespaces}
  334.  
  335.  
  336. % ** \!getnextvalueof\DIMEN\from\LIST
  337. % **   Similar to !getnext.  
  338. % **   \LIST has the form \\{dimen1}\\{dimen2}\\{dimen3} ... 
  339. % **   \DIMEN is a dimension register
  340. % **   Works also for counts
  341. %
  342. \def\!getnextvalueof#1\from#2{%
  343.   \expandafter\!gnextv#2\!#1#2}%
  344. \def\!gnextv\\#1#2\!#3#4{%
  345.   #3=#1%
  346.   \def#4{#2\\{#1}}%
  347.   \ignorespaces}
  348.  
  349.  
  350. % ** \!copylist\LISTMACROA\to\LISTMACROB
  351. % **   makes the replacement text of LISTMACRO B identical to that of
  352. % **   list macro A.
  353. \def\!copylist#1\to#2{%
  354.   \expandafter\!!copylist#1\!#2}
  355. \def\!!copylist#1\!#2{%
  356.   \def#2{#1}\ignorespaces}
  357.  
  358.  
  359. % **  \!wlet\CSA=\CSB
  360. % **  lets control sequence \CSB = control sequence \CSA, and writes a
  361. % **    message to that effect in the log file using plain TEK's \wlog
  362. \def\!wlet#1=#2{%
  363.   \let#1=#2 
  364.   \wlog{\string#1=\string#2}}
  365.  
  366. % ** \!listaddon ITEM LIST
  367. % ** LIST <-- LIST \\ ITEM
  368. \def\!listaddon#1#2{%
  369.   \expandafter\!!listaddon#2\!{#1}#2}
  370. \def\!!listaddon#1\!#2#3{%
  371.   \def#3{#1\\#2}}
  372.  
  373. % **  \!rightappendITEM\to\LISTMACRO
  374. % **    \LISTMACRO --> \LISTMACRO\\{ITEM}
  375. %\def\!rightappend#1\to#2{\expandafter\!!rightappend#2\!{#1}#2}
  376. %\def\!!rightappend#1\!#2#3{\def#3{#1\\{#2}}}
  377.  
  378.  
  379. % **  \!rightappendITEM\withCS\to\LISTMACRO
  380. % **    \LISTMACRO --> \LISTMACRO||CS||{ITEM}
  381. \def\!rightappend#1\withCS#2\to#3{\expandafter\!!rightappend#3\!#2{#1}#3}
  382. \def\!!rightappend#1\!#2#3#4{\def#4{#1#2{#3}}}
  383.  
  384.  
  385. % **  \!leftappendITEM\withCS\to\LISTMACRO
  386. % **    \LISTMACRO --> CS||{ITEM}||\LISTMACRO
  387. \def\!leftappend#1\withCS#2\to#3{\expandafter\!!leftappend#3\!#2{#1}#3}
  388. \def\!!leftappend#1\!#2#3#4{\def#4{#2{#3}#1}}
  389.  
  390.  
  391. % **  \!lop\LISTMACRO\to\ITEM
  392. % **    \\{item1}\\{item2}\\{item3} ... --> \\{item2}\\{item3} ...
  393. % **    item1 --> \ITEM
  394. \def\!lop#1\to#2{\expandafter\!!lop#1\!#1#2}
  395. \def\!!lop\\#1#2\!#3#4{\def#4{#1}\def#3{#2}}
  396.  
  397.  
  398. % **  \!placeNUMBER\of\LISTMACRO\in\ITEM
  399. % **    the NUMBERth item of \LISTMACRO --> replacement text of \ITEM
  400. %\def\!place#1\of#2\in#3{\def#3{\outofrange}%
  401. %{\count0=#1\def\\##1{\advance\count0-1 \ifnum\count0=0 \gdef#3{##1}\fi}#2}}
  402.  
  403.  
  404. % **  Following code converts a commalist to a list macro, with all items 
  405. % **    fully expanded.
  406. %\!ecfor\item:=\commalist\do{\expandafter\!rightappend\item\to\list}
  407.  
  408.  
  409. % ** \!loop ... repeat
  410. % ** This is exactly like TEX's \loop ... repeat.  It can be used in nesting
  411. % ** two loops, without puting the inner one inside a group.
  412. \def\!loop#1\repeat{\def\!body{#1}\!iterate}
  413. \def\!iterate{\!body\let\!next=\!iterate\else\let\!next=\relax\fi\!next}
  414.  
  415. % ** \!!loop ... repeat
  416. % ** This is exactly like TEX's \loop ... repeat.  It can be used in nesting
  417. % ** two loops, without puting the inner one inside a group.
  418. \def\!!loop#1\repeat{\def\!!body{#1}\!!iterate}
  419. \def\!!iterate{\!!body\let\!!next=\!!iterate\else\let\!!next=\relax\fi\!!next}
  420. %  (\multiput uses \!!loop)
  421.  
  422. % ** \!removept{DIMENREG}{\CS}
  423. % ** Defines the control sequence CS to be the value (in points) in the
  424. % ** dimension register DIMENREG (but without the "pt" TEK usually adds)
  425. % ** E.g., after  \dimen0=12.3pt \!removept\dimen0\A, \A expands to 12.3
  426. \def\!removept#1#2{\edef#2{\expandafter\!!removePT\the#1}}
  427. {\catcode`p=12 \catcode`t=12 \gdef\!!removePT#1pt{#1}}
  428.  
  429. % ** \pladevalueinpts of <DIMENSION REGISTER> in {CONTROL SEQUENCE}
  430. \def\placevalueinpts of <#1> in #2 {%
  431.   \!removept{#1}{#2}}
  432.  
  433. % ** \!mlap{...}  \!vmlap{...}
  434. % ** Center  ...  in a box of width 0.
  435. \def\!mlap#1{\hbox to 0pt{\hss#1\hss}}
  436. \def\!vmlap#1{\vbox to 0pt{\vss#1\vss}}
  437.  
  438. % ** \!not{TEK if-CONDITION}
  439. % ** By a TEK if-CONDITION is meant something like 
  440. % **     \ifnum\N<0,   or   \ifdim\A>\B
  441. % ** \!not produces an if-condition which is false if the original condition
  442. % ** is true, and true if the original condition is false.
  443. \def\!not#1{%
  444.   #1\relax
  445.     \!switchfalse
  446.   \else
  447.     \!switchtrue
  448.   \fi
  449.   \if!switch
  450.   \ignorespaces}
  451.  
  452.  
  453. % *******************
  454. % *** ALLOCATIONS ***
  455. % *******************
  456.  
  457. % This section allocates all the registers PiCTeX uses. Following
  458. % each allocation is a string of the form  ....N.D...L......... ;
  459. % the various letters show which sections of PiCTeX make explicit
  460. % reference to that register, according to the following code:
  461.  
  462. %   H Hacks
  463. %   A Areas
  464. %   W arroWs
  465. %   B Bars
  466. %   X boXes
  467. %   C Curves
  468. %   D Dashpattterns
  469. %   V diVision
  470. %   E Ellipses
  471. %   U rUles
  472. %   L Linear arc
  473. %   G loGten
  474. %   P Pictures
  475. %   O plOtting
  476. %   Y pYthagoras
  477. %   Q Quadratic arc
  478. %   R Rotations
  479. %   S Shading
  480. %   T Ticks
  481.  
  482. % Turn off messages from TeX's allocation macros
  483. \let\!!!wlog=\wlog              % "\wlog" is defined in plain TeX
  484. \def\wlog#1{}    
  485.  
  486. \newdimen\headingtoplotskip     %.A.................
  487. \newdimen\linethickness         %.A..X....U........T
  488. \newdimen\longticklength        %.A................T
  489. \newdimen\plotsymbolspacing     %......D...L....Q...
  490. \newdimen\shortticklength       %.A................T
  491. \newdimen\stackleading          %.A..........P......
  492. \newdimen\tickstovaluesleading  %.A................T
  493. \newdimen\totalarclength        %......D...L....Q...
  494. \newdimen\valuestolabelleading  %.A.................
  495.  
  496. \newbox\!boxA                   %.AW...............T
  497. \newbox\!boxB                   %..W................
  498. \newbox\!picbox                 %............P......
  499. \newbox\!plotsymbol             %..........L..O.....
  500. \newbox\!putobject              %............PO...S.
  501. \newbox\!shadesymbol            %.................S.
  502.  
  503. \newcount\!countA               %.A....D..UL....Q.ST
  504. \newcount\!countB               %......D..U.....Q.ST
  505. \newcount\!countC               %...............Q..T
  506. \newcount\!countD               %...................
  507. \newcount\!countE               %.............O....T
  508. \newcount\!countF               %.............O....T
  509. \newcount\!countG               %..................T
  510. \newcount\!fiftypt              %.........U.........
  511. \newcount\!intervalno           %..........L....Q...
  512. \newcount\!npoints              %..........L........
  513. \newcount\!nsegments            %.........U.........
  514. \newcount\!ntemp                %............P......
  515. \newcount\!parity               %.................S.
  516. \newcount\!scalefactor          %..................T
  517. \newcount\!tfs                  %.......V...........
  518. \newcount\!tickcase             %..................T
  519.  
  520. \newdimen\!Xleft                %............P......
  521. \newdimen\!Xright               %............P......
  522. \newdimen\!Xsave                %.A................T
  523. \newdimen\!Ybot                 %............P......
  524. \newdimen\!Ysave                %.A................T
  525. \newdimen\!Ytop                 %............P......
  526. \newdimen\!angle                %........E..........
  527. \newdimen\!arclength            %..W......UL....Q...
  528. \newdimen\!areabloc             %.A........L........
  529. \newdimen\!arealloc             %.A........L........
  530. \newdimen\!arearloc             %.A........L........
  531. \newdimen\!areatloc             %.A........L........
  532. \newdimen\!bshrinkage           %.................S.
  533. \newdimen\!checkbot             %..........L........
  534. \newdimen\!checkleft            %..........L........
  535. \newdimen\!checkright           %..........L........
  536. \newdimen\!checktop             %..........L........
  537. \newdimen\!dimenA               %.AW.X.DVEUL..OYQRST
  538. \newdimen\!dimenB               %....X.DVEU...O.QRS.
  539. \newdimen\!dimenC               %..W.X.DVEU......RS.
  540. \newdimen\!dimenD               %..W.X.DVEU....Y.RS.
  541. \newdimen\!dimenE               %..W........G..YQ.S.
  542. \newdimen\!dimenF               %...........G..YQ.S.
  543. \newdimen\!dimenG               %...........G..YQ.S.
  544. \newdimen\!dimenH               %...........G..Y..S.
  545. \newdimen\!dimenI               %...BX.........Y....
  546. \newdimen\!distacross           %..........L....Q...
  547. \newdimen\!downlength           %..........L........
  548. \newdimen\!dp                   %.A..X.......P....S.
  549. \newdimen\!dshade               %.................S.
  550. \newdimen\!dxpos                %..W......U..P....S.
  551. \newdimen\!dxprime              %...............Q...
  552. \newdimen\!dypos                %..WB.....U..P......
  553. \newdimen\!dyprime              %...............Q...
  554. \newdimen\!ht                   %.A..X.......P....S.
  555. \newdimen\!leaderlength         %......D..U.........
  556. \newdimen\!lshrinkage           %.................S.
  557. \newdimen\!midarclength         %...............Q...
  558. \newdimen\!offset               %.A................T
  559. \newdimen\!plotheadingoffset    %.A.................
  560. \newdimen\!plotsymbolxshift     %..........L..O.....
  561. \newdimen\!plotsymbolyshift     %..........L..O.....
  562. \newdimen\!plotxorigin          %..........L..O.....
  563. \newdimen\!plotyorigin          %..........L..O.....
  564. \newdimen\!rootten              %...........G.......
  565. \newdimen\!rshrinkage           %.................S.
  566. \newdimen\!shadesymbolxshift    %.................S.
  567. \newdimen\!shadesymbolyshift    %.................S.
  568. \newdimen\!tenAa                %...........G.......
  569. \newdimen\!tenAc                %...........G.......
  570. \newdimen\!tenAe                %...........G.......
  571. \newdimen\!tshrinkage           %.................S.
  572. \newdimen\!uplength             %..........L........
  573. \newdimen\!wd                   %....X.......P....S.
  574. \newdimen\!wmax                 %...............Q...
  575. \newdimen\!wmin                 %...............Q...
  576. \newdimen\!xB                   %...............Q...
  577. \newdimen\!xC                   %...............Q...
  578. \newdimen\!xE                   %..W.....E.L....Q.S.
  579. \newdimen\!xM                   %..W.....E......Q.S.
  580. \newdimen\!xS                   %..W.....E.L....Q.S.
  581. \newdimen\!xaxislength          %.A................T
  582. \newdimen\!xdiff                %..........L........
  583. \newdimen\!xleft                %............P......
  584. \newdimen\!xloc                 %..WB.....U.......S.
  585. \newdimen\!xorigin              %.A........L.P....S.
  586. \newdimen\!xpivot               %................R..
  587. \newdimen\!xpos                 %..........L.P..Q.ST
  588. \newdimen\!xprime               %...............Q...
  589. \newdimen\!xright               %............P......
  590. \newdimen\!xshade               %.................S.
  591. \newdimen\!xshift               %..W.........PO...S.
  592. \newdimen\!xtemp                %............P......
  593. \newdimen\!xunit                %.AWBX...EUL.P..QRS.
  594. \newdimen\!xxE                  %........E..........
  595. \newdimen\!xxM                  %........E..........
  596. \newdimen\!xxS                  %........E..........
  597. \newdimen\!xxloc                %..WB....EU.........
  598. \newdimen\!yB                   %...............Q...
  599. \newdimen\!yC                   %...............Q...
  600. \newdimen\!yE                   %..W.....E.L....Q...
  601. \newdimen\!yM                   %..W.....E......Q...
  602. \newdimen\!yS                   %..W.....E.L....Q...
  603. \newdimen\!yaxislength          %.A................T
  604. \newdimen\!ybot                 %............P......
  605. \newdimen\!ydiff                %..........L........
  606. \newdimen\!yloc                 %..WB.....U.......S.
  607. \newdimen\!yorigin              %.A........L.P....S.
  608. \newdimen\!ypivot               %................R..
  609. \newdimen\!ypos                 %..........L.P..Q.ST
  610. \newdimen\!yprime               %...............Q...
  611. \newdimen\!yshade               %.................S.
  612. \newdimen\!yshift               %..W.........PO...S.
  613. \newdimen\!ytemp                %............P......
  614. \newdimen\!ytop                 %............P......
  615. \newdimen\!yunit                %.AWBX...EUL.P..QRS.
  616. \newdimen\!yyE                  %........E..........
  617. \newdimen\!yyM                  %........E..........
  618. \newdimen\!yyS                  %........E..........
  619. \newdimen\!yyloc                %..WB....EU.........
  620. \newdimen\!zpt                  %.AWBX.DVEULGP.YQ.ST
  621.  
  622. \newif\if!axisvisible           %.A.................
  623. \newif\if!gridlinestoo          %..................T
  624. \newif\if!keepPO                %...................
  625. \newif\if!placeaxislabel        %.A.................
  626. \newif\if!switch                %H..................
  627. \newif\if!xswitch               %.A................T
  628.  
  629. \newtoks\!axisLaBeL             %.A.................
  630. \newtoks\!keywordtoks           %.A.................
  631.  
  632. \newwrite\!replotfile           %.............O.....
  633.  
  634. \newhelp\!keywordhelp{The keyword mentioned in the error message in unknown. 
  635. Replace NEW KEYWORD in the indicated response by the keyword that 
  636. should have been specified.}    %.A.................
  637.  
  638. % The following commands assign alternate names to some of the 
  639. % above registers.  "\!wlet"  is defined in  Hacks.
  640. \!wlet\!!origin=\!xM                   %.A................T
  641. \!wlet\!!unit=\!uplength               %.A................T
  642. \!wlet\!Lresiduallength=\!dimenG       %.........U.........
  643. \!wlet\!Rresiduallength=\!dimenF       %.........U.........
  644. \!wlet\!axisLength=\!distacross        %.A................T
  645. \!wlet\!axisend=\!ydiff                %.A................T
  646. \!wlet\!axisstart=\!xdiff              %.A................T
  647. \!wlet\!axisxlevel=\!arclength         %.A................T
  648. \!wlet\!axisylevel=\!downlength        %.A................T
  649. \!wlet\!beta=\!dimenE                  %...............Q...
  650. \!wlet\!gamma=\!dimenF                 %...............Q...
  651. \!wlet\!shadexorigin=\!plotxorigin     %.................S.
  652. \!wlet\!shadeyorigin=\!plotyorigin     %.................S.
  653. \!wlet\!ticklength=\!xS                %..................T
  654. \!wlet\!ticklocation=\!xE              %..................T
  655. \!wlet\!ticklocationincr=\!yE          %..................T
  656. \!wlet\!tickwidth=\!yS                 %..................T
  657. \!wlet\!totalleaderlength=\!dimenE     %.........U.........
  658. \!wlet\!xone=\!xprime                  %....X..............
  659. \!wlet\!xtwo=\!dxprime                 %....X..............
  660. \!wlet\!ySsave=\!yM                    %...................
  661. \!wlet\!ybB=\!yB                       %.................S.
  662. \!wlet\!ybC=\!yC                       %.................S.
  663. \!wlet\!ybE=\!yE                       %.................S.
  664. \!wlet\!ybM=\!yM                       %.................S.
  665. \!wlet\!ybS=\!yS                       %.................S.
  666. \!wlet\!ybpos=\!yyloc                  %.................S.
  667. \!wlet\!yone=\!yprime                  %....X..............
  668. \!wlet\!ytB=\!xB                       %.................S.
  669. \!wlet\!ytC=\!xC                       %.................S.
  670. \!wlet\!ytE=\!downlength               %.................S.
  671. \!wlet\!ytM=\!arclength                %.................S.
  672. \!wlet\!ytS=\!distacross               %.................S.
  673. \!wlet\!ytpos=\!xxloc                  %.................S.
  674. \!wlet\!ytwo=\!dyprime                 %....X..............
  675.  
  676.  
  677. % Initial values for registers
  678. \!zpt=0pt                              % static
  679. \!xunit=1pt
  680. \!yunit=1pt
  681. \!arearloc=\!xunit
  682. \!areatloc=\!yunit
  683. \!dshade=5pt
  684. \!leaderlength=24in
  685. \!tfs=256                              % static
  686. \!wmax=5.3pt                           % static
  687. \!wmin=2.7pt                           % static
  688. \!xaxislength=\!xunit
  689. \!xpivot=\!zpt
  690. \!yaxislength=\!yunit 
  691. \!ypivot=\!zpt
  692. \plotsymbolspacing=.4pt
  693.   \!dimenA=50pt \!fiftypt=\!dimenA     % static
  694.  
  695. \!rootten=3.162278pt                   % static
  696. \!tenAa=8.690286pt                     % static  (A5)
  697. \!tenAc=2.773839pt                     % static  (A3)
  698. \!tenAe=2.543275pt                     % static  (A1)
  699.  
  700. % Initial values for control sequences
  701. \def\!cosrotationangle{1}      %................R..
  702. \def\!sinrotationangle{0}      %................R..
  703. \def\!xpivotcoord{0}           %................R..
  704. \def\!xref{0}                  %............P......
  705. \def\!xshadesave{0}            %.................S.
  706. \def\!ypivotcoord{0}           %................R..
  707. \def\!yref{0}                  %............P......
  708. \def\!yshadesave{0}            %.................S.
  709. \def\!zero{0}                  %..................T
  710.  
  711. % Reset TeX to report allocations
  712. \let\wlog=\!!!wlog
  713. %  *************************************
  714. %  ***  AREAS: Deals with plot areas ***
  715. %  *************************************
  716. %
  717. %  ** User commands
  718. %  **   \setplotarea x from LEFT XCOORD to RIGTH XCOORD, y from BOTTOM YCOORD
  719. %  **      to TOP YCOORD
  720. %  **   \axis BOTTOM-LEFT-TOP-RIGHT  [SHIFTEDTO xy=COORD] [VISIBLE-INVISIBLE]
  721. %  **      [LABEL {label}] [TICKS] /
  722. %  **   \visibleaxes
  723. %  **   \invisibleaxes
  724. %  **   \plotheading {HEADING}
  725. %  **   \grid {# of columns} {# of rows}
  726. %  **   \normalgraphs 
  727.   
  728. %  **  \normalgraphs
  729. %  **    Sets defaults for graph setup. See Subsection 3.4 of manual.
  730. \def\normalgraphs{%
  731.   \longticklength=.4\baselineskip
  732.   \shortticklength=.25\baselineskip
  733.   \tickstovaluesleading=.25\baselineskip
  734.   \valuestolabelleading=.8\baselineskip
  735.   \linethickness=.4pt
  736.   \stackleading=.17\baselineskip
  737.   \headingtoplotskip=1.5\baselineskip
  738.   \visibleaxes
  739.   \ticksout
  740.   \nogridlines
  741.   \unloggedticks}
  742. %
  743. % **  \setplotarea x from LEFT XCOORD to RIGTH XCOORD, y from BOTTOM YCOORD
  744. % **    to TOP YCOORD
  745. % **  Reserves space in PICBOX for a rectangular box with the indicated
  746. % **   coordinates.  Must be specified before calls to  \axis, 
  747. % **   \grid, \plotheading.
  748. % **  See Subsection 3.1 of the manual.
  749. \def\setplotarea x from #1 to #2, y from #3 to #4 {%
  750.   \!arealloc=\!M{#1}\!xunit \advance \!arealloc -\!xorigin
  751.   \!areabloc=\!M{#3}\!yunit \advance \!areabloc -\!yorigin
  752.   \!arearloc=\!M{#2}\!xunit \advance \!arearloc -\!xorigin
  753.   \!areatloc=\!M{#4}\!yunit \advance \!areatloc -\!yorigin
  754.   \!initinboundscheck
  755.   \!xaxislength=\!arearloc  \advance\!xaxislength -\!arealloc
  756.   \!yaxislength=\!areatloc  \advance\!yaxislength -\!areabloc
  757.   \!plotheadingoffset=\!zpt
  758.   \!dimenput {{\setbox0=\hbox{}\wd0=\!xaxislength\ht0=\!yaxislength\box0}}
  759.      [bl] (\!arealloc,\!areabloc)}
  760. %
  761. % ** \visibleaxes, \invisibleaxes 
  762. % ** Switches for setting visibility of subsequent axes.
  763. % ** See Subsection 3.2 of the manual.
  764. \def\visibleaxes{%
  765.   \def\!axisvisibility{\!axisvisibletrue}}
  766. \def\invisibleaxes{%
  767.   \def\!axisvisibility{\!axisvisiblefalse}}
  768. %
  769. % ** The next few macros enable the user to fix up an erroneous keyword
  770. % **   in the \axis command.
  771. %  \newhelp is in ALLOCATIONS
  772. %  \newhelp\!keywordhelp{The keyword mentioned in the error message in unknown. 
  773. %  Replace NEW KEYWORD in the indicated response by the keyword that 
  774. %  should have been specified.}
  775.  
  776. \def\!fixkeyword#1{%
  777.   \errhelp=\!keywordhelp
  778.   \errmessage{Unrecognized keyword `#1': \the\!keywordtoks{NEW KEYWORD}'}}
  779.  
  780. %  \newtoks\!keywordtoks    In ALLOCATIONS.
  781. \!keywordtoks={enter `i\fixkeyword}
  782.  
  783. \def\fixkeyword#1{%
  784.   \!nextkeyword#1 }
  785.  
  786. % ** \axis BOTTOM-LEFT-TOP-RIGHT  [SHIFTEDTO xy=COORD] [VISIBLE-INVISIBLE]
  787. % **   [LABEL {label}] [TICKS] /
  788. % ** Exactly one of the keywords BOTTOM, LEFT, TOP, RIGHT must be
  789. % ** specified. Axis is drawn along the indicated edge of the current
  790. % ** plot area, shifted if the SHIFTEDTO option is used, visible or
  791. % ** invisible according the selected option, with an optional LABEL,
  792. % ** and optional TICKS (see ticks.tex for the options avialabel with
  793. % ** TICKS). The TICKS option must be the last one specified. The \axis
  794. % ** MUST be terminated with a / followed by a space.
  795. % ** See Subsection 3.2 of the manual for more information.
  796.  
  797. % ** The various options of the \axis command are processed by the
  798. % ** \!nextkeyword macro defined below. For example, 
  799. % ** `\!nextkeyword shiftedto ' expands to `\!axisshiftedto'.
  800. \def\axis {%
  801.   \def\!nextkeyword##1 {%
  802.     \expandafter\ifx\csname !axis##1\endcsname \relax
  803.       \def\!next{\!fixkeyword{##1}}%
  804.     \else
  805.       \def\!next{\csname !axis##1\endcsname}%
  806.     \fi
  807.     \!next}%
  808.   \!offset=\!zpt
  809.   \!axisvisibility
  810.   \!placeaxislabelfalse
  811.   \!nextkeyword}
  812.  
  813. % ** This and the various macros that follow handle the keyword
  814. % ** specifications on the \axis command
  815. % ** See Subsection 3.2 of the manual.
  816. \def\!axisbottom{%
  817.   \!axisylevel=\!areabloc
  818.   \def\!tickxsign{0}%
  819.   \def\!tickysign{-}%
  820.   \def\!axissetup{\!axisxsetup}%
  821.   \def\!axislabeltbrl{t}%
  822.   \!nextkeyword}
  823.  
  824. \def\!axistop{%
  825.   \!axisylevel=\!areatloc
  826.   \def\!tickxsign{0}%
  827.   \def\!tickysign{+}%
  828.   \def\!axissetup{\!axisxsetup}%
  829.   \def\!axislabeltbrl{b}%
  830.   \!nextkeyword}
  831.  
  832. \def\!axisleft{%
  833.   \!axisxlevel=\!arealloc
  834.   \def\!tickxsign{-}%
  835.   \def\!tickysign{0}%
  836.   \def\!axissetup{\!axisysetup}%
  837.   \def\!axislabeltbrl{r}%
  838.   \!nextkeyword}
  839.  
  840. \def\!axisright{%
  841.   \!axisxlevel=\!arearloc
  842.   \def\!tickxsign{+}%
  843.   \def\!tickysign{0}%
  844.   \def\!axissetup{\!axisysetup}%
  845.   \def\!axislabeltbrl{l}%
  846.   \!nextkeyword}
  847.  
  848. \def\!axisshiftedto#1=#2 {%
  849.   \if 0\!tickxsign
  850.     \!axisylevel=\!M{#2}\!yunit
  851.     \advance\!axisylevel -\!yorigin
  852.   \else
  853.     \!axisxlevel=\!M{#2}\!xunit
  854.     \advance\!axisxlevel -\!xorigin
  855.   \fi
  856.   \!nextkeyword}
  857.  
  858. \def\!axisvisible{%
  859.   \!axisvisibletrue  
  860.   \!nextkeyword}
  861.  
  862. \def\!axisinvisible{%
  863.   \!axisvisiblefalse
  864.   \!nextkeyword}
  865.  
  866. \def\!axislabel#1 {%
  867.   \!axisLaBeL={#1}%
  868.   \!placeaxislabeltrue
  869.   \!nextkeyword}
  870.  
  871. \expandafter\def\csname !axis/\endcsname{%
  872.   \!axissetup % This could done already by "ticks"; if so, now \relax
  873.   \if!placeaxislabel
  874.     \!placeaxislabel
  875.   \fi
  876.   \if +\!tickysign %                 ** (A "top" axis)
  877.     \!dimenA=\!axisylevel
  878.     \advance\!dimenA \!offset %      ** dimA = top of the axis structure
  879.     \advance\!dimenA -\!areatloc %   ** dimA = excess over the plot area
  880.     \ifdim \!dimenA>\!plotheadingoffset
  881.       \!plotheadingoffset=\!dimenA % ** Greatest excess over the plot area
  882.     \fi
  883.   \fi}
  884.  
  885. % ** \grid {c} {r} 
  886. % ** Partitions the plot area into c columns and r rows; see Subsection 3.3
  887. % ** of the manual.
  888. % ** (Other grid patterns can be drawn with the TICKS option of the \axis 
  889. % ** command.
  890. \def\grid #1 #2 {%
  891.   \!countA=#1\advance\!countA 1
  892.   \axis bottom invisible ticks length <\!zpt> andacross quantity {\!countA} /
  893.   \!countA=#2\advance\!countA 1
  894.   \axis left   invisible ticks length <\!zpt> andacross quantity {\!countA} / }
  895.  
  896. % ** \plotheading{HEADING}
  897. % ** Places HEADING centered above the top of the plotarea (and above
  898. % ** any top axis ticks marks, tick labels, and axis label); see
  899. % ** Subsection 3.3 of the manual.
  900. \def\plotheading#1 {%
  901.   \advance\!plotheadingoffset \headingtoplotskip
  902.   \!dimenput {#1} [B] <.5\!xaxislength,\!plotheadingoffset>
  903.     (\!arealloc,\!areatloc)}
  904.  
  905. % ** From here on, the routines are internal.
  906. \def\!axisxsetup{%
  907.   \!axisxlevel=\!arealloc
  908.   \!axisstart=\!arealloc
  909.   \!axisend=\!arearloc
  910.   \!axisLength=\!xaxislength
  911.   \!!origin=\!xorigin
  912.   \!!unit=\!xunit
  913.   \!xswitchtrue
  914.   \if!axisvisible 
  915.     \!makeaxis
  916.   \fi}
  917.  
  918. \def\!axisysetup{%
  919.   \!axisylevel=\!areabloc
  920.   \!axisstart=\!areabloc
  921.   \!axisend=\!areatloc
  922.   \!axisLength=\!yaxislength
  923.   \!!origin=\!yorigin
  924.   \!!unit=\!yunit
  925.   \!xswitchfalse
  926.   \if!axisvisible
  927.     \!makeaxis
  928.   \fi}
  929.  
  930. \def\!makeaxis{%
  931.   \setbox\!boxA=\hbox{% (Make a pseudo-y[x] tick for an x[y]-axis)
  932.     \beginpicture
  933.       \!setdimenmode
  934.       \setcoordinatesystem point at {\!zpt} {\!zpt}   
  935.       \putrule from {\!zpt} {\!zpt} to
  936.         {\!tickysign\!tickysign\!axisLength} 
  937.         {\!tickxsign\!tickxsign\!axisLength}
  938.     \endpicturesave <\!Xsave,\!Ysave>}%
  939.     \wd\!boxA=\!zpt
  940.     \!placetick\!axisstart}
  941.  
  942. \def\!placeaxislabel{%
  943.   \advance\!offset \valuestolabelleading
  944.   \if!xswitch
  945.     \!dimenput {\the\!axisLaBeL} [\!axislabeltbrl]
  946.       <.5\!axisLength,\!tickysign\!offset> (\!axisxlevel,\!axisylevel)
  947.     \advance\!offset \!dp  % ** advance offset by the "tallness"
  948.     \advance\!offset \!ht  % ** of the label
  949.   \else
  950.     \!dimenput {\the\!axisLaBeL} [\!axislabeltbrl]
  951.       <\!tickxsign\!offset,.5\!axisLength> (\!axisxlevel,\!axisylevel)
  952.   \fi
  953.   \!axisLaBeL={}}
  954.  
  955.  
  956. % *******************************
  957. % *** ARROWS  (Draws arrows)  ***
  958. % *******************************
  959. %
  960. % ** User commands
  961. % **  \arrow <ARROW HEAD LENGTH> [MID FRACTION, BASE FRACTION]
  962. % **    [<XSHIFT,YSHIFT>] from XFROM YFROM to XTO YTO
  963. % **  \betweenarrows {TEXT} [orientation & shift] from XFROM YFROM to XTO YTO
  964.  
  965. % ** \arrow <ARROW HEAD LENGTH> [MID FRACTION, BASE FRACTION]
  966. % **    [<XSHIFT,YSHIFT>] from XFROM YFROM to XTO YTO
  967. % ** Draws an arrow from (XFROM,YFROM) to (XTO,YTO).  The arrow head
  968. % ** is constructed two quadratic arcs, which extend back a distance
  969. % ** ARROW HEAD LENGTH (a dimension) on both sides of the arrow shaft.
  970. % ** All the way back the arcs are a distance BASE FRACTION*ARROW HEAD
  971. % ** LENGTH apart, while half-way back they are a distance MID FRACTION*
  972. % ** ARROW HEAD LENGTH apart. <XSHIFT,YSHIFT> is optional, and has
  973. % ** its usual interpreation. See Subsection 5.4 of the manual.
  974.  
  975. \def\arrow <#1> [#2,#3]{%
  976.   \!ifnextchar<{\!arrow{#1}{#2}{#3}}{\!arrow{#1}{#2}{#3}<\!zpt,\!zpt> }}
  977.  
  978. \def\!arrow#1#2#3<#4,#5> from #6 #7 to #8 #9 {%
  979. %
  980. % ** convert to dimensions
  981.   \!xloc=\!M{#8}\!xunit   
  982.   \!yloc=\!M{#9}\!yunit
  983.   \!dxpos=\!xloc  \!dimenA=\!M{#6}\!xunit  \advance \!dxpos -\!dimenA
  984.   \!dypos=\!yloc  \!dimenA=\!M{#7}\!yunit  \advance \!dypos -\!dimenA
  985.   \let\!MAH=\!M%                         ** save current c/d mode
  986.   \!setdimenmode%                        ** go into dimension mode
  987. %
  988.   \!xshift=#4\relax  \!yshift=#5\relax%  ** pick up shift
  989.   \!reverserotateonly\!xshift\!yshift%   ** back rotate shift
  990.   \advance\!xshift\!xloc  \advance\!yshift\!yloc
  991. %
  992. % **  draw shaft of arrow
  993.   \!xS=-\!dxpos  \advance\!xS\!xshift
  994.   \!yS=-\!dypos  \advance\!yS\!yshift
  995.   \!start (\!xS,\!yS)
  996.   \!ljoin (\!xshift,\!yshift)
  997. %
  998. % ** find 32*cosine and 32*sine of angle of rotation
  999.   \!Pythag\!dxpos\!dypos\!arclength
  1000.   \!divide\!dxpos\!arclength\!dxpos  
  1001.   \!dxpos=32\!dxpos  \!removept\!dxpos\!!cos
  1002.   \!divide\!dypos\!arclength\!dypos  
  1003.   \!dypos=32\!dypos  \!removept\!dypos\!!sin
  1004. % ** construct arrowhead
  1005.   \!halfhead{#1}{#2}{#3}%                ** draw half of arrow head
  1006.   \!halfhead{#1}{-#2}{-#3}%              ** draw other half
  1007. %
  1008.   \let\!M=\!MAH%                         ** restore old c/d mode
  1009.   \ignorespaces}
  1010. %
  1011. % ** draw half of arrow head
  1012.   \def\!halfhead#1#2#3{%
  1013.     \!dimenC=-#1%                
  1014.     \divide \!dimenC 2 %                 ** half way back
  1015.     \!dimenD=#2\!dimenC%                 ** half the mid width
  1016.     \!rotate(\!dimenC,\!dimenD)by(\!!cos,\!!sin)to(\!xM,\!yM)
  1017.     \!dimenC=-#1%                        ** all the way back
  1018.     \!dimenD=#3\!dimenC
  1019.     \!dimenD=.5\!dimenD%                 ** half the full width
  1020.     \!rotate(\!dimenC,\!dimenD)by(\!!cos,\!!sin)to(\!xE,\!yE)
  1021.     \!start (\!xshift,\!yshift)
  1022.     \advance\!xM\!xshift  \advance\!yM\!yshift
  1023.     \advance\!xE\!xshift  \advance\!yE\!yshift
  1024.     \!qjoin (\!xM,\!yM) (\!xE,\!yE) 
  1025.     \ignorespaces}
  1026.  
  1027.  
  1028. % ** \betweenarrows {TEXT} [orientation & shift] from XFROM YFROM to XTO YTO
  1029. % **   Makes things like <--- text --->, using arrow heads from TeX's fonts.
  1030. % **   See Subsection 5.4 of the manual.
  1031. \def\betweenarrows #1#2 from #3 #4 to #5 #6 {%
  1032.   \!xloc=\!M{#3}\!xunit  \!xxloc=\!M{#5}\!xunit%   
  1033.   \!yloc=\!M{#4}\!yunit  \!yyloc=\!M{#6}\!yunit%           
  1034.   \!dxpos=\!xxloc  \advance\!dxpos by -\!xloc
  1035.   \!dypos=\!yyloc  \advance\!dypos by -\!yloc
  1036.   \advance\!xloc .5\!dxpos
  1037.   \advance\!yloc .5\!dypos
  1038. %
  1039.   \let\!MBA=\!M%           ** save current coord\dimen mode
  1040.   \!setdimenmode%          ** express locations in dimens
  1041.   \ifdim\!dypos=\!zpt
  1042.     \ifdim\!dxpos<\!zpt \!dxpos=-\!dxpos \fi
  1043.     \put {\!lrarrows{\!dxpos}{#1}}#2{} at {\!xloc} {\!yloc}
  1044.   \else
  1045.     \ifdim\!dxpos=\!zpt
  1046.       \ifdim\!dypos<\!zpt \!dypos=-\!zpt \fi
  1047.       \put {\!udarrows{\!dypos}{#1}}#2{} at {\!xloc} {\!yloc}
  1048.     \fi
  1049.   \fi
  1050.   \let\!M=\!MBA%           ** restore previous c/d mode
  1051.   \ignorespaces}
  1052.  
  1053. % ** Subroutine for left-right between arrows 
  1054. \def\!lrarrows#1#2{% #1=width, #2=text
  1055.   {\setbox\!boxA=\hbox{$\mkern-2mu\mathord-\mkern-2mu$}%
  1056.    \setbox\!boxB=\hbox{$\leftarrow$}\!dimenE=\ht\!boxB
  1057.    \setbox\!boxB=\hbox{}\ht\!boxB=2\!dimenE
  1058.    \hbox to #1{$\mathord\leftarrow\mkern-6mu
  1059.      \cleaders\copy\!boxA\hfil
  1060.      \mkern-6mu\mathord-$%
  1061.      \kern.4em $\vcenter{\box\!boxB}$$\vcenter{\hbox{#2}}$\kern.4em
  1062.      $\mathord-\mkern-6mu
  1063.      \cleaders\copy\!boxA\hfil
  1064.      \mkern-6mu\mathord\rightarrow$}}}
  1065.  
  1066. % ** Subroutine for up-down between arrows 
  1067. \def\!udarrows#1#2{% #1=width, #2=text
  1068.   {\setbox\!boxB=\hbox{#2}%
  1069.    \setbox\!boxA=\hbox to \wd\!boxB{\hss$\vert$\hss}%
  1070.    \!dimenE=\ht\!boxA \advance\!dimenE \dp\!boxA \divide\!dimenE 2
  1071.    \vbox to #1{\offinterlineskip
  1072.       \vskip .05556\!dimenE
  1073.       \hbox to \wd\!boxB{\hss$\mkern.4mu\uparrow$\hss}\vskip-\!dimenE
  1074.       \cleaders\copy\!boxA\vfil
  1075.       \vskip-\!dimenE\copy\!boxA
  1076.       \vskip\!dimenE\copy\!boxB\vskip.4em
  1077.       \copy\!boxA\vskip-\!dimenE
  1078.       \cleaders\copy\!boxA\vfil
  1079.       \vskip-\!dimenE \hbox to \wd\!boxB{\hss$\mkern.4mu\downarrow$\hss}
  1080.       \vskip .05556\!dimenE}}}
  1081.  
  1082.  
  1083. % ***************************
  1084. % *** BARS  (Draws bars)  ***
  1085. % ***************************
  1086. %
  1087. % ** User commands:
  1088. % ** \putbar [<XSHIFT,YSHIFT>] breadth <BREADTH> from XSTART YSTART
  1089. % **   to XEND YEND
  1090. % ** \setbars [<XSHIFT,YSHIFT>] breadth <BREADTH> baseline at XY = COORD
  1091. % **   [baselabels ([B_ORIENTATION_x,B_ORIENTATION_y] <B_XSHIFT,B_YSHIFT>)]
  1092. % **   [endlabels  ([E_ORIENTATION_x,E_ORIENTATION_y] <E_XSHIFT,E_YSHIFT>)]
  1093.  
  1094.  
  1095. % ** \putbar [<XSHIFT,YSHIFT>] breadth <BREADTH> from XSTART YSTART
  1096. % **   to XEND YEND
  1097. % ** Either XSTART=XEND or YSTART=YEND. Draws a rectangle between
  1098. % **   (XSTART,YSTART) & (XEND,YEND). The "depth" of the rectangle
  1099. % **   is determined by those two plot positions; its other
  1100. % **   dimension "breadth" is specified by the dimension BREADTH.
  1101. % ** See Subsection 4.2 of the manual.
  1102. \def\putbar#1breadth <#2> from #3 #4 to #5 #6 {%
  1103.   \!xloc=\!M{#3}\!xunit  \!xxloc=\!M{#5}\!xunit%   
  1104.   \!yloc=\!M{#4}\!yunit  \!yyloc=\!M{#6}\!yunit%           
  1105.   \!dypos=\!yyloc  \advance\!dypos by -\!yloc
  1106.   \!dimenI=#2  
  1107.   \ifdim \!dimenI=\!zpt %            ** If 0 breadth
  1108.     \putrule#1from {#3} {#4} to {#5} {#6} % ** Then draw line
  1109.   \else %                            ** Else, put in a rectangle
  1110.     \let\!MBar=\!M%                  ** save current c/d mode
  1111.     \!setdimenmode %                 ** go into dimension mode
  1112.     \divide\!dimenI 2
  1113.     \ifdim \!dypos=\!zpt             
  1114.       \advance \!yloc -\!dimenI %    ** Equal y coordinates
  1115.       \advance \!yyloc \!dimenI
  1116.     \else
  1117.       \advance \!xloc -\!dimenI %    ** Equal x coordinates
  1118.       \advance \!xxloc \!dimenI
  1119.     \fi
  1120.     \putrectangle#1corners at {\!xloc} {\!yloc} and {\!xxloc} {\!yyloc}
  1121.     \let\!M=\!MBar %                 ** restore c/d mode
  1122.   \fi
  1123.   \ignorespaces}
  1124.  
  1125.  
  1126. % ** \setbars [<XSHIFT,YSHIFT>] breadth <BREADTH> baseline at XY = COORD
  1127. % **   [baselabels ([B_ORIENTATION_x,B_ORIENTATION_y] <B_XSHIFT,B_YSHIFT>)]
  1128. % **   [endlabels  ([E_ORIENTATION_x,E_ORIENTATION_y] <E_XSHIFT,E_YSHIFT>)]
  1129. % ** This command puts PiCTeX into the bar graph drawing mode described
  1130. % **   in Subsection 4.4 of the manual.
  1131. \def\setbars#1breadth <#2> baseline at #3 = #4 {%
  1132.   \edef\!barshift{#1}%
  1133.   \edef\!barbreadth{#2}%
  1134.   \edef\!barorientation{#3}%
  1135.   \edef\!barbaseline{#4}%
  1136.   \def\!bardobaselabel{\!bardoendlabel}%
  1137.   \def\!bardoendlabel{\!barfinish}%
  1138.   \let\!drawcurve=\!barcurve
  1139.   \!setbars}
  1140. \def\!setbars{%
  1141.   \futurelet\!nextchar\!!setbars}
  1142. \def\!!setbars{%
  1143.   \if b\!nextchar
  1144.     \def\!!!setbars{\!setbarsbget}%
  1145.   \else 
  1146.     \if e\!nextchar
  1147.       \def\!!!setbars{\!setbarseget}%
  1148.     \else
  1149.       \def\!!!setbars{\relax}%
  1150.     \fi
  1151.   \fi
  1152.   \!!!setbars}
  1153. \def\!setbarsbget baselabels (#1) {%
  1154.   \def\!barbaselabelorientation{#1}%
  1155.   \def\!bardobaselabel{\!!bardobaselabel}%
  1156.   \!setbars}
  1157. \def\!setbarseget endlabels (#1) {%
  1158.   \edef\!barendlabelorientation{#1}%
  1159.   \def\!bardoendlabel{\!!bardoendlabel}%
  1160.   \!setbars}
  1161.  
  1162. % ** \!barcurve
  1163. % ** Draws a bargraph with preset values of barshift, barbreadth,
  1164. % ** barorientation (x or y) and barbaseline (coordinate)
  1165. \def\!barcurve #1 #2 {%
  1166.   \if y\!barorientation
  1167.     \def\!basexarg{#1}%
  1168.     \def\!baseyarg{\!barbaseline}%
  1169.   \else
  1170.     \def\!basexarg{\!barbaseline}%
  1171.     \def\!baseyarg{#2}%
  1172.   \fi
  1173.   \expandafter\putbar\!barshift breadth <\!barbreadth> from {\!basexarg}
  1174.     {\!baseyarg} to {#1} {#2}
  1175.   \def\!endxarg{#1}%
  1176.   \def\!endyarg{#2}%
  1177.   \!bardobaselabel}
  1178.  
  1179. \def\!!bardobaselabel "#1" {%
  1180.   \put {#1}\!barbaselabelorientation{} at {\!basexarg} {\!baseyarg}
  1181.   \!bardoendlabel}
  1182.  
  1183. \def\!!bardoendlabel "#1" {%
  1184.   \put {#1}\!barendlabelorientation{} at {\!endxarg} {\!endyarg}
  1185.   \!barfinish}
  1186.  
  1187. \def\!barfinish{%
  1188.   \!ifnextchar/{\!finish}{\!barcurve}}
  1189.  
  1190.  
  1191. % ********************************
  1192. % *** BOXES (Draws rectangles) ***
  1193. % ********************************
  1194. %
  1195. % ** User commands:
  1196. % **   \putrectangle [<XSHIFT,YSHIFT>] corners at  XCOORD1 YCOORD1
  1197. % **     and  XCOORD2 YCOORD2 
  1198. % **   \shaderectangleson
  1199. % **   \shaderectanglesoff
  1200. % **   \frame [<SEPARATION>] {TEXT}
  1201. % **   \rectangle <WIDTH> <HEIGHT>
  1202. %
  1203. %
  1204. % **  \putrectangle [<XSHIFT,YSHIFT>] corners at XCOORD1 YCOORD1 
  1205. % **    and  XCOORD2 YCOORD2 
  1206. % **  Draws a rectangle with corners at (X1,Y1), (X2,Y1), (X1,Y2), (X2,Y2)
  1207. % **  Lines have thickness \linethickness, and overlap at the corners.
  1208. % **  The optional field  <XSHIFT,YSHIFT>  functions as with a \put command.
  1209. % **  See Subsection 4.2 of the manual.
  1210. \def\putrectangle{%
  1211.   \!ifnextchar<{\!putrectangle}{\!putrectangle<\!zpt,\!zpt> }}
  1212. \def\!putrectangle<#1,#2> corners at #3 #4 and #5 #6 {%
  1213. %
  1214. % ** get locations
  1215.   \!xone=\!M{#3}\!xunit  \!xtwo=\!M{#5}\!xunit%   
  1216.   \!yone=\!M{#4}\!yunit  \!ytwo=\!M{#6}\!yunit%           
  1217.   \ifdim \!xtwo<\!xone
  1218.     \!dimenI=\!xone  \!xone=\!xtwo  \!xtwo=\!dimenI
  1219.   \fi
  1220.   \ifdim \!ytwo<\!yone
  1221.     \!dimenI=\!yone  \!yone=\!ytwo  \!ytwo=\!dimenI
  1222.   \fi
  1223.   \!dimenI=#1\relax  \advance\!xone\!dimenI  \advance\!xtwo\!dimenI
  1224.   \!dimenI=#2\relax  \advance\!yone\!dimenI  \advance\!ytwo\!dimenI
  1225.   \let\!MRect=\!M%                  ** save current coord/dimen mode
  1226.   \!setdimenmode
  1227. %
  1228. % ** shade rectangle if appropriate
  1229.   \!shaderectangle
  1230. %
  1231. % ** draw horizontal edges
  1232.   \!dimenI=.5\linethickness
  1233.   \advance \!xone  -\!dimenI%       ** adjust x-location to overlap corners
  1234.   \advance \!xtwo   \!dimenI%       ** ditto
  1235.   \putrule from {\!xone} {\!yone} to {\!xtwo} {\!yone} 
  1236.   \putrule from {\!xone} {\!ytwo} to {\!xtwo} {\!ytwo} 
  1237. %
  1238. % ** draw vertical edges
  1239.   \advance \!xone   \!dimenI%       ** restore original x-values
  1240.   \advance \!xtwo  -\!dimenI% 
  1241.   \advance \!yone  -\!dimenI%       ** adjust y-location to overlap corners
  1242.   \advance \!ytwo   \!dimenI%       ** ditto
  1243.   \putrule from {\!xone} {\!yone} to {\!xone} {\!ytwo} 
  1244.   \putrule from {\!xtwo} {\!yone} to {\!xtwo} {\!ytwo} 
  1245. %
  1246.   \let\!M=\!MRect%                  ** restore coord/dimen mode
  1247.   \ignorespaces}
  1248.  
  1249. % ** \shaderectangleson 
  1250. % **   Subsequent rectangles will be shaded according to 
  1251. % **   the current shading pattern.  Affects \putrectangle, \putbar,
  1252. % **   \frame, \sethistograms, and \setbars. See Subsection 7.5 of the manual.
  1253. \def\shaderectangleson{%     
  1254.   \def\!shaderectangle{\!!shaderectangle}%
  1255.   \ignorespaces}
  1256. % ** \shaderectanglesoff 
  1257. % **    Suppresses  \shaderectangleson.  The default.
  1258. \def\shaderectanglesoff{%
  1259.   \def\!shaderectangle{}%
  1260.   \ignorespaces}
  1261.  
  1262. \shaderectanglesoff
  1263.  
  1264. % ** The following internal routine shades the current rectangle, when
  1265. % **   \!shaderectangle = \!!shaderectangle . 
  1266. \def\!!shaderectangle{%
  1267.   \!dimenA=\!xtwo  \advance \!dimenA -\!xone
  1268.   \!dimenB=\!ytwo  \advance \!dimenB -\!yone
  1269.   \ifdim \!dimenA<\!dimenB
  1270.     \!startvshade (\!xone,\!yone,\!ytwo)
  1271.     \!lshade      (\!xtwo,\!yone,\!ytwo)
  1272.   \else
  1273.     \!starthshade (\!yone,\!xone,\!xtwo)
  1274.     \!lshade      (\!ytwo,\!xone,\!xtwo)
  1275.   \fi
  1276.   \ignorespaces}
  1277.   
  1278. % ** \frame [<SEPARATION>] {TEXT}
  1279. % ** Draws a frame of thickness linethickness about the box enclosing
  1280. % **   TEXT; the frame is separated from the box by a distance of
  1281. % **   SEPARATION.  The result is an hbox with the same baseline as TEXT.
  1282. % **   If <SEPARATION> is omitted, you get the effect of <0pt>.
  1283. % ** See Subsection 4.2 of the manual.
  1284. \def\frame{%
  1285.   \!ifnextchar<{\!frame}{\!frame<\!zpt> }}
  1286. \long\def\!frame<#1> #2{%
  1287.   \beginpicture
  1288.     \setcoordinatesystem units <1pt,1pt> point at 0 0 
  1289.     \put {#2} [Bl] at 0 0 
  1290.     \!dimenA=#1\relax
  1291.     \!dimenB=\!wd \advance \!dimenB \!dimenA
  1292.     \!dimenC=\!ht \advance \!dimenC \!dimenA
  1293.     \!dimenD=\!dp \advance \!dimenD \!dimenA
  1294.     \let\!MFr=\!M
  1295.     \!setdimenmode
  1296.     \putrectangle corners at {-\!dimenA} {-\!dimenD} and {\!dimenB} {\!dimenC}
  1297.     \!setcoordmode
  1298.     \let\!M=\!MFr
  1299.   \endpicture
  1300.   \ignorespaces}
  1301.  
  1302. % ** \rectangle <WIDTH> <HEIGHT>
  1303. % ** Constructs a rectangle of width WIDTH and heigth HEIGHT. 
  1304. % ** See Subsection 4.2 of the manual.
  1305. \def\rectangle <#1> <#2> {%
  1306.   \setbox0=\hbox{}\wd0=#1\ht0=#2\frame {\box0}}
  1307.  
  1308.  
  1309. % *********************************************
  1310. % ***  CURVES  (Upper level \plot commands) ***
  1311. % *********************************************
  1312. %
  1313. % ** User commands
  1314. % **   \plot  DATA  /
  1315. % **   \plot  "FILE NAME"
  1316. % **   \setquadratic
  1317. % **   \setlinear
  1318. % **   \sethistograms
  1319. % **   \vshade  ...
  1320. % **   \hshade  ...
  1321.  
  1322. % \plot: multi-purpose command. Draws histograms, bar graphs, piecewise-linear
  1323. % or piecewise quadratic curves, depending on the setting of \!drawcurve.
  1324. % See Subsections 4.3-4.5, 5.1, 5.2 of the manual.
  1325. \def\plot{%
  1326.   \!ifnextchar"{\!plotfromfile}{\!drawcurve}}
  1327. \def\!plotfromfile"#1"{%
  1328.   \expandafter\!drawcurve \input #1 /}
  1329.  
  1330. % Command to set piecewise quadratic mode
  1331. % See Subsections 5.1, 7.3, and 7.4 of the manual.
  1332. \def\setquadratic{%
  1333.   \let\!drawcurve=\!qcurve
  1334.   \let\!!Shade=\!!qShade
  1335.   \let\!!!Shade=\!!!qShade}
  1336.  
  1337. % Command to set piecewise linear mode
  1338. % See Subsections 5.1, 7.3, and 7.4 of the manual.
  1339. \def\setlinear{%
  1340.   \let\!drawcurve=\!lcurve
  1341.   \let\!!Shade=\!!lShade
  1342.   \let\!!!Shade=\!!!lShade}
  1343.  
  1344. % Command to set histogram mode
  1345. % See Subsection 4.3 of the manual.
  1346. \def\sethistograms{%
  1347.   \let\!drawcurve=\!hcurve}
  1348.  
  1349. % Commands to cycle through list of coordinates in piecewise quadratic 
  1350. % interpolation mode
  1351. \def\!qcurve #1 #2 {%
  1352.   \!start (#1,#2)
  1353.   \!Qjoin}
  1354. \def\!Qjoin#1 #2 #3 #4 {%
  1355.   \!qjoin (#1,#2) (#3,#4)             % \!qjoin  is defined in QUADRATIC
  1356.   \!ifnextchar/{\!finish}{\!Qjoin}}
  1357.  
  1358. % Commands to cycle through list of coordinates in piecewise linear 
  1359. % interpolation mode
  1360. \def\!lcurve #1 #2 {%
  1361.   \!start (#1,#2)
  1362.   \!Ljoin}
  1363. \def\!Ljoin#1 #2 {%
  1364.   \!ljoin (#1,#2)                    % \!ljoin  is defined in LINEAR
  1365.   \!ifnextchar/{\!finish}{\!Ljoin}}
  1366.  
  1367. \def\!finish/{\ignorespaces}
  1368.  
  1369. % Command to cycle through list of coordinates in histogram mode
  1370. \def\!hcurve #1 #2 {%
  1371.   \edef\!hxS{#1}%
  1372.   \edef\!hyS{#2}%
  1373.   \!hjoin}
  1374. \def\!hjoin#1 #2 {%
  1375.   \putrectangle corners at {\!hxS} {\!hyS} and {#1} {#2}
  1376.   \edef\!hxS{#1}%
  1377.   \!ifnextchar/{\!finish}{\!hjoin}}
  1378.  
  1379.  
  1380. % \vshade: See Subsection 7.3 of the manual.
  1381. \def\vshade #1 #2 #3 {%
  1382.   \!startvshade (#1,#2,#3)
  1383.   \!Shadewhat}
  1384.  
  1385. % \hshade: See Subsection 7.4 of the manual.
  1386. \def\hshade #1 #2 #3 {%
  1387.   \!starthshade (#1,#2,#3)
  1388.   \!Shadewhat}
  1389.  
  1390. % Commands to cycle through coordinates and optional "edge effect"
  1391. % fields while shading.
  1392. \def\!Shadewhat{%
  1393.   \futurelet\!nextchar\!Shade}
  1394. \def\!Shade{%
  1395.   \if <\!nextchar
  1396.     \def\!nextShade{\!!Shade}%
  1397.   \else
  1398.     \if /\!nextchar
  1399.       \def\!nextShade{\!finish}%
  1400.     \else
  1401.       \def\!nextShade{\!!!Shade}%
  1402.     \fi
  1403.   \fi
  1404.   \!nextShade}
  1405. \def\!!lShade<#1> #2 #3 #4 {%
  1406.   \!lshade <#1> (#2,#3,#4)                 % \!lshade is defined in SHADING
  1407.   \!Shadewhat}
  1408. \def\!!!lShade#1 #2 #3 {%
  1409.   \!lshade (#1,#2,#3)
  1410.   \!Shadewhat} 
  1411. \def\!!qShade<#1> #2 #3 #4 #5 #6 #7 {%
  1412.   \!qshade <#1> (#2,#3,#4) (#5,#6,#7)      % \!qshade is defined in SHADING
  1413.   \!Shadewhat}
  1414. \def\!!!qShade#1 #2 #3 #4 #5 #6 {%
  1415.   \!qshade (#1,#2,#3) (#4,#5,#6)
  1416.   \!Shadewhat} 
  1417.  
  1418. % ** Set default interpolation mode
  1419. \setlinear
  1420.  
  1421.  
  1422. %  ********************************************
  1423. %  *** DASHPATTERNS (Sets up dash patterns) ***
  1424. %  ********************************************
  1425.  
  1426. %  **  User commands:
  1427. %  **    \setdashpattern <DIMEN1,DIMEN2,DIMEN3,...>
  1428. %  **    \setdots <INTRADOT_DISTANCE>
  1429. %  **    \setdotsnear <INTRADOT_DISTANCE> for <ARC LENGTH>
  1430. %  **    \setdashes <DASH/SKIP_DISTANCE>
  1431. %  **    \setdashesnear <DASH/SKIP_DISTANCE> for <ARC LENGTH>
  1432. %  **    \setsolid
  1433. %  **    \findlength {CURVE CMDS}
  1434.  
  1435. %  **  Internal commands:
  1436. %  **    \!dashingon
  1437. %  **    \!dashingoff
  1438.  
  1439. %  **  Dash patterns are specified by a balanced token list whose complete
  1440. %  **    expansion has the form: DIMEN1,DIMEN2,DIMEN3,DIMEN4,... ; this produces
  1441. %  **    an arc of length DIMEN1, a skip of length DIMEN2, an arc of length
  1442. %  **    DIMEN3, a skip of length DIMEN4, ... .  Any number of DIMEN values may
  1443. %  **    be given. The pattern is repeated as many times (perhaps fractional)
  1444. %  **    as necessary to draw the curve. 
  1445. %  **  A dash pattern remains in effect until it is overridden by a call to
  1446. %  **    \setdashpattern, or to \setdots, \setdotsnear ... , \setdashes, 
  1447. %  **    \setdashesnear ... , or \setsolid.
  1448. %  **  Solid lines are the default.
  1449.  
  1450.  
  1451. %  **  \def\setdashpattern <DIMEN1,DIMEN2,DIMEN3,...>
  1452. %  **  The following routine converts a balanced list of tokens whose
  1453. %  **  complete expansion has the form  DIMEN1,DIMEN2, ... , DIMENk  into 
  1454. %  **  three list macros that are used in drawing dashed rules and curves:
  1455. %  **    !Flist:   \!Rule{DIMEN1}\!Skip{DIMEN2}\!Rule{DIMEN3}\!Skip{DIMEN4} ...
  1456. %  **    !Blist:   ...\!Skip{DIMEN4}\!Rule{DIMEN3}\!Skip{DIMEN2}\!Rule{DIMEN1}
  1457. %  **    !UDlist:  \\{DIMEN1}\\{DIMEN2}\\{DIMEN3}\\{DIMEN4} ...;
  1458. %  **  calculates \!leaderlength := DIMEN1 + ... + DIMENk; and
  1459. %  **  sets the curve drawing routines to dash mode.
  1460. %  **  Those lists are used by the curve drawing routines.
  1461. %  **  Dimenj ... may be given as an explicit dimension (e.g., 5pt), or
  1462. %  **  as an expression involving a dimension register (e.g., -2.5\dimen0).
  1463. %  **  See Subsection 6.2 of the manual
  1464. \def\setdashpattern <#1>{%
  1465.   \def\!Flist{}\def\!Blist{}\def\!UDlist{}%
  1466.   \!countA=0
  1467.   \!ecfor\!item:=#1\do{%
  1468.     \!dimenA=\!item\relax
  1469.     \expandafter\!rightappend\the\!dimenA\withCS{\\}\to\!UDlist%
  1470.     \advance\!countA  1
  1471.     \ifodd\!countA
  1472.       \expandafter\!rightappend\the\!dimenA\withCS{\!Rule}\to\!Flist%
  1473.       \expandafter\!leftappend\the\!dimenA\withCS{\!Rule}\to\!Blist%
  1474.     \else 
  1475.       \expandafter\!rightappend\the\!dimenA\withCS{\!Skip}\to\!Flist%
  1476.       \expandafter\!leftappend\the\!dimenA\withCS{\!Skip}\to\!Blist%
  1477.     \fi}%
  1478.   \!leaderlength=\!zpt
  1479.   \def\!Rule##1{\advance\!leaderlength  ##1}%
  1480.   \def\!Skip##1{\advance\!leaderlength  ##1}%
  1481.   \!Flist%
  1482.   \ifdim\!leaderlength>\!zpt 
  1483.   \else
  1484.     \def\!Flist{\!Skip{24in}}\def\!Blist{\!Skip{24in}}\ignorespaces
  1485.     \def\!UDlist{\\{\!zpt}\\{24in}}\ignorespaces
  1486.     \!leaderlength=24in
  1487.   \fi
  1488.   \!dashingon}   
  1489.  
  1490.  
  1491. %  **  \!dashingon  -- puts the curve drawing routines into dash mode
  1492. %  **  \!dashingoff -- puts the curve drawing routines into solid mode
  1493. %  **  These are internal commands, invoked by \setdashpattern and \setsolid
  1494. \def\!dashingon{%
  1495.   \def\!advancedashing{\!!advancedashing}%
  1496.   \def\!drawlinearsegment{\!lineardashed}%
  1497.   \def\!puthline{\!putdashedhline}%
  1498.   \def\!putvline{\!putdashedvline}%
  1499. %  \def\!putsline{\!putdashedsline}%
  1500.   \ignorespaces}% 
  1501. \def\!dashingoff{%
  1502.   \def\!advancedashing{\relax}%
  1503.   \def\!drawlinearsegment{\!linearsolid}%
  1504.   \def\!puthline{\!putsolidhline}%
  1505.   \def\!putvline{\!putsolidvline}%
  1506. %  \def\!putsline{\!putsolidsline}%
  1507.   \ignorespaces}
  1508.  
  1509.  
  1510. %  **  \setdots <LENGTH>  --  sets up a dot/skip pattern where dot (actually
  1511. %  **    the current plotsymbol) is plunked down once for every LENGTH 
  1512. %  **    traveled along the curve.  LENGTH defaults to 5pt.
  1513. %  **    See Subsection 6.1 of the manual.
  1514. \def\setdots{%
  1515.   \!ifnextchar<{\!setdots}{\!setdots<5pt>}}
  1516. \def\!setdots<#1>{%
  1517.   \!dimenB=#1\advance\!dimenB -\plotsymbolspacing
  1518.   \ifdim\!dimenB<\!zpt
  1519.     \!dimenB=\!zpt
  1520.   \fi
  1521. \setdashpattern <\plotsymbolspacing,\!dimenB>}
  1522.  
  1523. % ** \setdotsnear <LENGTH> for <ARC LENGTH>
  1524. % ** sets up a dot pattern where the dots are approximately LENGTH apart,
  1525. % ** the total length of the pattern is ARC LENGTH, and the pattern
  1526. % ** begins and ends with a dot. See Subsection 6.3 of the manual.
  1527. \def\setdotsnear <#1> for <#2>{%
  1528.   \!dimenB=#2\relax  \advance\!dimenB -.05pt  
  1529.   \!dimenC=#1\relax  \!countA=\!dimenC 
  1530.   \!dimenD=\!dimenB  \advance\!dimenD .5\!dimenC  \!countB=\!dimenD
  1531.   \divide \!countB  \!countA
  1532.   \ifnum 1>\!countB 
  1533.     \!countB=1
  1534.   \fi
  1535.   \divide\!dimenB  \!countB
  1536.   \setdots <\!dimenB>}
  1537.  
  1538. %  **  \setdashes <LENGTH>  --  sets up a dash/skip pattern where the dash
  1539. %  **    and the skip are each of length LENGTH (the dash is formed by
  1540. %  **    plunking down the current plotsymbol over an arc of length LENGTH
  1541. %  **    and so may actually be longer than LENGTH.  LENGTH defaults to 5pt.
  1542. %  **    See Subsection 6.1 of the manual.
  1543. \def\setdashes{%
  1544.   \!ifnextchar<{\!setdashes}{\!setdashes<5pt>}}
  1545. \def\!setdashes<#1>{\setdashpattern <#1,#1>}
  1546.  
  1547. % ** \setdashesnear ...
  1548. % ** Like \setdotsnear; the pattern begins and ends with a dash.
  1549. % ** See Subsection 6.3 of the manual.
  1550. \def\setdashesnear <#1> for <#2>{%
  1551.   \!dimenB=#2\relax  
  1552.   \!dimenC=#1\relax  \!countA=\!dimenC 
  1553.   \!dimenD=\!dimenB  \advance\!dimenD .5\!dimenC  \!countB=\!dimenD
  1554.   \divide \!countB  \!countA
  1555.   \ifodd \!countB 
  1556.   \else 
  1557.     \advance \!countB  1
  1558.   \fi
  1559.   \divide\!dimenB  \!countB
  1560.   \setdashes <\!dimenB>}
  1561.  
  1562. %  **  \setsolid  --  puts the curve drawing routines in "solid line" mode,
  1563. %  **    the default mode.  See Subsection 6.1 of the manual.
  1564. \def\setsolid{%
  1565.   \def\!Flist{\!Rule{24in}}\def\!Blist{\!Rule{24in}}%  
  1566.   \def\!UDlist{\\{24in}\\{\!zpt}}%
  1567.   \!dashingoff}  
  1568. \setsolid
  1569.  
  1570. %  **  \findlength {CURVE CMDS}
  1571. %  **  PiCTeX executes the \start, \ljoin, and \qjoin cmds comprising
  1572. %  **  CURVE CMDS without plotting anything, but stashes the length
  1573. %  **  of the phantom curve away in \totalarclength.
  1574. %  **  See Subsection 6.3 of the manual.
  1575. \def\findlength#1{%
  1576.   \begingroup
  1577.     \setdashpattern <0pt, \maxdimen>
  1578.     \setplotsymbol ({})  
  1579.     \dontsavelinesandcurves
  1580.     #1%
  1581.   \endgroup
  1582.   \ignorespaces}
  1583.  
  1584.  
  1585. % *************************************************************
  1586. % *** DIVISION  (Does long division of dimension registers) ***
  1587. % *************************************************************
  1588.  
  1589. % ** User command:
  1590. % **   \Divide {DIVIDEND} by {DIVISOR} forming {RESULT}
  1591.   
  1592. % ** Internal command
  1593. % **   \!divide{DIVIDEND}{DIVISOR}{RESULT}
  1594.  
  1595. % **  \!divide DIVIDEND [by] DIVISOR [to get] ANSWER
  1596. % **  Divides the dimension DIVIDEND by the dimension DIVISOR, placing the 
  1597. % **  quotient in the dimension register ANSWER.  Values are understood to 
  1598. % **  be in points.  E.g.  12.5pt/1.4pt=8.92857pt.
  1599. % **  Quotient is accurate to 1/65536pt=2**[-16]pt
  1600. % **  |DIVISOR| should be < 2048pt (about 28 inches).
  1601. \def\!divide#1#2#3{%
  1602.   \!dimenB=#1%                      **  dimB  holds current remainder (r)
  1603.   \!dimenC=#2%                      **  dimC  holds divisor (d)
  1604.   \!dimenD=\!dimenB%                **  dimD  holds quotient q=r/d for this 
  1605.   \divide \!dimenD \!dimenC%        **    step, in units of scaled pts
  1606.   \!dimenA=\!dimenD%                **  dimA  eventually holds answer (a)
  1607.   \multiply\!dimenD \!dimenC%       **  r <-- r - dq
  1608.   \advance\!dimenB -\!dimenD%       **  First step complete. Have integer part
  1609. %                                   **  of a, and corresponding remainder.
  1610.   \!dimenD=\!dimenC%                **  Temporarily use dimD to hold |d|
  1611.     \ifdim\!dimenD<\!zpt \!dimenD=-\!dimenD 
  1612.   \fi
  1613.   \ifdim\!dimenD<64pt%              **  Branch on the magnitude of |d|
  1614.     \!divstep[\!tfs]\!divstep[\!tfs]%
  1615.   \else 
  1616.     \!!divide
  1617.   \fi
  1618.   #3=\!dimenA\ignorespaces}
  1619.  
  1620. % **  The following code handles divisors  d  with 
  1621. % **    (1)  .88in =  64pt <= d <  256pt =  3.54in
  1622. % **    (2) 3.54in = 256pt <= d < 2048pt = 28.34in
  1623. % **  Anything bigger than that may result in an overflow condition.
  1624. % **  For our purposes, we should never even see case (2).
  1625. \def\!!divide{%
  1626.   \ifdim\!dimenD<256pt
  1627.     \!divstep[64]\!divstep[32]\!divstep[32]%
  1628.   \else 
  1629.     \!divstep[8]\!divstep[8]\!divstep[8]\!divstep[8]\!divstep[8]%
  1630.     \!dimenA=2\!dimenA
  1631.   \fi}
  1632.  
  1633.  
  1634. % **  The following macro does the real long division work.
  1635. \def\!divstep[#1]{%                 **  #1 = "B"
  1636.   \!dimenB=#1\!dimenB%              **  r <-- B*r
  1637.   \!dimenD=\!dimenB%                **  dimD  holds quotient q=r/d for this 
  1638.     \divide \!dimenD by \!dimenC%   **    step, in units of scaled pts
  1639.   \!dimenA=#1\!dimenA%              **  a <-- B*a + q
  1640.     \advance\!dimenA by \!dimenD%
  1641.   \multiply\!dimenD by \!dimenC%    **  r <-- r - dq
  1642.     \advance\!dimenB by -\!dimenD}
  1643.  
  1644. % **  \Divide:  See Subsection 9.3 of the manual.
  1645. \def\Divide <#1> by <#2> forming <#3> {%
  1646.   \!divide{#1}{#2}{#3}}
  1647.  
  1648.  
  1649. % *********************************************
  1650. % *** ELLIPSES (Draws ellipses and circles) ***
  1651. % *********************************************
  1652.  
  1653. % ** User commands
  1654. % **   \ellipticalarc  axes ratio A:B  DEGREES degrees from XSTART YSTART 
  1655. % **      center at XCENTER YCENTER 
  1656. % **   \circulararc DEGREES degrees from XSTART YSTART 
  1657. % **      center at XCENTER YCENTER 
  1658.  
  1659. % ** Internal command
  1660. % **   \!sinandcos{32*ANGLE in radians}{32*SIN}{32*COS}
  1661.  
  1662.  
  1663. % **   \ellipticalarc  axes ratio A:B  DEGREES degrees from XSTART YSTART 
  1664. % **      center at XCENTER YCENTER 
  1665. % **    Draws a elliptical arc starting at the coordinate point (XSTART,YSTART).
  1666. % **    The center of the ellipse of which the arc is a segment is at 
  1667. % **      (XCENTER,YCENTER).
  1668. % **    The arc extends through an angle of DEGREES degrees (may be + or -).
  1669. % **    A:B is the ratio of the length of the xaxis to the length of
  1670. % **      the yaxis of the ellipse
  1671. % **    Sqrt{[(XSTART-XCENTER)/A]**2 + [(YSTART-YCENTER)/B]**2}
  1672. % **      must be < 512pt (about 7in).
  1673. % **    Doesn't modify the dimensions (ht, dp, wd) of the PiCture under
  1674. % **      construction.
  1675.  
  1676. % ** \circulararc  --  See Subsection 5.3 of the manual.
  1677. \def\circulararc{%
  1678.   \ellipticalarc axes ratio 1:1 }
  1679.  
  1680. % ** \ellipticalarc  --  See Subsection 5.3 of the manual.
  1681. \def\ellipticalarc axes ratio #1:#2 #3 degrees from #4 #5 center at #6 #7 {%
  1682.   \!angle=#3pt\relax%                    ** get angle
  1683.   \ifdim\!angle>\!zpt 
  1684.     \def\!sign{}%                        ** counterclockwise
  1685.   \else 
  1686.     \def\!sign{-}\!angle=-\!angle%       ** clockwise
  1687.   \fi
  1688.   \!xxloc=\!M{#6}\!xunit%                ** convert CENTER to dimension
  1689.   \!yyloc=\!M{#7}\!yunit     
  1690.   \!xxS=\!M{#4}\!xunit%                  ** get STARTing point on rim of ellipse
  1691.   \!yyS=\!M{#5}\!yunit
  1692.   \advance\!xxS -\!xxloc%                ** make center of ellipse (0,0)
  1693.   \advance\!yyS -\!yyloc
  1694.   \!divide\!xxS{#1pt}\!xxS %             ** scale point on ellipse to point on 
  1695.   \!divide\!yyS{#2pt}\!yyS %                 corresponding circle
  1696. %
  1697.   \let\!MC=\!M%                          ** save current c/d mode
  1698.   \!setdimenmode%                        ** go into dimension mode
  1699. %
  1700.   \!xS=#1\!xxS  \advance\!xS\!xxloc
  1701.   \!yS=#2\!yyS  \advance\!yS\!yyloc
  1702.   \!start (\!xS,\!yS)%
  1703.   \!loop\ifdim\!angle>14.9999pt%         ** draw in major portion of ellipse 
  1704.     \!rotate(\!xxS,\!yyS)by(\!cos,\!sign\!sin)to(\!xxM,\!yyM) 
  1705.     \!rotate(\!xxM,\!yyM)by(\!cos,\!sign\!sin)to(\!xxE,\!yyE)
  1706.     \!xM=#1\!xxM  \advance\!xM\!xxloc  \!yM=#2\!yyM  \advance\!yM\!yyloc
  1707.     \!xE=#1\!xxE  \advance\!xE\!xxloc  \!yE=#2\!yyE  \advance\!yE\!yyloc
  1708.     \!qjoin (\!xM,\!yM) (\!xE,\!yE)
  1709.     \!xxS=\!xxE  \!yyS=\!yyE 
  1710.     \advance \!angle -15pt
  1711.   \repeat
  1712.   \ifdim\!angle>\!zpt%                   ** complete remaining arc, if any
  1713.     \!angle=100.53096\!angle%            ** convert angle to radians, divide
  1714.     \divide \!angle 360 %                **   by 2, and multiply by 32
  1715.     \!sinandcos\!angle\!!sin\!!cos%      ** get 32*sin & 32*cos
  1716.     \!rotate(\!xxS,\!yyS)by(\!!cos,\!sign\!!sin)to(\!xxM,\!yyM) 
  1717.     \!rotate(\!xxM,\!yyM)by(\!!cos,\!sign\!!sin)to(\!xxE,\!yyE)
  1718.     \!xM=#1\!xxM  \advance\!xM\!xxloc  \!yM=#2\!yyM  \advance\!yM\!yyloc
  1719.     \!xE=#1\!xxE  \advance\!xE\!xxloc  \!yE=#2\!yyE  \advance\!yE\!yyloc
  1720.     \!qjoin (\!xM,\!yM) (\!xE,\!yE)
  1721.   \fi
  1722. %
  1723.   \let\!M=\!MC%                          ** restore c/d mode
  1724.   \ignorespaces}%                        **   if appropriate
  1725.  
  1726.  
  1727. %  ** \!rotate(XREG,YREG)by(32cos,32sin)to(XXREG,YYREG)
  1728. %  ** rotates (XREG,YREG) by angle with specfied scaled cos & sin to
  1729. %  ** (XXREG,YYREG).  Uses \!dimenA & \!dimenB as scratch registers.
  1730. \def\!rotate(#1,#2)by(#3,#4)to(#5,#6){% 
  1731.   \!dimenA=#3#1\advance \!dimenA -#4#2%   ** Rcos(x+t)=Rcosx*cost - Rsinx*sint
  1732.   \!dimenB=#3#2\advance \!dimenB  #4#1%   ** Rsin(x+t)=Rsinx*cost + Rcosx*sint
  1733.   \divide \!dimenA 32  \divide \!dimenB 32 
  1734.   #5=\!dimenA  #6=\!dimenB
  1735.   \ignorespaces}
  1736. \def\!sin{4.17684}%                       ** 32*sin(pi/24) (pi/24=7.5deg)
  1737. \def\!cos{31.72624}%                      ** 32*cos(pi/24)
  1738.  
  1739.  
  1740. %  ** \!sinandcos{32*ANGLE in radians}{\SINCS}{\COSCS}
  1741. %  **   Computes the 32*sine and 32*cosine of a small ANGLE expressed in 
  1742. %  **   radians/32 and puts these values in the replacement texts of 
  1743. %  **   \SINCS and \COSCS
  1744. \def\!sinandcos#1#2#3{%
  1745.  \!dimenD=#1%                **  angle is expressed in radians/32: 1pt = 1/32rad
  1746.  \!dimenA=\!dimenD%          **  dimA will eventually contain 32sin(angle)in pts
  1747.  \!dimenB=32pt%              **  dimB will eventually contain 32cos(angle)in pts
  1748.  \!removept\!dimenD\!value%  **  get value of 32*angle, without "pt"
  1749.  \!dimenC=\!dimenD%          **  holds 32*angle**i/i! in pts
  1750.  \!dimenC=\!value\!dimenC \divide\!dimenC by 64 %   ** now 32*angle**2/2
  1751.  \advance\!dimenB by -\!dimenC%                     ** 32-32*angle**2/2
  1752.  \!dimenC=\!value\!dimenC \divide\!dimenC by 96 %   ** now 32*angle**3/3!
  1753.  \advance\!dimenA by -\!dimenC%                     ** now 32*(angle-angle**3/6)
  1754.  \!dimenC=\!value\!dimenC \divide\!dimenC by 128 %  ** now 32*angle**4/4!
  1755.  \advance\!dimenB by \!dimenC%
  1756.  \!removept\!dimenA#2%                              ** set 32*sin(angle)
  1757.  \!removept\!dimenB#3%                              ** set 32*cos(angle)
  1758.  \ignorespaces}
  1759.  
  1760.  
  1761. % *****************************************************************
  1762. % ***  RULES  (Draws rules, i.e., horizontal & vertical lines)  ***
  1763. % *****************************************************************
  1764.  
  1765. % **  User command:
  1766. % **    \putrule [<XDIMEN,YDIMEN>] from  XCOORD1 YCOORD1 
  1767. % **      to  XCOORD2 YCOORD2 
  1768.  
  1769. % **  Internal commands:
  1770. % **    \!puthline [<XDIMEN,YDIMEN>]    (h = horizontal)
  1771. % **      Set by dashpat to either: \!putsolidhline  or \!putdashedhline
  1772. % **    \!putvline [<XDIMEN,YDIMEN>]    (v = vertical)
  1773. % **      Either:  \!putsolidvline  or  \!putdashedvline
  1774.  
  1775.  
  1776. % **  \putrule [<XDIMEN,YDIMEN>] from XCOORD1 YCOORD1
  1777. % **    to XCOORD2 YCOORD2
  1778. % **  Draws a rule -- dashed or solid depending on the current dash pattern --
  1779. % **    from (X1,Y1) to (X2,Y2).  Uses TEK's  \hrule & \vrule & \leaders  
  1780. % **    constructions to handle horizontal & vertical lines efficiently both
  1781. % **    in terms of execution time and space in the DVI file.  
  1782. % **  See Subsection 4.1 of the manual.
  1783. \def\putrule#1from #2 #3 to #4 #5 {%
  1784.   \!xloc=\!M{#2}\!xunit  \!xxloc=\!M{#4}\!xunit%   
  1785.   \!yloc=\!M{#3}\!yunit  \!yyloc=\!M{#5}\!yunit%           
  1786.   \!dxpos=\!xxloc  \advance\!dxpos by -\!xloc
  1787.   \!dypos=\!yyloc  \advance\!dypos by -\!yloc
  1788. %
  1789.   \ifdim\!dypos=\!zpt
  1790.     \def\!!Line{\!puthline{#1}}\ignorespaces
  1791.   \else
  1792.     \ifdim\!dxpos=\!zpt
  1793.       \def\!!Line{\!putvline{#1}}\ignorespaces
  1794.     \else 
  1795.        \def\!!Line{}
  1796.     \fi
  1797.   \fi
  1798.   \let\!ML=\!M%           ** save current coord\dimen mode
  1799.   \!setdimenmode%         ** express locations in dimens
  1800.   \!!Line%
  1801.   \let\!M=\!ML%           ** restore previous c/d mode
  1802.   \ignorespaces}
  1803.  
  1804.  
  1805. % **  \!putsolidhline [<XDIMEN,YDIMEN>]
  1806. % **  Place horizontal solid line
  1807. \def\!putsolidhline#1{%
  1808.   \ifdim\!dxpos>\!zpt 
  1809.     \put{\!hline\!dxpos}#1[l] at {\!xloc} {\!yloc}
  1810.   \else 
  1811.     \put{\!hline{-\!dxpos}}#1[l] at {\!xxloc} {\!yyloc}
  1812.   \fi
  1813.   \ignorespaces}
  1814.  
  1815. % **  \!putsolidvline [shifted <XDIMEN,YDIMEN>]
  1816. % **  Place vertical solid line
  1817. \def\!putsolidvline#1{%
  1818.   \ifdim\!dypos>\!zpt 
  1819.     \put{\!vline\!dypos}#1[b] at {\!xloc} {\!yloc}
  1820.   \else 
  1821.     \put{\!vline{-\!dypos}}#1[b] at {\!xxloc} {\!yyloc}
  1822.   \fi
  1823.   \ignorespaces}
  1824.  
  1825. \def\!hline#1{\hbox to #1{\leaders \hrule height\linethickness\hfill}}
  1826. \def\!vline#1{\vbox to #1{\leaders \vrule width\linethickness\vfill}}
  1827.  
  1828.  
  1829. % **  \!putdashedhline [<XDIMEN,YDIMEN>]
  1830. % **  Place dashed horizontal line
  1831. \def\!putdashedhline#1{%
  1832.   \ifdim\!dxpos>\!zpt 
  1833.     \!DLsetup\!Flist\!dxpos
  1834.     \put{\hbox to \!totalleaderlength{\!hleaders}\!hpartialpattern\!Rtrunc}
  1835.       #1[l] at {\!xloc} {\!yloc} 
  1836.   \else 
  1837.     \!DLsetup\!Blist{-\!dxpos}
  1838.     \put{\!hpartialpattern\!Ltrunc\hbox to \!totalleaderlength{\!hleaders}}
  1839.       #1[r] at {\!xloc} {\!yloc} 
  1840.   \fi
  1841.   \ignorespaces}
  1842.  
  1843. % **  \!putdashedhline [<XDIMEN,YDIMEN>]
  1844. % **  Place dashed vertical line
  1845. \def\!putdashedvline#1{%
  1846.   \!dypos=-\!dypos%            ** vertical leaders go from top to bottom
  1847.   \ifdim\!dypos>\!zpt 
  1848.     \!DLsetup\!Flist\!dypos 
  1849.     \put{\vbox{\vbox to \!totalleaderlength{\!vleaders}
  1850.       \!vpartialpattern\!Rtrunc}}#1[t] at {\!xloc} {\!yloc} 
  1851.   \else 
  1852.     \!DLsetup\!Blist{-\!dypos}
  1853.     \put{\vbox{\!vpartialpattern\!Ltrunc
  1854.       \vbox to \!totalleaderlength{\!vleaders}}}#1[b] at {\!xloc} {\!yloc} 
  1855.   \fi
  1856.   \ignorespaces}
  1857.  
  1858.  
  1859. % **  The rest of the macros in this section are subroutines used by 
  1860. % **  \!putdashedhline and \!putdashedvline.
  1861. \def\!DLsetup#1#2{%            ** Dashed-Line set up
  1862.   \let\!RSlist=#1%             ** set !Rule-Skip list
  1863.   \!countB=#2%                 ** convert rule length to integer (number of sps)
  1864.   \!countA=\!leaderlength%     ** ditto, leaderlength
  1865.   \divide\!countB by \!countA% ** number of complete leader units
  1866.   \!totalleaderlength=\!countB\!leaderlength
  1867.   \!Rresiduallength=#2%
  1868.   \advance \!Rresiduallength by -\!totalleaderlength%  \** excess length
  1869.   \!Lresiduallength=\!leaderlength
  1870.   \advance \!Lresiduallength by -\!Rresiduallength
  1871.   \ignorespaces}
  1872.  
  1873. \def\!hleaders{%
  1874.   \def\!Rule##1{\vrule height\linethickness width##1}%
  1875.   \def\!Skip##1{\hskip##1}%
  1876.   \leaders\hbox{\!RSlist}\hfill}
  1877.  
  1878. \def\!hpartialpattern#1{%
  1879.   \!dimenA=\!zpt \!dimenB=\!zpt 
  1880.   \def\!Rule##1{#1{##1}\vrule height\linethickness width\!dimenD}%
  1881.   \def\!Skip##1{#1{##1}\hskip\!dimenD}%
  1882.   \!RSlist}
  1883.  
  1884. \def\!vleaders{%
  1885.   \def\!Rule##1{\hrule width\linethickness height##1}%
  1886.   \def\!Skip##1{\vskip##1}%
  1887.   \leaders\vbox{\!RSlist}\vfill}
  1888.  
  1889. \def\!vpartialpattern#1{%
  1890.   \!dimenA=\!zpt \!dimenB=\!zpt 
  1891.   \def\!Rule##1{#1{##1}\hrule width\linethickness height\!dimenD}%
  1892.   \def\!Skip##1{#1{##1}\vskip\!dimenD}%
  1893.   \!RSlist}
  1894.  
  1895. \def\!Rtrunc#1{\!trunc{#1}>\!Rresiduallength}
  1896. \def\!Ltrunc#1{\!trunc{#1}<\!Lresiduallength}
  1897.  
  1898. \def\!trunc#1#2#3{%          
  1899.   \!dimenA=\!dimenB         
  1900.   \advance\!dimenB by #1%
  1901.   \!dimenD=\!dimenB  \ifdim\!dimenD#2#3\!dimenD=#3\fi
  1902.   \!dimenC=\!dimenA  \ifdim\!dimenC#2#3\!dimenC=#3\fi
  1903.   \advance \!dimenD by -\!dimenC}
  1904.  
  1905.  
  1906. %  ****************************************************************
  1907. %  ***  LINEAR ARC  (Draws straight lines -- solid and dashed)  ***
  1908. %  ****************************************************************
  1909.  
  1910. %  **  User commands
  1911. %  **    \inboundscheckoff
  1912. %  **    \inboundscheckon
  1913.    
  1914. %  **  Internal commands 
  1915. %  **    \!start (XCOORD,YCOORD)
  1916. %  **    \!ljoin (XCOORD,YCOORD)
  1917. %  **    \!drawlinearsegment  --  set by \dashpat to either
  1918. %  **      \!linearsolid  or  \!lineardashed
  1919. %  **    \!advancedashing     --  set by \dashpat to either
  1920. %  **       \relax  or  \!!advancedashing
  1921. %  **    \!plotifinbounds     --  set by \inboundscheck off/on to either
  1922. %  **       \!plot  or  \!!plotifinbounds
  1923. %  **    \!initinboundscheck  --  set by \inboundscheck off/on to either
  1924. %  **       \relax  or  \!!initinboundscheck
  1925.  
  1926.  
  1927. %  \plotsymbolspacing  ** distance between consecutive plot positions
  1928. %  \!xS                ** starting x
  1929. %  \!yS                ** starting y
  1930. %  \!xE                ** ending   x
  1931. %  \!yE                ** ending   y
  1932. %  \!xdiff             ** x_end - x_start
  1933. %  \!ydiff             ** y_end - y_start
  1934. %  \!distacross        ** how far along curve next point to be plotted is
  1935. %  \!arclength         ** approximate length of arc for current interval
  1936. %  \!downlength        ** remaining length for "pen" to be down    
  1937. %  \!uplength          ** length for "pen" to be down    
  1938. %  \!intervalno        ** counts segments to curve
  1939. %  \totalarclength     ** cumulative distance along curve
  1940. %  \!npoints           ** approximately  (arc length / plotsymbolspacing)
  1941.  
  1942. %  **  Calls -- \!Pythag, \!divide, \!plot
  1943.  
  1944.  
  1945. %  **  \!start (XCOORD,YCOORD)
  1946. %  **  Sets initial point for linearly (or quadratically) interpolated curve
  1947. \def\!start (#1,#2){%
  1948.   \!plotxorigin=\!xorigin  \advance \!plotxorigin by \!plotsymbolxshift
  1949.   \!plotyorigin=\!yorigin  \advance \!plotyorigin by \!plotsymbolyshift
  1950.   \!xS=\!M{#1}\!xunit \!yS=\!M{#2}\!yunit
  1951.   \!rotateaboutpivot\!xS\!yS
  1952.   \!copylist\!UDlist\to\!!UDlist% **\!UDlist has the form \\{dimen1}\\{dimen2}..
  1953. %                                 ** Routine will draw dashed line with pen
  1954. %                                 ** down for dimen1, up for dimen2, ...
  1955.   \!getnextvalueof\!downlength\from\!!UDlist
  1956.   \!distacross=\!zpt%             ** 1st point goes at start of curve
  1957.   \!intervalno=0 %                ** initialize interval counter
  1958.   \global\totalarclength=\!zpt%   ** initialize distance traveled along curve
  1959.   \ignorespaces}
  1960.  
  1961.  
  1962. %  **  \!ljoin (XCOORD,YCOORD) 
  1963. %  **  Draws a straight line starting at the last point specified
  1964. %  **    by the most recent \!start, \!ljoin, or \!qjoin, and
  1965. %  **    ending at (XCOORD,YCOORD).
  1966. \def\!ljoin (#1,#2){%
  1967.   \advance\!intervalno by 1
  1968.   \!xE=\!M{#1}\!xunit \!yE=\!M{#2}\!yunit
  1969.   \!rotateaboutpivot\!xE\!yE
  1970.   \!xdiff=\!xE \advance \!xdiff by -\!xS%**  xdiff = xE - xS
  1971.   \!ydiff=\!yE \advance \!ydiff by -\!yS%**  ydiff = yE - yS
  1972.   \!Pythag\!xdiff\!ydiff\!arclength%     **  arclength = sqrt(xdiff**2+ydiff**2) 
  1973.   \global\advance \totalarclength by \!arclength%
  1974.   \!drawlinearsegment%   ** set by dashpat to \!linearsolid or \!lineardashed
  1975.   \!xS=\!xE \!yS=\!yE%   ** shift ending points to starting points
  1976.   \ignorespaces}
  1977.  
  1978.  
  1979. % **  The following routine is used to draw a "solid" line between (xS,yS)
  1980. % **  and (xE,yE).  Points are spaced nearly every  \plotsymbolspacing length
  1981. % **  along the line.  
  1982. \def\!linearsolid{%
  1983.   \!npoints=\!arclength
  1984.   \!countA=\plotsymbolspacing
  1985.   \divide\!npoints by \!countA%      ** now #pts =. arclength/plotsymbolspacing
  1986.   \ifnum \!npoints<1 
  1987.     \!npoints=1 
  1988.   \fi
  1989.   \divide\!xdiff by \!npoints
  1990.   \divide\!ydiff by \!npoints
  1991.   \!xpos=\!xS \!ypos=\!yS
  1992. %
  1993.   \loop\ifnum\!npoints>-1
  1994.     \!plotifinbounds
  1995.     \advance \!xpos by \!xdiff
  1996.     \advance \!ypos by \!ydiff
  1997.     \advance \!npoints by -1
  1998.   \repeat
  1999.   \ignorespaces}
  2000.  
  2001.  
  2002. % ** The following routine is used to draw a dashed line between (xS,yS)
  2003. % ** and (xE,yE). The dash pattern continues from the previous segment.
  2004. \def\!lineardashed{%
  2005. % **
  2006.   \ifdim\!distacross>\!arclength
  2007.     \advance \!distacross by -\!arclength  %nothing to plot in this interval
  2008. %
  2009.   \else
  2010. %
  2011.     \loop\ifdim\!distacross<\!arclength
  2012. %     ** plot point, interpolating linearly in x and y
  2013.       \!divide\!distacross\!arclength\!dimenA%  ** dimA = across/arclength
  2014.       \!removept\!dimenA\!t%  ** \!t holds value in dimA, without the "pt"
  2015.       \!xpos=\!t\!xdiff \advance \!xpos by \!xS
  2016.       \!ypos=\!t\!ydiff \advance \!ypos by \!yS
  2017.       \!plotifinbounds
  2018.       \advance\!distacross by \plotsymbolspacing
  2019.       \!advancedashing
  2020.     \repeat  
  2021. %
  2022.     \advance \!distacross by -\!arclength%    ** prepare for next interval 
  2023.   \fi
  2024.   \ignorespaces}
  2025.  
  2026.  
  2027. \def\!!advancedashing{%
  2028.   \advance\!downlength by -\plotsymbolspacing
  2029.   \ifdim \!downlength>\!zpt
  2030.   \else
  2031.     \advance\!distacross by \!downlength
  2032.     \!getnextvalueof\!uplength\from\!!UDlist
  2033.     \advance\!distacross by \!uplength
  2034.     \!getnextvalueof\!downlength\from\!!UDlist
  2035.   \fi}
  2036.  
  2037.  
  2038. % ** \inboundscheckoff & \inboundscheckon: See Subsection 5.5 of the manual.
  2039. \def\inboundscheckoff{%
  2040.   \def\!plotifinbounds{\!plot(\!xpos,\!ypos)}%
  2041.   \def\!initinboundscheck{\relax}\ignorespaces}
  2042. \def\inboundscheckon{%
  2043.   \def\!plotifinbounds{\!!plotifinbounds}%
  2044.   \def\!initinboundscheck{\!!initinboundscheck}%
  2045.   \!initinboundscheck\ignorespaces} 
  2046. \inboundscheckoff
  2047.  
  2048. % ** The following code plots the current point only if it falls in the
  2049. % ** current plotarea.  It doesn't matter if the coordinate system has
  2050. % ** changed since the plotarea was set up.  However, shifts of the plot
  2051. % ** are ignored (how the plotsymbol stands relative to its plot position is
  2052. % ** unknown anyway).
  2053. \def\!!plotifinbounds{%
  2054.   \ifdim \!xpos<\!checkleft
  2055.   \else
  2056.     \ifdim \!xpos>\!checkright
  2057.     \else
  2058.       \ifdim \!ypos<\!checkbot
  2059.       \else
  2060.          \ifdim \!ypos>\!checktop
  2061.          \else
  2062.            \!plot(\!xpos,\!ypos)
  2063.          \fi 
  2064.       \fi
  2065.     \fi
  2066.   \fi}
  2067.  
  2068.  
  2069. \def\!!initinboundscheck{%
  2070.   \!checkleft=\!arealloc     \advance\!checkleft by \!xorigin
  2071.   \!checkright=\!arearloc    \advance\!checkright by \!xorigin
  2072.   \!checkbot=\!areabloc      \advance\!checkbot by \!yorigin
  2073.   \!checktop=\!areatloc      \advance\!checktop by \!yorigin}
  2074.  
  2075.  
  2076. % *********************************
  2077. % *** LOGTEN  (Log_10 function) ***
  2078. % *********************************
  2079. %
  2080. % ** \!logten{X}
  2081. % ** Calculates log_10 of X.  X and LOG10(X) are in fixed point notation.
  2082. % **  X must be positive; it may have an optional `+' sign; any number
  2083. % **  of digits may be specified for X.  The absolute error in LOG10(X) is
  2084. % **  less than .0001 (probably < .00006).  That's about as good as you
  2085. % **  hope for, since TEX only operates to 5 figures after the decimal
  2086. % **  point anyway.
  2087.  
  2088. %  \!rootten=3.162278pt       **** These are values are set in ALLOCATIONS
  2089. %  \!tenAe=2.543275pt  (=A5)
  2090. %  \!tenAc=2.773839pt  (=A3)
  2091. %  \!tenAa=8.690286pt  (=A1)
  2092.  
  2093. \def\!logten#1#2{%
  2094.   \expandafter\!!logten#1\!nil
  2095.   \!removept\!dimenF#2%
  2096.   \ignorespaces}
  2097.  
  2098. \def\!!logten#1#2\!nil{%
  2099.   \if -#1%
  2100.     \!dimenF=\!zpt
  2101.     \def\!next{\ignorespaces}%
  2102.   \else
  2103.     \if +#1%
  2104.       \def\!next{\!!logten#2\!nil}%
  2105.     \else
  2106.       \if .#1%
  2107.         \def\!next{\!!logten0.#2\!nil}%
  2108.       \else
  2109.         \def\!next{\!!!logten#1#2..\!nil}%
  2110.       \fi
  2111.     \fi
  2112.   \fi
  2113.   \!next}
  2114.  
  2115. \def\!!!logten#1#2.#3.#4\!nil{%
  2116.   \!dimenF=1pt %                 ** DimF holds log10 original argument
  2117.   \if 0#1%                      
  2118.     \!!logshift#3pt %            ** Argument < 1
  2119.   \else %                        ** Argument >= 1
  2120.     \!logshift#2/%               ** Shift decimal pt as many places
  2121.     \!dimenE=#1.#2#3pt %         **   as there are figures in #2
  2122.   \fi %                          ** Now dimE holds revised X want log10 of
  2123.   \ifdim \!dimenE<\!rootten%          ** Transform X to XX between sqrt(10) 
  2124.     \multiply \!dimenE 10 %           **   and 10*sqrt(10)
  2125.     \advance  \!dimenF -1pt
  2126.   \fi
  2127.   \!dimenG=\!dimenE%                  ** dimG <- (XX + 10)
  2128.     \advance\!dimenG 10pt
  2129.   \advance\!dimenE -10pt %            ** dimE <- (XX - 10)
  2130.   \multiply\!dimenE 10 %              ** dimE = 10*(XX-10)
  2131.   \!divide\!dimenE\!dimenG\!dimenE%   ** Now dimE=10t==10*(XX-10)/(XX+10)
  2132.   \!removept\!dimenE\!t%              ** !t=10t, with "pt" removed
  2133.   \!dimenG=\!t\!dimenE%               ** dimG=100t**2
  2134.   \!removept\!dimenG\!tt%             ** !tt=100t**2, with "pt" removed
  2135.   \!dimenH=\!tt\!tenAe%               ** dimH=10*a5*(10t)**2 /100
  2136.     \divide\!dimenH 100
  2137.   \advance\!dimenH \!tenAc%           ** ditto + 10*a3
  2138.   \!dimenH=\!tt\!dimenH%              ** ditto * (10t)**2 /100
  2139.     \divide\!dimenH 100   
  2140.   \advance\!dimenH \!tenAa%           ** ditto + 10*a1
  2141.   \!dimenH=\!t\!dimenH%               ** ditto * 10t / 100
  2142.     \divide\!dimenH 100 %             ** Now dimH = log10(XX) - 1
  2143.   \advance\!dimenF \!dimenH}%         ** dimF = log10(X)
  2144.  
  2145. \def\!logshift#1{%
  2146.   \if #1/%
  2147.     \def\!next{\ignorespaces}%
  2148.   \else
  2149.     \advance\!dimenF 1pt 
  2150.     \def\!next{\!logshift}%
  2151.   \fi 
  2152.   \!next}
  2153.  
  2154.  \def\!!logshift#1{%
  2155.    \advance\!dimenF -1pt
  2156.    \if 0#1%
  2157.      \def\!next{\!!logshift}%
  2158.    \else
  2159.      \if p#1%
  2160.        \!dimenF=1pt
  2161.        \def\!next{\!dimenE=1p}%
  2162.      \else
  2163.        \def\!next{\!dimenE=#1.}%
  2164.      \fi
  2165.    \fi
  2166.    \!next}
  2167.  
  2168.  
  2169. % ***********************************************************
  2170. % *** PICTURES (Basic setups for PiCtures; \put commands) ***
  2171. % ***********************************************************
  2172.  
  2173. % **  User Commands:
  2174. % **    \beginpicture
  2175. % **    \endpicture    
  2176. % **    \endpicturesave <XREG,YREG>
  2177. % **    \setcoordinatesystem units <XUNIT,YUNIT> point at XREF YREF
  2178. % **    \put {OBJECT} [ORIENTATION] <XSHIFT,YSHIFT> at XCOORD YCOORD
  2179. % **    \multiput {OJBECT} [ORIENTATION] <XSHIFT,YSHIFT>) at
  2180. % **      XCOORD YCOORD
  2181. % **      *NUMBER_OF_TIMES DXCOORD DYCOORD  /
  2182. % **    \accountingon
  2183. % **    \accountingoff
  2184. % **    \stack [ORIENTATION] <LEADING> {LIST OF ITEMS}
  2185. % **    \lines [ORIENTATION] {LINES}
  2186. % **    \Lines [ORIENTATION] {LINES}
  2187. % **    \setdimensionmode
  2188. % **    \setcoordinatemode
  2189. % **    \Xdistance
  2190. % **    \Ydistance
  2191.   
  2192. % **  Internal commands:
  2193. % **    \!setputobject{OBJECT}{[ORIENTATION]<XSHIFT,YSHIFT>}
  2194. % **    \!dimenput{OBJECT}[ORIENTATION]<XSHIFT,YSHIFT>(XDIMEN,YDIMEN)
  2195. % **    \!setdimenmode
  2196. % **    \!setcoordmode
  2197. % **    \!ifdimenmode
  2198. % **    \!ifcoordmode
  2199.   
  2200.  
  2201. % **  \beginpicture
  2202. % **  \endpicture
  2203. % **  \endpicturesave <XREG,YREG>
  2204. % **    \beginpicture ... \endpicture  creates an hbox.  Objects are
  2205. % **    placed in this box using the \put command and the like (see below).
  2206. % **    The location of an object is specified in terms of coordinate system(s)
  2207. % **    established by \setcoordinatesystem.  Each coordinate system (there
  2208. % **    might be just one) specifies the length of 1 horizontal unit, the length
  2209. % **    of 1 vertical unit, and the coordinates of a "reference point".  The
  2210. % **    reference points of various coordinate systems will be in the same
  2211. % **    physical location.  The macros keep track of the size of the objects
  2212. % **    and their locations. The resulting hbox is the smallest hbox which
  2213. % **    encloses all the objects, and whose TEK reference point is the point
  2214. % **    on the left edge of the box closest vertically to the PICTEX reference
  2215. % **    point. Using \endpicturesave, you can (globally) save the distance TEK's
  2216. % **    reference point is to the right (respectively, up from) PICTEX's 
  2217. % **    reference point in the dimension register \XREG (respectively \YREG). 
  2218. % **    You can then \put the picture OBJECT into a larger picture so that its
  2219. % **    reference point is at (XCOORD,YCOORD) with the command
  2220. % **      \put {picture OBJECT} [Bl] <\XREG, \YREG> at  XCOORD YCOORD 
  2221.  
  2222. % **  \beginpicture : See Subsection 1.1 of the manual.
  2223. \def\beginpicture{%
  2224.   \setbox\!picbox=\hbox\bgroup%
  2225.   \!xleft=\maxdimen  
  2226.   \!xright=-\maxdimen
  2227.   \!ybot=\maxdimen
  2228.   \!ytop=-\maxdimen}
  2229.  
  2230. % **  \endpicture : See Subsection 1.1 of the manual.
  2231. \def\endpicture{%
  2232.   \ifdim\!xleft=\maxdimen%  ** check if nothing was put in picbox
  2233.     \!xleft=\!zpt \!xright=\!zpt \!ybot=\!zpt \!ytop=\!zpt 
  2234.   \fi
  2235.   \global\!Xleft=\!xleft \global\!Xright=\!xright
  2236.   \global\!Ybot=\!ybot \global\!Ytop=\!ytop
  2237.   \egroup%
  2238.   \ht\!picbox=\!Ytop  \dp\!picbox=-\!Ybot
  2239.   \ifdim\!Ybot>\!zpt
  2240.   \else 
  2241.     \ifdim\!Ytop<\!zpt
  2242.       \!Ybot=\!Ytop
  2243.     \else
  2244.       \!Ybot=\!zpt
  2245.     \fi
  2246.   \fi
  2247.   \hbox{\kern-\!Xleft\lower\!Ybot\box\!picbox\kern\!Xright}}
  2248.  
  2249. % **  \endpicturesave : See Subsection 8.4 of the manual.
  2250. \def\endpicturesave <#1,#2>{%
  2251.   \endpicture \global #1=\!Xleft \global #2=\!Ybot \ignorespaces}
  2252.  
  2253.  
  2254. % **   \setcoordinatesystem units <XUNIT,YUNIT> 
  2255. % **     point at XREF YREF  
  2256. % **   Each of `units <XUNIT,YUNIT>' and `point at XREF YREF' 
  2257. % **     are optional.
  2258. % **   Unit lengths must be given in dimensions (e.g., <10pt,1in>).
  2259. % **     Default unit lengths are 1pt, 1pt, or previous unit lengths.
  2260. % **   Reference point is specified in current units (e.g., 3 5 ). 
  2261. % **     Default reference point is 0 0 , or previous reference point.
  2262. % **   Unit lengths and reference points obey TEX's scoping rules.
  2263. % **   See Subsection 1.2 of the manual.
  2264. \def\setcoordinatesystem{%
  2265.   \!ifnextchar{u}{\!getlengths }
  2266.     {\!getlengths units <\!xunit,\!yunit>}}
  2267. \def\!getlengths units <#1,#2>{%
  2268.   \!xunit=#1\relax
  2269.   \!yunit=#2\relax
  2270.   \!ifcoordmode 
  2271.     \let\!SCnext=\!SCccheckforRP
  2272.   \else
  2273.     \let\!SCnext=\!SCdcheckforRP
  2274.   \fi
  2275.   \!SCnext}
  2276. \def\!SCccheckforRP{%
  2277.   \!ifnextchar{p}{\!cgetreference }
  2278.     {\!cgetreference point at {\!xref} {\!yref} }}
  2279. \def\!cgetreference point at #1 #2 {%
  2280.   \edef\!xref{#1}\edef\!yref{#2}%
  2281.   \!xorigin=\!xref\!xunit  \!yorigin=\!yref\!yunit  
  2282.   \!initinboundscheck % ** See linear.tex
  2283.   \ignorespaces}
  2284. \def\!SCdcheckforRP{%
  2285.   \!ifnextchar{p}{\!dgetreference}%
  2286.     {\ignorespaces}}
  2287. \def\!dgetreference point at #1 #2 {%
  2288.   \!xorigin=#1\relax  \!yorigin=#2\relax
  2289.   \ignorespaces}
  2290.  
  2291.  
  2292. %  ** \put {OBJECT} [XY] <XDIMEN,YDIMEN> at (XCOORD,YCOORD)
  2293. %  **   `[XY]' and `<XDIMEN,YDIMEN>' are optional.
  2294. %  **   First OBJECT is placed in an hbox (the "objectbox") and then a
  2295. %  **     "reference point" is assigned to the objectbox as follows:
  2296. %  **     [1] first, the reference point is taken to be the center of the box;
  2297. %  **     [2] next, centering is overridden by the specifications
  2298. %  **           X=l -- reference point along the left edge of the objectbox
  2299. %  **           X=r -- reference point along the right edge of the objectbox
  2300. %  **           Y=b -- reference point along the bottom edge of the objectbox
  2301. %  **           Y=B -- reference point along the Baseline of the objectbox
  2302. %  **           Y=t -- reference point along the top edge of the objectbox;
  2303. %  **     [3] finally the reference point is shifted left by XDIMEN, down
  2304. %  **           by YDIMEN  (both default to 0pt).
  2305. %  **   The objectbox is placed within PICBOX with its reference point at  
  2306. %  **     (XCOORD,YCOORD). 
  2307. %  **   If OBJECT is a saved box, say  box0, you have to write
  2308. %  **     \put{\box0}...   or  \put{\copy0}...
  2309. %  **   The objectbox is void after the put.
  2310. %  **   See Subsection 2.1 of the manual.
  2311. \long\def\put#1#2 at #3 #4 {%
  2312.   \!setputobject{#1}{#2}%
  2313.   \!xpos=\!M{#3}\!xunit  \!ypos=\!M{#4}\!yunit  
  2314.   \!rotateaboutpivot\!xpos\!ypos%
  2315.   \advance\!xpos -\!xorigin  \advance\!xpos -\!xshift
  2316.   \advance\!ypos -\!yorigin  \advance\!ypos -\!yshift
  2317.   \kern\!xpos\raise\!ypos\box\!putobject\kern-\!xpos%
  2318.   \!doaccounting\ignorespaces}
  2319.  
  2320. %  **   \multiput etc.  Like  \put.  The objectbox is not voided until the
  2321. %  **     termininating /, and is placed repeatedly with:
  2322. %  **     XCOORD YCOORD -- the objectbox is put down with its reference point
  2323. %  **       at (XCOORD,YCOORD);
  2324. %  **     *N DXCOORD DYCOORD -- each of N times the current
  2325. %  **       (xcoord,ycoord) is incremented by (DXCOORD,DYCOORD), and the
  2326. %  **       objectbox is put down with its reference point at (xcoord,ycoord)
  2327. %  **       (This specification has to follow an XCOORD YCOORD pair)
  2328. %  **     See Subsection 2.2 of the manual.
  2329. \long\def\multiput #1#2 at {%
  2330.   \!setputobject{#1}{#2}%
  2331.   \!ifnextchar"{\!putfromfile}{\!multiput}}
  2332. \def\!putfromfile"#1"{%
  2333.   \expandafter\!multiput \input #1 /}
  2334. \def\!multiput{%
  2335.   \futurelet\!nextchar\!!multiput}
  2336. \def\!!multiput{%
  2337.   \if *\!nextchar
  2338.     \def\!nextput{\!alsoby}%
  2339.   \else
  2340.     \if /\!nextchar
  2341.       \def\!nextput{\!finishmultiput}%
  2342.     \else
  2343.       \def\!nextput{\!alsoat}%
  2344.     \fi
  2345.   \fi
  2346.   \!nextput}
  2347. \def\!finishmultiput/{%
  2348.   \setbox\!putobject=\hbox{}%
  2349.   \ignorespaces}
  2350.  
  2351. %  **   \!alsoat XCOORD YCOORD 
  2352. %  **     The objectbox is put down with reference point at XCOORD,YCOORD
  2353. \def\!alsoat#1 #2 {%
  2354.   \!xpos=\!M{#1}\!xunit  \!ypos=\!M{#2}\!yunit  
  2355.   \!rotateaboutpivot\!xpos\!ypos%
  2356.   \advance\!xpos -\!xorigin  \advance\!xpos -\!xshift
  2357.   \advance\!ypos -\!yorigin  \advance\!ypos -\!yshift
  2358.   \kern\!xpos\raise\!ypos\copy\!putobject\kern-\!xpos%
  2359.   \!doaccounting
  2360.   \!multiput}
  2361.  
  2362. % **   \!alsoby*N DXCOORD DYCOORD
  2363. % **     N times, the current (XCOORD,YCOORD) is advanced by (DXCOORD,DYCOORD),
  2364. % **     and the current (shifted, oriented) OBJECT is put down.
  2365. \def\!alsoby*#1 #2 #3 {%
  2366.   \!dxpos=\!M{#2}\!xunit \!dypos=\!M{#3}\!yunit 
  2367.   \!rotateonly\!dxpos\!dypos
  2368.   \!ntemp=#1%
  2369.   \!!loop\ifnum\!ntemp>0
  2370.     \advance\!xpos by \!dxpos  \advance\!ypos by \!dypos
  2371.     \kern\!xpos\raise\!ypos\copy\!putobject\kern-\!xpos%
  2372.     \advance\!ntemp by -1
  2373.   \repeat
  2374.   \!doaccounting 
  2375.   \!multiput}
  2376.  
  2377. % **  \accountingoff : Suspends PiCTeX's accounting of the aggregate
  2378. % **    size of the picture box.
  2379. % **  \accounting on : Reinstates accounting.
  2380. % **  See Subsection 8.2 of the manual.
  2381. \def\accountingon{\def\!doaccounting{\!!doaccounting}\ignorespaces}
  2382. \def\accountingoff{\def\!doaccounting{}\ignorespaces}
  2383. \accountingon
  2384. \def\!!doaccounting{%
  2385.   \!xtemp=\!xpos  
  2386.   \!ytemp=\!ypos
  2387.   \ifdim\!xtemp<\!xleft 
  2388.      \!xleft=\!xtemp 
  2389.   \fi
  2390.   \advance\!xtemp by  \!wd 
  2391.   \ifdim\!xright<\!xtemp 
  2392.     \!xright=\!xtemp
  2393.   \fi
  2394.   \advance\!ytemp by -\!dp
  2395.   \ifdim\!ytemp<\!ybot  
  2396.     \!ybot=\!ytemp
  2397.   \fi
  2398.   \advance\!ytemp by  \!dp
  2399.   \advance\!ytemp by  \!ht 
  2400.   \ifdim\!ytemp>\!ytop  
  2401.     \!ytop=\!ytemp  
  2402.   \fi}
  2403.  
  2404. \long\def\!setputobject#1#2{%
  2405.   \setbox\!putobject=\hbox{#1}%
  2406.   \!ht=\ht\!putobject  \!dp=\dp\!putobject  \!wd=\wd\!putobject
  2407.   \wd\!putobject=\!zpt
  2408.   \!xshift=.5\!wd   \!yshift=.5\!ht   \advance\!yshift by -.5\!dp
  2409.   \edef\!putorientation{#2}%
  2410.   \expandafter\!SPOreadA\!putorientation[]\!nil%
  2411.   \expandafter\!SPOreadB\!putorientation<\!zpt,\!zpt>\!nil\ignorespaces}
  2412.  
  2413. \def\!SPOreadA#1[#2]#3\!nil{\!etfor\!orientation:=#2\do\!SPOreviseshift}
  2414.  
  2415. \def\!SPOreadB#1<#2,#3>#4\!nil{\advance\!xshift by -#2\advance\!yshift by -#3}
  2416.  
  2417. \def\!SPOreviseshift{%
  2418.   \if l\!orientation 
  2419.     \!xshift=\!zpt
  2420.   \else 
  2421.     \if r\!orientation 
  2422.       \!xshift=\!wd
  2423.     \else 
  2424.       \if b\!orientation
  2425.         \!yshift=-\!dp
  2426.       \else 
  2427.         \if B\!orientation 
  2428.           \!yshift=\!zpt
  2429.         \else 
  2430.           \if t\!orientation 
  2431.             \!yshift=\!ht
  2432.           \fi 
  2433.         \fi
  2434.       \fi
  2435.     \fi
  2436.   \fi}
  2437.  
  2438.  
  2439. %  **  \!dimenput{OBJECT} <XDIMEN,YDIMEN> [XY] (XLOC,YLOC)
  2440. %  **    This is an internal put routine, similar to \put, except that
  2441. %  **    XLOC=distance right from reference point, YLOC=distance up from
  2442. %  **    reference point. XLOC and YLOC are dimensions, so this routine
  2443. %  **    is completely independent of the current coordinate system. 
  2444. %  **    This routine does NOT do ROTATIONS.
  2445. \long\def\!dimenput#1#2(#3,#4){%
  2446.   \!setputobject{#1}{#2}%
  2447.   \!xpos=#3\advance\!xpos by -\!xshift
  2448.   \!ypos=#4\advance\!ypos by -\!yshift
  2449.   \kern\!xpos\raise\!ypos\box\!putobject\kern-\!xpos%
  2450.   \!doaccounting\ignorespaces}
  2451.  
  2452.  
  2453. %  ** The following macros permit the picture drawing routines to be used 
  2454. %  ** either in the default "coordinate mode", or in "dimension mode".
  2455. %  **   In coordinate mode  \!M(1.5,\!xunit)    expands to  1.5\!xunit
  2456. %  **   In dimension  mode  \!M(1.5pt,\!xunit)  expands to  1.5pt
  2457. %  ** Dimension mode is useful in coding macros.
  2458. %  ** Any special purpose picture macro that sets dimension mode should 
  2459. %  ** reset coordinate mode before completion.
  2460. %  ** See Subsection 9.2 of the manual.
  2461. \def\!setdimenmode{%
  2462.   \let\!M=\!M!!\ignorespaces}
  2463. \def\!setcoordmode{%
  2464.   \let\!M=\!M!\ignorespaces}
  2465. \def\!ifcoordmode{%
  2466.   \ifx \!M \!M!}
  2467. \def\!ifdimenmode{%
  2468.   \ifx \!M \!M!!}
  2469. \def\!M!#1#2{#1#2} 
  2470. \def\!M!!#1#2{#1}
  2471. \!setcoordmode
  2472. \let\setdimensionmode=\!setdimenmode
  2473. \let\setcoordinatemode=\!setcoordmode
  2474.  
  2475. %  ** \Xdistance{XCOORD}, \Ydistance{YCOORD}  are the horizontal and
  2476. %  **   vertical distances from the origin (0,0) to the point
  2477. %  **   (XCOORD,YCOORD)  in the current coordinate system.
  2478. %  ** See Subsection 9.2 of the manual.
  2479. \def\Xdistance#1{%
  2480.   \!M{#1}\!xunit
  2481.   \ignorespaces}
  2482. \def\Ydistance#1{%
  2483.   \!M{#1}\!yunit
  2484.   \ignorespaces}
  2485.  
  2486. % ** The following macros -- \stack, \line, and \Lines -- are useful for
  2487. % **   annotating PiCtures. They can be used outside the \beginpicture ...
  2488. % **   \endpicture environment.
  2489.  
  2490. % ** \stack [POSITIONING] <LEADING> {VALUESLIST}
  2491. % ** Builds a vertical stack of the values in VALUESLIST. Values in
  2492. % ** VALUESLIST are separated by commas.  In the resulting stack, values are
  2493. % ** centered by default, and positioned flush left (right) if 
  2494. % ** POSITIONING = l (r).  Values are separated vertically by LEADING,
  2495. % ** which defaults to \stackleading.
  2496. % ** See Subsection 2.3 of the manual.
  2497. \def\stack{%
  2498.   \!ifnextchar[{\!stack}{\!stack[c]}}
  2499. \def\!stack[#1]{%
  2500.   \let\!lglue=\hfill \let\!rglue=\hfill
  2501.   \expandafter\let\csname !#1glue\endcsname=\relax
  2502.   \!ifnextchar<{\!!stack}{\!!stack<\stackleading>}}
  2503. \def\!!stack<#1>#2{%
  2504.   \vbox{\def\!valueslist{}\!ecfor\!value:=#2\do{%
  2505.     \expandafter\!rightappend\!value\withCS{\\}\to\!valueslist}%
  2506.     \!lop\!valueslist\to\!value
  2507.     \let\\=\cr\lineskiplimit=\maxdimen\lineskip=#1%
  2508.     \baselineskip=-1000pt\halign{\!lglue##\!rglue\cr \!value\!valueslist\cr}}%
  2509.   \ignorespaces}
  2510.  
  2511. % ** \lines [POSITIONING] {LINES}
  2512. % ** Builds a vertical array of the lines in LINES. Each line in LINES
  2513. % ** is terminated by a \cr.  In the resulting array, lines are
  2514. % ** centered by default, and positioned flush left (right) if 
  2515. % ** POSITIONING = l (r).  The lines in the array are subject to TeX's
  2516. % ** usual spacing rules: in particular the baselines are ordinarily an equal
  2517. % ** distance apart. The baseline of the array is the baseline of the
  2518. % ** the bottom line.
  2519. % ** See Subsection 2.3 of the manual.
  2520. \def\lines{%
  2521.   \!ifnextchar[{\!lines}{\!lines[c]}}
  2522. \def\!lines[#1]#2{%
  2523.   \let\!lglue=\hfill \let\!rglue=\hfill
  2524.   \expandafter\let\csname !#1glue\endcsname=\relax
  2525.   \vbox{\halign{\!lglue##\!rglue\cr #2\crcr}}%
  2526.   \ignorespaces}
  2527.  
  2528. % ** \Lines [POSITIONING] {LINES}
  2529. % ** Like \lines, but the baseline of the array is the baseline of the
  2530. % ** top line.  See Subsection 2.3 of the manual.
  2531. \def\Lines{%
  2532.   \!ifnextchar[{\!Lines}{\!Lines[c]}}
  2533. \def\!Lines[#1]#2{%
  2534.   \let\!lglue=\hfill \let\!rglue=\hfill
  2535.   \expandafter\let\csname !#1glue\endcsname=\relax
  2536.   \vtop{\halign{\!lglue##\!rglue\cr #2\crcr}}%
  2537.   \ignorespaces}
  2538.  
  2539.  
  2540. % *********************************************
  2541. % *** PLOTTING (Things to do with plotting) ***
  2542. % *********************************************
  2543.  
  2544. % **  User commands
  2545. % **    \setplotsymbol ({PLOTSYMBOL} [ORIENTATION] <XSHIFT,YSHIFT>)
  2546. % **    \savelinesandcurves on "FILE_NAME"
  2547. % **    \dontsavelinesandcurves
  2548. % **    \writesavefile {MESSAGE}
  2549. % **    \replot {FILE_NAME}
  2550.  
  2551. % **  Internal command
  2552. % **    \!plot(XDIMEN,YDIMEN)
  2553.  
  2554. % **  \setplotsymbol ({PLOTSYMBOL} [ ] < , >)
  2555. % **  Save PLOTSYMBOL away in an hbox for use with curve plotting routines
  2556. % **  See Subsection 5.2 of the manual.
  2557. \def\setplotsymbol(#1#2){%
  2558.   \!setputobject{#1}{#2}
  2559.   \setbox\!plotsymbol=\box\!putobject%
  2560.   \!plotsymbolxshift=\!xshift 
  2561.   \!plotsymbolyshift=\!yshift 
  2562.   \ignorespaces}
  2563.  
  2564. \setplotsymbol({\fiverm .})%       ** initialize plotsymbol
  2565.  
  2566.  
  2567. % **  \!plot is either \!!plot (when no lines and curves are being saved) or
  2568. % **                   \!!!plot (when   lines and curves are being saved)
  2569.  
  2570. % **  \!!plot(XDIMEN,YDIMEN)
  2571. % **  Places the current plotsymbol a horizontal distance=XDIMEN-xorigin 
  2572. % **    and a vertical distance=YDIMEN-yorigin from the current
  2573. % **    reference point.  
  2574. \def\!!plot(#1,#2){%
  2575.   \!dimenA=-\!plotxorigin \advance \!dimenA by #1%    ** over
  2576.   \!dimenB=-\!plotyorigin \advance \!dimenB by #2%    ** up
  2577.   \kern\!dimenA\raise\!dimenB\copy\!plotsymbol\kern-\!dimenA%
  2578.   \ignorespaces}
  2579.  
  2580. % **  \!!!plot(XDIMEN,YDIMEN)
  2581. % **  Like \!!plot, but also saves the plot location in units of 
  2582. % **    scaled point, on file `replotfile'
  2583. \def\!!!plot(#1,#2){%
  2584.   \!dimenA=-\!plotxorigin \advance \!dimenA by #1%    ** over
  2585.   \!dimenB=-\!plotyorigin \advance \!dimenB by #2%    ** up
  2586.   \kern\!dimenA\raise\!dimenB\copy\!plotsymbol\kern-\!dimenA%
  2587.   \!countE=\!dimenA
  2588.   \!countF=\!dimenB
  2589.   \immediate\write\!replotfile{\the\!countE,\the\!countF.}%
  2590.   \ignorespaces}
  2591.  
  2592.  
  2593. % ** \savelinesandcurves on "FILE_NAME"
  2594. % **   Switch to save locations used for plotting lines and curves
  2595. % **   (No advantage in saving locations for solid lines; however
  2596. % **   replotting curve locations speeds things up by a factor of about 4. 
  2597. % ** \dontsavelinesandcurves
  2598. % **   Terminates \savelinesandcurves. The default.
  2599. % ** See Subsection 5.6 of the manual.
  2600. \def\savelinesandcurves on "#1" {%
  2601.   \immediate\closeout\!replotfile
  2602.   \immediate\openout\!replotfile=#1%
  2603.   \let\!plot=\!!!plot}
  2604.  
  2605. \def\dontsavelinesandcurves {%
  2606.   \let\!plot=\!!plot}
  2607. \dontsavelinesandcurves
  2608.  
  2609. % ** \writesavefile {MESSAGE}
  2610. % ** The message is preceded by a "%", so that it won't interfere
  2611. % ** with replotting.
  2612. % ** See Subsection 5.6 of the manual.
  2613. {\catcode`\%=11\xdef\!Commentsignal{%}}
  2614. \def\writesavefile#1 {%
  2615.   \immediate\write\!replotfile{\!Commentsignal #1}%
  2616.   \ignorespaces}
  2617.  
  2618. % ** \replot "FILE_NAME"
  2619. % **   Replots the locations saved earlier under \savelinesandcurves
  2620. % **   on "FILE_NAME"
  2621. % ** See Subsection 5.6 of the manual.
  2622. \def\replot"#1" {%
  2623.   \expandafter\!replot\input #1 /}
  2624. \def\!replot#1,#2. {%
  2625.   \!dimenA=#1sp
  2626.   \kern\!dimenA\raise#2sp\copy\!plotsymbol\kern-\!dimenA
  2627.   \futurelet\!nextchar\!!replot}
  2628. \def\!!replot{%
  2629.   \if /\!nextchar 
  2630.     \def\!next{\!finish}%
  2631.   \else
  2632.     \def\!next{\!replot}%
  2633.   \fi
  2634.   \!next}
  2635. % **************************************************
  2636. % ***  PYTHAGORAS  (Euclidean distance function) ***
  2637. % **************************************************
  2638.  
  2639. % ** User command:
  2640. % **   \placehypotenuse for <dimension1> and <dimension2> in <register> 
  2641.  
  2642. % ** Internal command:
  2643. % **   \!Pythag{X}{Y}{Z}
  2644. % **     Input X,Y are dimensions, or dimension registers.
  2645. % **     Output Z == sqrt(X**2+Y**2) must be a dimension register.
  2646. % **     Assumes that |X|+|Y| < 2048pt (about 28in).
  2647.  
  2648. % ** Without loss of generality, suppose  x>0, y>0.  Put s = x+y,
  2649. % **   z = sqrt(x**2+y**2). Then  z = s*f,  where  f = sqrt(t**2 + (1-t)**2)
  2650. % **   = sqrt((1+tau**2)/2), where  t = x/s  and  tau = 2(t-1/2) .
  2651.  
  2652. % ** Uses the \!divide macro (which uses registers \!dimenA--\!dimenD.
  2653. % ** Uses the \!removept macro   (e.g., 123.45pt --> 123.45)
  2654. % ** Uses registers \!dimenE--\!dimenI.
  2655. \def\!Pythag#1#2#3{%
  2656.   \!dimenE=#1\relax                                     
  2657.   \ifdim\!dimenE<\!zpt 
  2658.     \!dimenE=-\!dimenE 
  2659.   \fi%                                            ** dimE = |x|
  2660.   \!dimenF=#2\relax
  2661.   \ifdim\!dimenF<\!zpt 
  2662.     \!dimenF=-\!dimenF 
  2663.   \fi%                                            ** dimF = |y|
  2664.   \advance \!dimenF by \!dimenE%                  ** dimF = s = |x|+|y|
  2665.   \ifdim\!dimenF=\!zpt 
  2666.     \!dimenG=\!zpt%                               ** dimG = z = sqrt(x**2+y**2)
  2667.   \else 
  2668.     \!divide{8\!dimenE}\!dimenF\!dimenE%          ** now dimE = 8t = (8|x|)/s
  2669.     \advance\!dimenE by -4pt%                     ** 8tau = (8t-4)*2
  2670.       \!dimenE=2\!dimenE%                         **   (tau = 2*t - 1)
  2671.     \!removept\!dimenE\!!t%                       ** 8tau, without "pt"
  2672.     \!dimenE=\!!t\!dimenE%                        ** (8tau)**2, in pts
  2673.     \advance\!dimenE by 64pt%                     ** u = [64 + (8tau)**2]/2
  2674.     \divide \!dimenE by 2%                        **   [u = (8f)**2]
  2675.     \!dimenH=7pt%                                 ** initial guess g at sqrt(u)
  2676.     \!!Pythag\!!Pythag\!!Pythag%                  ** 3 iterations give sqrt(u)
  2677.     \!removept\!dimenH\!!t%                       ** 8f=sqrt(u), without "pt"
  2678.     \!dimenG=\!!t\!dimenF%                        ** z = (8f)*s/8
  2679.     \divide\!dimenG by 8
  2680.   \fi
  2681.   #3=\!dimenG
  2682.   \ignorespaces}
  2683.  
  2684. \def\!!Pythag{%                                   ** Newton-Raphson for sqrt
  2685.   \!divide\!dimenE\!dimenH\!dimenI%               ** v = u/g
  2686.   \advance\!dimenH by \!dimenI%                   ** g <-- (g + u/g)/2
  2687.     \divide\!dimenH by 2}
  2688.  
  2689. % **  \placehypotenuse for <XI> and <ETA> in <ZETA>
  2690. % **  See Subsection 9.3 of the manual.
  2691. \def\placehypotenuse for <#1> and <#2> in <#3> {%
  2692.   \!Pythag{#1}{#2}{#3}}
  2693.  
  2694.  
  2695. % **********************************************
  2696. % *** QUADRATIC ARC  (Draws a quadratic arc) ***
  2697. % **********************************************
  2698.  
  2699. % **  Internal command
  2700. % **    \!qjoin (XCOORD1,YCOORD1) (XCOORD2,YCOORD2)
  2701.  
  2702. % **  \!qjoin (XCOORD1,YCOORD1) (XCOORD2,YCOORD2)
  2703. % **  Draws an arc starting at the (last) point specified by the most recent
  2704. % **  \!qjoin, or \!ljoin, or \!start  and passing through (X_1,Y_1), (X_2,Y_2).
  2705. % **  Uses quadratic interpolation in both  x  and  y:  
  2706. % **    x(t), 0 <= t <= 1, interpolates  x_0, x_1, x_2  at  t=0, .5, 1
  2707. % **    y(t), 0 <= t <= 1, interpolates  y_0, y_1, y_2  at  t=0, .5, 1
  2708.  
  2709. \def\!qjoin (#1,#2) (#3,#4){%
  2710.   \advance\!intervalno by 1
  2711.   \!ifcoordmode
  2712.     \edef\!xmidpt{#1}\edef\!ymidpt{#2}%
  2713.   \else
  2714.     \!dimenA=#1\relax \edef\!xmidpt{\the\!dimenA}%
  2715.     \!dimenA=#2\relax \edef\!xmidpt{\the\!dimenA}%
  2716.   \fi
  2717.   \!xM=\!M{#1}\!xunit  \!yM=\!M{#2}\!yunit   \!rotateaboutpivot\!xM\!yM
  2718.   \!xE=\!M{#3}\!xunit  \!yE=\!M{#4}\!yunit   \!rotateaboutpivot\!xE\!yE
  2719. %
  2720. % ** Find coefficients for x(t)=a_x + b_x*t + c_x*t**2
  2721.   \!dimenA=\!xM  \advance \!dimenA by -\!xS%   ** dimA = I = xM - xS
  2722.   \!dimenB=\!xE  \advance \!dimenB by -\!xM%   ** dimB = II = xE-xM
  2723.   \!xB=3\!dimenA \advance \!xB by -\!dimenB%   ** b=3I-II
  2724.   \!xC=2\!dimenB \advance \!xC by -2\!dimenA%  ** c=2(II-I)
  2725. %
  2726. % ** Find coefficients for y(t)=y_x + b_y*t + c_y*t**2
  2727.   \!dimenA=\!yM  \advance \!dimenA by -\!yS%   
  2728.   \!dimenB=\!yE  \advance \!dimenB by -\!yM%  
  2729.   \!yB=3\!dimenA \advance \!yB by -\!dimenB%  
  2730.   \!yC=2\!dimenB \advance \!yC by -2\!dimenA% 
  2731. %
  2732. % ** Use Simpson's rule to calculate arc length over [0,1/2]:
  2733. % **   arc length = 1/2[1/6 f(0) + 4/6 f(1/4) + 1/6 f(1/2)]
  2734. % ** with f(t) = sqrt(x'(t)**2 + y'(t)**2).
  2735.   \!xprime=\!xB  \!yprime=\!yB%          ** x'(t) = b + 2ct
  2736.   \!dxprime=.5\!xC  \!dyprime=.5\!yC%    ** dt=1/4 ==> dx'(t) = c/2
  2737.   \!getf \!midarclength=\!dimenA
  2738.   \!getf \advance \!midarclength by 4\!dimenA
  2739.   \!getf \advance \!midarclength by \!dimenA
  2740.   \divide \!midarclength by 12
  2741. %
  2742. % ** Get arc length over [0,1].
  2743.   \!arclength=\!dimenA
  2744.   \!getf \advance \!arclength by 4\!dimenA
  2745.   \!getf \advance \!arclength by \!dimenA
  2746.   \divide \!arclength by 12%             ** Now have arc length over [1/2,1]
  2747.   \advance \!arclength by \!midarclength
  2748.   \global\advance \totalarclength by \!arclength
  2749. %
  2750. %
  2751. % ** Check to see if there's anything to plot in this interval
  2752.   \ifdim\!distacross>\!arclength 
  2753.     \advance \!distacross by -\!arclength%   ** nothing 
  2754. %
  2755.   \else
  2756.     \!initinverseinterp%  ** initialize for inverse interpolation on arc length
  2757.     \loop\ifdim\!distacross<\!arclength%     ** loop over points on arc 
  2758.       \!inverseinterp%    ** find  t  such that arc length[0,t] = distacross,
  2759. %                         **   using inverse quadratic interpolation
  2760. %                         ** now evaluate x(t)=(c*t + b)*t + a
  2761.       \!xpos=\!t\!xC \advance\!xpos by \!xB
  2762.         \!xpos=\!t\!xpos \advance \!xpos by \!xS
  2763. %                                             ** evaluate y(t)
  2764.       \!ypos=\!t\!yC \advance\!ypos by \!yB
  2765.         \!ypos=\!t\!ypos \advance \!ypos by \!yS
  2766.       \!plotifinbounds%                       ** plot point if in bounds
  2767.       \advance\!distacross \plotsymbolspacing%** advance arc length for next pt
  2768.       \!advancedashing%                       ** see "linear"
  2769.     \repeat  
  2770. %
  2771.     \advance \!distacross by -\!arclength%    ** prepare for next interval 
  2772.   \fi
  2773. %
  2774.   \!xS=\!xE%              ** shift ending points to starting points
  2775.   \!yS=\!yE
  2776.   \ignorespaces}
  2777.  
  2778.  
  2779. % ** \!getf -- Calculates sqrt(x'(t)**2 + y'(t)**2) and advances
  2780. % **   x'(t) and y'(t)
  2781. \def\!getf{\!Pythag\!xprime\!yprime\!dimenA%
  2782.   \advance\!xprime by \!dxprime
  2783.   \advance\!yprime by \!dyprime}
  2784.  
  2785.  
  2786. % ** \!initinverseinterp -- initializes for inverse quadratic interpolation
  2787. % ** of arc length provided  1/3 < midarclength/arclength < 2/3; otherwise
  2788. % ** initializes for inverse linear interpolation.
  2789. \def\!initinverseinterp{%
  2790.   \ifdim\!arclength>\!zpt
  2791.     \!divide{8\!midarclength}\!arclength\!dimenE% ** dimE=8w=8r/s, where  r 
  2792. %                                               **  = midarclength, s=arclength
  2793. % **  Test for  w  out of range:  w<1/3  or w>2/3
  2794.     \ifdim\!dimenE<\!wmin \!setinverselinear
  2795.     \else 
  2796.       \ifdim\!dimenE>\!wmax \!setinverselinear
  2797.       \else%                                    ** w  in range: initialize
  2798.         \def\!inverseinterp{\!inversequad}\ignorespaces
  2799. %
  2800. % **     Calculate the coefficients  \!beta  and  \!gamma  of the quadratic
  2801. % **                    t = \!beta*v + \!gamma*v**2
  2802. % **     taking the values  t=0, 1/2, 1  at  v=0, w==r/s, 1  respectively:
  2803. % **        \!beta = (1/2 - w**2)/[w(1-w)] 
  2804. % **        \!gamma = 1 - beta.
  2805. %
  2806.          \!removept\!dimenE\!Ew%           **  8w, without "pt"
  2807.          \!dimenF=-\!Ew\!dimenE%           **  -(8w)**2
  2808.          \advance\!dimenF by 32pt%         **  32 - (8w)**2
  2809.          \!dimenG=8pt 
  2810.          \advance\!dimenG by -\!dimenE%    **  8 - 8w
  2811.          \!dimenG=\!Ew\!dimenG%            **  (8w)*(8-8w)
  2812.          \!divide\!dimenF\!dimenG\!beta%   **  beta = (32-(8w)**2)/(8w(8-8w))
  2813. %                                          **       = (1/2 - w**2)/(w(1-w))
  2814.          \!gamma=1pt
  2815.          \advance \!gamma by -\!beta%      **  gamma = 1-beta
  2816.       \fi%       ** end of the \ifdim\!dimenE>\!wmax
  2817.     \fi%         ** end of the \ifdim\!dimenE<\!wmin
  2818.   \fi%           ** end of the \ifdim\!arclength>\!zpt
  2819.   \ignorespaces}
  2820.  
  2821.  
  2822. % ** For 0 <= t <= 1, let AL(t) = arclength[0,t]/arclength[0,1]; note
  2823. % ** AL(0)=0, AL(1/2)=midarclength/arclength, AL(1)=1.  This routine
  2824. % ** calculates an approximation to AL^{-1}(distance across/arclength),
  2825. % ** using the assumption that AL^{-1} is quadratic.  Specifically, 
  2826. % ** it finds  t  such that
  2827. % **    AL^{-1}(v) =. t = v*(\!beta + \!gamma*v)
  2828. % ** where  \!beta  and  \!gamma  are set by \!initinv, and where
  2829. % ** v=distance across/arclength
  2830. \def\!inversequad{%
  2831.   \!divide\!distacross\!arclength\!dimenG%   ** dimG = v = distacross/arclength
  2832.   \!removept\!dimenG\!v%                     ** v, without "pt"
  2833.   \!dimenG=\!v\!gamma%                       ** gamma*v
  2834.   \advance\!dimenG by \!beta%                ** beta + gamma*v
  2835.   \!dimenG=\!v\!dimenG%                      ** t = v*(beta + gamma*v)
  2836.   \!removept\!dimenG\!t}%                    ** t, without "pt"
  2837.  
  2838.  
  2839. % ** When  w <= 1/3  or  w >= 2/3, the following routine writes (using
  2840. % ** plain TEK's \wlog command) a warning message on the user's log file,
  2841. % ** and initializes for inverse linear interpolation on arc length.
  2842. \def\!setinverselinear{%
  2843.   \def\!inverseinterp{\!inverselinear}%
  2844.   \divide\!dimenE by 8 \!removept\!dimenE\!t
  2845.   \!countC=\!intervalno \multiply \!countC 2
  2846.   \!countB=\!countC     \advance \!countB -1
  2847.   \!countA=\!countB     \advance \!countA -1
  2848.   \wlog{\the\!countB th point (\!xmidpt,\!ymidpt) being plotted 
  2849.     doesn't lie in the}%
  2850.   \wlog{ middle third of the arc between the \the\!countA th 
  2851.     and \the\!countC th points:}%
  2852.   \wlog{ [arc length \the\!countA\space to \the\!countB]/[arc length 
  2853.     \the \!countA\space to \the\!countC]=\!t.}%
  2854.   \ignorespaces}
  2855.  
  2856. % **  Inverse linear interpolation
  2857. \def\!inverselinear{% 
  2858.   \!divide\!distacross\!arclength\!dimenG
  2859.   \!removept\!dimenG\!t}
  2860.  
  2861.  
  2862. % **************************************
  2863. % **  ROTATIONS  (Handles rotations) ***
  2864. % **************************************
  2865.  
  2866. % ** User commands
  2867. % **   \startrotation [by COS_OF_ANGLE SIN_OF_ANGLE] [about XPIVOT YPIVOT]
  2868. % **   \stoprotation
  2869.  
  2870. % **   \startrotation [by COS_OF_ANGLE SIN_OF_ANGLE] [about XPIVOT YPIVOT]
  2871. % ** Future (XCOORD,YCOORD)'s will be rotated about (XPIVOT,YPIVOT) 
  2872. % ** by the angle with the give COS and SIN. Both fields are optional.
  2873. % ** [COS,SIN] defaults to previous value, or (1,0).
  2874. % ** (XPIVOT,YPIVOT) defaults to previous value, or (0,0)
  2875. % ** You can't change the coordinate system in the scope of a rotation.
  2876. % ** See Subsection 9.1 of the manual.
  2877. \def\startrotation{%
  2878.   \let\!rotateaboutpivot=\!!rotateaboutpivot
  2879.   \let\!rotateonly=\!!rotateonly
  2880.   \!ifnextchar{b}{\!getsincos }%
  2881.     {\!getsincos by {\!cosrotationangle} {\!sinrotationangle} }}
  2882. \def\!getsincos by #1 #2 {%
  2883.   \edef\!cosrotationangle{#1}%
  2884.   \edef\!sinrotationangle{#2}%
  2885.   \!ifcoordmode 
  2886.     \let\!ROnext=\!ccheckforpivot
  2887.   \else
  2888.     \let\!ROnext=\!dcheckforpivot
  2889.   \fi
  2890.   \!ROnext}
  2891. \def\!ccheckforpivot{%
  2892.   \!ifnextchar{a}{\!cgetpivot}%
  2893.     {\!cgetpivot about {\!xpivotcoord} {\!ypivotcoord} }}
  2894. \def\!cgetpivot about #1 #2 {%
  2895.   \edef\!xpivotcoord{#1}%
  2896.   \edef\!ypivotcoord{#2}%
  2897.   \!xpivot=#1\!xunit  \!ypivot=#2\!yunit
  2898.   \ignorespaces}
  2899. \def\!dcheckforpivot{%
  2900.   \!ifnextchar{a}{\!dgetpivot}{\ignorespaces}}
  2901. \def\!dgetpivot about #1 #2 {%
  2902.   \!xpivot=#1\relax  \!ypivot=#2\relax
  2903.   \ignorespaces}
  2904.   
  2905.  
  2906. % ** Following terminates rotation.
  2907. % ** See Subsection 9.1 of the manual.
  2908. \def\stoprotation{%
  2909.   \let\!rotateaboutpivot=\!!!rotateaboutpivot
  2910.   \let\!rotateonly=\!!!rotateonly
  2911.   \ignorespaces}
  2912.  
  2913. % ** !!rotateaboutpivot{XREG}{YREG}
  2914. % ** XREG <-- xpvt + cos(angle)*(XREG-xpvt) - sin(angle)*(YREG-ypvt)
  2915. % ** YREG <-- ypvt + cos(angle)*(YREG-ypvt) + sin(angle)*(XREG-xpvt)
  2916. % ** XREG,YREG are dimension registers. Can't be \!dimenA to \!dimenD
  2917. \def\!!rotateaboutpivot#1#2{%
  2918.   \!dimenA=#1\relax  \advance\!dimenA -\!xpivot
  2919.   \!dimenB=#2\relax  \advance\!dimenB -\!ypivot
  2920.   \!dimenC=\!cosrotationangle\!dimenA
  2921.     \advance \!dimenC -\!sinrotationangle\!dimenB
  2922.   \!dimenD=\!cosrotationangle\!dimenB
  2923.     \advance \!dimenD  \!sinrotationangle\!dimenA
  2924.   \advance\!dimenC \!xpivot  \advance\!dimenD \!ypivot
  2925.   #1=\!dimenC  #2=\!dimenD
  2926.   \ignorespaces}
  2927.  
  2928. % ** \!!rotateonly{XREG}{YREG}
  2929. % ** Like \!!rotateaboutpivot, but with a pivot of  (0,0)
  2930. \def\!!rotateonly#1#2{%
  2931.   \!dimenA=#1\relax  \!dimenB=#2\relax 
  2932.   \!dimenC=\!cosrotationangle\!dimenA
  2933.     \advance \!dimenC -\!rotsign\!sinrotationangle\!dimenB
  2934.   \!dimenD=\!cosrotationangle\!dimenB
  2935.     \advance \!dimenD  \!rotsign\!sinrotationangle\!dimenA
  2936.   #1=\!dimenC  #2=\!dimenD
  2937.   \ignorespaces}
  2938. \def\!rotsign{}
  2939. \def\!!!rotateaboutpivot#1#2{\relax}
  2940. \def\!!!rotateonly#1#2{\relax}
  2941. \stoprotation
  2942.  
  2943. \def\!reverserotateonly#1#2{%
  2944.   \def\!rotsign{-}%
  2945.   \!rotateonly{#1}{#2}%
  2946.   \def\!rotsign{}%
  2947.   \ignorespaces}
  2948.  
  2949.  
  2950. % **********************************
  2951. % *** SHADING  (Handles shading) ***
  2952. % **********************************
  2953.  
  2954. % **  User commands
  2955. % **    \setshadegrid [span <SPAN>] [point at XSHADE YSHADE] 
  2956. % **    \setshadesymbol [<LS, RS, BS, TS>] ({SHADESYMBOL}
  2957. % **      <XDIMEN,YDIMEN> [ORIENTATION])
  2958.  
  2959. % **  Internal commands:
  2960. % **    \!startvshade  (xS,ybS,ytS)
  2961. % **    \!starthshade  (yS,xlS,xrS)
  2962. % **    \!lshade [<LS,RS,BS,TS>]
  2963. % **       ** when shading vertically:
  2964. % **       [the region from (xS,ybS,ytS) to] (xE,ybE,ytE)
  2965. % **       ** when shading horizontally:
  2966. % **       [the region from (yS,xlS,xrS) to] (yE,xlE,xrE)
  2967. % **    \!qshade [<LS,RS,BS,TS>]
  2968. % **       ** when shading vertically:
  2969. % **       [the region from (xS,ybS,ytS) to] (xM,ybM,ytM)  (xE,ybE,ytE)
  2970. % **       ** when shading horizontally:
  2971. % **       [the region from (yS,xlS,xrS) to] (yM,xlM,xrM)  (yE,xlE,xrE)
  2972. % **    \!lattice{ANCHOR}{SPAN}{LOCATION}{INDEX}{LATTICE LOCATION}
  2973. % **    \!override{NOMINAL DIMEN}{REPLACEMENT DIMEN}{DIMEN}
  2974.  
  2975.  
  2976. % **  The shading routine can operate either in a "vertical mode" or a
  2977. % **  "horizontal mode".  In vertical mode, the region to be shaded is specified
  2978. % **  in the form
  2979. % **                 {(x,y): xl <= x <= xr  &  yb(x) <= y <= yt(x)}
  2980. % **  where  yb  and  yt  are functions of  x.  In horizontal mode, the region
  2981. % **  is specified in the form
  2982. % **                 {(x,y): yb <= y <= yt  &  xl(y) <= x <= xr(y)}.
  2983. % **  The functions  yb  and  yt  may be either both linear or both quadratic;
  2984. % **  similarly for  xl  and  xr.  A region with say, piecewise quadratic bottom
  2985. % **  and top boundaries, can be shaded by consecutive (vertical) \!qshades,
  2986. % **  proceeding from left to right.  Similarly, a region with piecewise     
  2987. % **  quadratic left and right boundaries can be shaded by consecutive
  2988. % **  (horizontal) \!qshades, proceeding from bottom to top.  More complex
  2989. % **  regions can be shaded by partitioning them into appropriate subregions,
  2990. % **  and shading those.
  2991.     
  2992. % **  Shading is accomplished by placing a user-selected shading symbol at
  2993. % **  those points of a regular grid which fall within the region to be
  2994. % **  shaded.  This region can be "shrunk" so that a largish shading symbol
  2995. % **  will not extend outside it.  Shrinking is accomplished by specifying
  2996. % **  shrinkages for the left, right, bottom, and top boundaries, in a manner
  2997. % **  discussed further below.
  2998.  
  2999. % **  \shades and \!joins MUST NOT be intermingled.  Finish drawing a curve
  3000. % **  before starting to shade a region, and finish shading a region before
  3001. % **  starting to draw a curve.
  3002.  
  3003.  
  3004. % **  \setshadegrid [span <SPAN>] [point at XSHADE YSHADE] 
  3005. % **  The shading symbol is placed down on the points of a grid centered
  3006. % **  at the coordinate point (XSHADE,YSHADE).  The grid points are of the
  3007. % **  form (j*SPAN,k*SPAN), with  j+k  even.  SPAN is specified
  3008. % **  as a dimension.
  3009. % **  (XSHADE,YSHADE) defaults to previous (XSHADE,YSHADE) (or (0,0) if none)
  3010. % **  SPAN defaults to previous span (or 5pt if none)
  3011. % **  See Subsection 7.2 of the manual.
  3012. \def\setshadegrid{%
  3013.   \!ifnextchar{s}{\!getspan }
  3014.     {\!getspan span <\!dshade>}}
  3015. \def\!getspan span <#1>{%
  3016.   \!dshade=#1\relax
  3017.   \!ifcoordmode 
  3018.     \let\!GRnext=\!GRccheckforAP
  3019.   \else
  3020.     \let\!GRnext=\!GRdcheckforAP
  3021.   \fi
  3022.   \!GRnext}
  3023. \def\!GRccheckforAP{%
  3024.   \!ifnextchar{p}{\!cgetanchor }
  3025.     {\!cgetanchor point at {\!xshadesave} {\!yshadesave} }}
  3026. \def\!cgetanchor point at #1 #2 {%
  3027.   \edef\!xshadesave{#1}\edef\!yshadesave{#2}%
  3028.   \!xshade=\!xshadesave\!xunit  \!yshade=\!yshadesave\!yunit
  3029.   \ignorespaces}
  3030. \def\!GRdcheckforAP{%
  3031.   \!ifnextchar{p}{\!dgetanchor}%
  3032.     {\ignorespaces}}
  3033. \def\!dgetanchor point at #1 #2 {%
  3034.   \!xshade=#1\relax  \!yshade=#2\relax
  3035.   \ignorespaces}
  3036.  
  3037. % **  \setshadesymbol  [<LS, RS, BS, TS>] ({SHADESYMBOL}
  3038. % **    <XDIMEN,YDIMEN> [ORIENTATION])
  3039. % **  Saves SHADESYMBOL away in an hbox for use with shading routines.
  3040. % **  A shade symbol will not be plotted if its plot position comes within
  3041. % **    distance LS of the left boundary,  RS of the right boundary,  TS of the
  3042. % **    top boundary,  BS of the bottom boundary.  These parameters have 
  3043. % **    default values that should work in most cases (see below).
  3044. % **    To override a default value, specify the replacement value
  3045. % **    in the appropriate subfield of the shrinkages field.
  3046. % **    0pt may be coded as  "z" (without the quotes).  To accept a
  3047. % **    default value, leave the field empty.  Thus
  3048. % **      [,z,,5pt]  sets  LS=default, RS=0pt, BS=default, TS=5pt .
  3049. % **    Skipping the shrinkages field accepts all the defaults.
  3050. % **  See Subsection 7.1 of the manual.
  3051. \def\setshadesymbol{%
  3052.   \!ifnextchar<{\!setshadesymbol}{\!setshadesymbol<,,,> }}
  3053.  
  3054. \def\!setshadesymbol <#1,#2,#3,#4> (#5#6){%
  3055. % **  set the shadesymbol
  3056.   \!setputobject{#5}{#6}%                        
  3057.   \setbox\!shadesymbol=\box\!putobject%
  3058.   \!shadesymbolxshift=\!xshift \!shadesymbolyshift=\!yshift
  3059. %
  3060. % **  set the shrinkages
  3061.   \!dimenA=\!xshift \advance\!dimenA \!smidge% ** default LS = xshift - smidge
  3062.   \!override\!dimenA{#1}\!lshrinkage%         
  3063.   \!dimenA=\!wd \advance \!dimenA -\!xshift%   ** default RS = width - xshift
  3064.     \advance\!dimenA \!smidge%                                  - smidge
  3065.     \!override\!dimenA{#2}\!rshrinkage
  3066.   \!dimenA=\!dp \advance \!dimenA \!yshift%    ** default BS = depth + yshift
  3067.     \advance\!dimenA \!smidge%                                  - smidge
  3068.     \!override\!dimenA{#3}\!bshrinkage
  3069.   \!dimenA=\!ht \advance \!dimenA -\!yshift%   ** default TS = height - yshift
  3070.     \advance\!dimenA \!smidge%                                  - smidge
  3071.     \!override\!dimenA{#4}\!tshrinkage
  3072.   \ignorespaces}
  3073. \def\!smidge{-.2pt}%
  3074.  
  3075. % ** \!override{NOMINAL DIMEN}{REPLACEMENT DIMEN}{DIMEN}
  3076. % ** Overrides the NOMINAL DIMEN by the REPLACEMENT DIMEN to produce DIMEN,
  3077. % ** according to the following rules:
  3078. % **   REPLACEMENT DIMEN empty: DIMEN <-- NOMINAL DIMEN
  3079. % **   REPLACEMENT DIMEN z:     DIMEN <-- 0pt
  3080. % **   otherwise:               DIMEN <-- REPLACEMENT DIMEN
  3081. % ** DIMEN must be a dimension register
  3082. \def\!override#1#2#3{%
  3083.   \edef\!!override{#2}% 
  3084.   \ifx \!!override\empty
  3085.     #3=#1\relax
  3086.   \else
  3087.     \if z\!!override
  3088.       #3=\!zpt
  3089.     \else
  3090.       \ifx \!!override\!blankz
  3091.         #3=\!zpt
  3092.       \else
  3093.         #3=#2\relax
  3094.       \fi
  3095.     \fi
  3096.   \fi
  3097.   \ignorespaces}
  3098. \def\!blankz{ z}
  3099.  
  3100. \setshadesymbol ({\fiverm .})%       ** initialize plotsymbol
  3101. %                                    ** \fivesy ^^B  is a small cross
  3102.  
  3103.  
  3104. % ** \!startvshade [at] (xS,ybS,ytS)
  3105. % ** Initiates vertical shading mode
  3106. \def\!startvshade#1(#2,#3,#4){%
  3107.   \let\!!xunit=\!xunit%
  3108.   \let\!!yunit=\!yunit%
  3109.   \let\!!xshade=\!xshade%
  3110.   \let\!!yshade=\!yshade%
  3111.   \def\!getshrinkages{\!vgetshrinkages}%
  3112.   \let\!setshadelocation=\!vsetshadelocation%
  3113.   \!xS=\!M{#2}\!!xunit
  3114.   \!ybS=\!M{#3}\!!yunit
  3115.   \!ytS=\!M{#4}\!!yunit
  3116.   \!shadexorigin=\!xorigin  \advance \!shadexorigin \!shadesymbolxshift
  3117.   \!shadeyorigin=\!yorigin  \advance \!shadeyorigin \!shadesymbolyshift
  3118.   \ignorespaces}
  3119.  
  3120. % ** \!starthshade [at] (yS,xlS,xrS)
  3121. % ** Initiates horizontal shading mode
  3122. \def\!starthshade#1(#2,#3,#4){%
  3123.   \let\!!xunit=\!yunit%
  3124.   \let\!!yunit=\!xunit%
  3125.   \let\!!xshade=\!yshade%
  3126.   \let\!!yshade=\!xshade%
  3127.   \def\!getshrinkages{\!hgetshrinkages}%
  3128.   \let\!setshadelocation=\!hsetshadelocation%
  3129.   \!xS=\!M{#2}\!!xunit
  3130.   \!ybS=\!M{#3}\!!yunit
  3131.   \!ytS=\!M{#4}\!!yunit
  3132.   \!shadexorigin=\!xorigin  \advance \!shadexorigin \!shadesymbolxshift
  3133.   \!shadeyorigin=\!yorigin  \advance \!shadeyorigin \!shadesymbolyshift
  3134.   \ignorespaces}
  3135.  
  3136.  
  3137. % **  \!lattice{ANCHOR}{SPAN}{LOCATION}{INDEX}{LATTICE LOCATION}
  3138. % **  Consider the lattice with points  ANCHOR + j*SPAN. This routine determines
  3139. % **  the index  k  of the smallest lattice point >= LOCATION, and sets
  3140. % **  LATTICE LOCATION = ANCHOR + k*SPAN.
  3141. % **  INDEX is assumed to be a count register, LATTICE LOCATION a dimen reg.
  3142. \def\!lattice#1#2#3#4#5{%
  3143.   \!dimenA=#1%                        ** dimA = ANCHOR
  3144.   \!dimenB=#2%                        ** dimB = SPAN  (assumed > 0pt)
  3145.   \!countB=\!dimenB%                  ** ctB  = SPAN, as a count
  3146. %
  3147. % ** Determine index of smallest lattice point >= LOCATION
  3148.   \!dimenC=#3%                        ** dimC = LOCATION
  3149.   \advance\!dimenC -\!dimenA%         ** now dimC = LOCATION-ANCHOR
  3150.   \!countA=\!dimenC%                  ** ctA = above, as a count
  3151.   \divide\!countA \!countB%           ** now ctA = desired index, if dimC <= 0
  3152.   \ifdim\!dimenC>\!zpt
  3153.     \!dimenD=\!countA\!dimenB%        ** (tentative k)*span
  3154.     \ifdim\!dimenD<\!dimenC%          ** if this is false, ctA = desired index
  3155.       \advance\!countA 1 %            ** if true, have to add 1
  3156.     \fi
  3157.   \fi
  3158. %
  3159.   \!dimenC=\!countA\!dimenB%          ** lattice location = anchor + ctA*span
  3160.     \advance\!dimenC \!dimenA
  3161.   #4=\!countA%                        ** the desired index
  3162.   #5=\!dimenC%                        ** corresponding lattice location
  3163.   \ignorespaces}
  3164.  
  3165.  
  3166. % ** \!qshade [with shrinkages] [[LS,RS,BS,TS]]
  3167. % ***** during vertical shading:
  3168. % **    [the region from (xS,ybS,ytS) to] (xM,ybM,ytM) [and] (xE,ybE,ytE)
  3169. % ** Shades the region {(x,y): xS <= x <= xE, yb(x) <= y <= yt(x)}, where 
  3170. % **   yb is the quadratic thru (xS,ybS) & (xM,ybM) & (xE,ybE)
  3171. % **   yt is the quadratic thru (xS,ytS) & (xM,ybM) & (xE,ytE)
  3172. % ** xS,ybS,ytS are either given by \!startvshade or carried over
  3173. % **   as the ending values of the immediately preceding \!qshade.
  3174. % ** For the interpretation of LS, RS, BS, & TS, see \setshadesymbol. The
  3175. % **   values set there can be overridden, for the course of this \!qshade
  3176. % **   only, in the same manner as overrides are specified for
  3177. % **   \setshadesymbol.
  3178. % ***** during horizontal shading:
  3179. % **    [the region from (yS,xlS,xrS) to] (yM,xlM,xrM) [and] (yE,xlE,xrE)
  3180. \def\!qshade#1(#2,#3,#4)#5(#6,#7,#8){%
  3181.   \!xM=\!M{#2}\!!xunit
  3182.   \!ybM=\!M{#3}\!!yunit
  3183.   \!ytM=\!M{#4}\!!yunit
  3184.   \!xE=\!M{#6}\!!xunit
  3185.   \!ybE=\!M{#7}\!!yunit
  3186.   \!ytE=\!M{#8}\!!yunit
  3187.   \!getcoeffs\!xS\!ybS\!xM\!ybM\!xE\!ybE\!ybB\!ybC%**Get coefficients B & C for
  3188.   \!getcoeffs\!xS\!ytS\!xM\!ytM\!xE\!ytE\!ytB\!ytC%**y=y0 + B(x-X0) + C(x-X0)**2
  3189.   \def\!getylimits{\!qgetylimits}%
  3190.   \!shade{#1}\ignorespaces}
  3191.  
  3192. % ** \!lshade ... (xE,ybE,ytE)
  3193. % ** This is like \!qshade, but the top and bottom boundaries are linear,
  3194. % ** rather than quadratic.
  3195. \def\!lshade#1(#2,#3,#4){%
  3196.   \!xE=\!M{#2}\!!xunit
  3197.   \!ybE=\!M{#3}\!!yunit
  3198.   \!ytE=\!M{#4}\!!yunit
  3199.   \!dimenE=\!xE  \advance \!dimenE -\!xS%   ** xE-xS
  3200.   \!dimenC=\!ytE \advance \!dimenC -\!ytS%  ** ytE-ytS
  3201.   \!divide\!dimenC\!dimenE\!ytB%            ** ytB = (ytE-ytS)/(xE-xS)
  3202.   \!dimenC=\!ybE \advance \!dimenC -\!ybS%  ** ybE-ybS
  3203.   \!divide\!dimenC\!dimenE\!ybB%            ** ybB = (ybE-ybS)/(xE-xS)
  3204.   \def\!getylimits{\!lgetylimits}%
  3205.   \!shade{#1}\ignorespaces}
  3206.  
  3207. % **  \!getcoeffs{X0}{Y0}{X1}{Y1}{X2}{Y2}{B}{C}
  3208. % **  Finds  B  and  C  such that the quadratic  y = Y0 + B(x-X0) + C(x-X0)**2
  3209. % **  passes through (X1,Y1) and (X2,Y2):  when X0=0=Y0, the formulas are:
  3210. % **                   B = S1 - X1*C,   C = (S2-S1)/X2
  3211. % **  with
  3212. % **                 S1 = Y1/X1,   S2 = (Y2-Y1)/(X2-X1).
  3213. \def\!getcoeffs#1#2#3#4#5#6#7#8{% 
  3214.   \!dimenC=#4\advance \!dimenC -#2%            ** dimC=Y1-Y0
  3215.   \!dimenE=#3\advance \!dimenE -#1%            ** dimE=X1-X0
  3216.   \!divide\!dimenC\!dimenE\!dimenF%            ** dimF=S1
  3217.   \!dimenC=#6\advance \!dimenC -#4%            ** dimC=Y2-Y1
  3218.   \!dimenH=#5\advance \!dimenH -#3%            ** dimH=X2-X1
  3219.   \!divide\!dimenC\!dimenH\!dimenG%            ** dimG=S2
  3220.   \advance\!dimenG -\!dimenF%                  ** dimG=S2-S1
  3221.   \advance \!dimenH \!dimenE%                  ** dimH=X2-X0
  3222.   \!divide\!dimenG\!dimenH#8%                  ** C=(S2-S1)/(X2-X0)
  3223.   \!removept#8\!t%                             ** C, without "pt"
  3224.   #7=-\!t\!dimenE%                             ** -C*(X1-X0)
  3225.   \advance #7\!dimenF%                         ** B=S1-C*(X1-X0)
  3226.   \ignorespaces}
  3227.  
  3228.  
  3229. \def\!shade#1{%
  3230. % ** Get LS,RS,BS,TS for this panel
  3231.   \!getshrinkages#1<,,,>\!nil% %       ** now effective LS=dimE, RS=dimF,
  3232. %                                      **   BS=dimG, TS=dimH
  3233.   \advance \!dimenE \!xS%              ** now dimE=xS+LS
  3234.   \!lattice\!!xshade\!dshade\!dimenE%  ** set parity=index of left-mst x-lattice
  3235.     \!parity\!xpos%                    **   point >= xS+LS, xpos=its location
  3236.   \!dimenF=-\!dimenF%                  ** set dimF=xE-RS
  3237.     \advance\!dimenF \!xE
  3238. %               
  3239.   \!loop\!not{\ifdim\!xpos>\!dimenF}%  ** loop over x-lattice points <= xE-RS
  3240.     \!shadecolumn%                 
  3241.     \advance\!xpos \!dshade%           ** move over to next column
  3242.     \advance\!parity 1%                ** increase index of x-point
  3243.   \repeat
  3244. %
  3245.   \!xS=\!xE%                           ** shift ending values to starting values
  3246.   \!ybS=\!ybE
  3247.   \!ytS=\!ytE
  3248.   \ignorespaces}
  3249.  
  3250.  
  3251. \def\!vgetshrinkages#1<#2,#3,#4,#5>#6\!nil{%
  3252.   \!override\!lshrinkage{#2}\!dimenE
  3253.   \!override\!rshrinkage{#3}\!dimenF
  3254.   \!override\!bshrinkage{#4}\!dimenG
  3255.   \!override\!tshrinkage{#5}\!dimenH
  3256.   \ignorespaces}
  3257. \def\!hgetshrinkages#1<#2,#3,#4,#5>#6\!nil{%
  3258.   \!override\!lshrinkage{#2}\!dimenG
  3259.   \!override\!rshrinkage{#3}\!dimenH
  3260.   \!override\!bshrinkage{#4}\!dimenE
  3261.   \!override\!tshrinkage{#5}\!dimenF
  3262.   \ignorespaces}
  3263.  
  3264.  
  3265. \def\!shadecolumn{%
  3266.   \!dxpos=\!xpos
  3267.   \advance\!dxpos -\!xS%            ** dx = x - xS
  3268.   \!removept\!dxpos\!dx%            ** ditto, without "pt"
  3269.   \!getylimits%                     ** get top and bottom y-values
  3270.   \advance\!ytpos -\!dimenH%        ** less TS
  3271.   \advance\!ybpos \!dimenG%         ** plus BS
  3272.   \!yloc=\!!yshade%                 ** get anchor point for this column
  3273.   \ifodd\!parity 
  3274.      \advance\!yloc \!dshade
  3275.   \fi
  3276.   \!lattice\!yloc{2\!dshade}\!ybpos%
  3277.     \!countA\!ypos%                 ** ypos=smallest y point for this column
  3278.   \!dimenA=-\!shadexorigin \advance \!dimenA \!xpos%      ** over
  3279.   \loop\!not{\ifdim\!ypos>\!ytpos}% ** loop over ypos <= yt(t)
  3280.     \!setshadelocation%             ** vmode: xloc=xpos, yloc=ypos 
  3281. %                                   ** hmode: xloc=ypos, yloc=xpos 
  3282.     \!rotateaboutpivot\!xloc\!yloc%
  3283.     \!dimenA=-\!shadexorigin \advance \!dimenA \!xloc%    ** over
  3284.     \!dimenB=-\!shadeyorigin \advance \!dimenB \!yloc%    ** up
  3285.     \kern\!dimenA \raise\!dimenB\copy\!shadesymbol \kern-\!dimenA
  3286.     \advance\!ypos 2\!dshade
  3287.   \repeat
  3288.   \ignorespaces}
  3289.  
  3290. \def\!qgetylimits{%
  3291.   \!dimenA=\!dx\!ytC              
  3292.   \advance\!dimenA \!ytB%         ** yt(t)=ytS + dx*(Bt + dx*Ct)
  3293.   \!ytpos=\!dx\!dimenA
  3294.   \advance\!ytpos \!ytS
  3295.   \!dimenA=\!dx\!ybC              
  3296.   \advance\!dimenA \!ybB%         ** yb(t)=ybS + dx*(Bb + dx*Cb)
  3297.   \!ybpos=\!dx\!dimenA
  3298.   \advance\!ybpos \!ybS}
  3299.  
  3300. \def\!lgetylimits{%
  3301.   \!ytpos=\!dx\!ytB%              ** yt(t)=ytS + dx*Bt
  3302.   \advance\!ytpos \!ytS
  3303.   \!ybpos=\!dx\!ybB%              ** yb(t)=ybS + dx*Bb
  3304.   \advance\!ybpos \!ybS}
  3305.  
  3306. \def\!vsetshadelocation{%         ** vmode: xloc=xpos, yloc=ypos 
  3307.   \!xloc=\!xpos
  3308.   \!yloc=\!ypos}
  3309. \def\!hsetshadelocation{%         ** hmode: xloc=ypos, yloc=xpos 
  3310.   \!xloc=\!ypos
  3311.   \!yloc=\!xpos}
  3312.  
  3313.  
  3314. % **************************************
  3315. % *** TICKS  (Draws ticks on graphs) ***
  3316. % **************************************
  3317.  
  3318. % ** User commands
  3319. % **   \ticksout
  3320. % **   \ticksin
  3321. % **   \gridlines
  3322. % **   \nogridlines
  3323. % **   \loggedticks
  3324. % **   \unloggesticks
  3325. % ** See Subsection 3.4 of the manual
  3326.  
  3327. % ** The following is an option of the \axis command
  3328. % **   ticks 
  3329. % **     [in] [out] 
  3330. % **     [long] [short] [length <LENGTH>] 
  3331. % **     [width <WIDTH>]
  3332. % **     [andacross] [butnotacross] 
  3333. % **     [logged] [unlogged] 
  3334. % **     [unlabeled] [numbered] [withvalues VALUE1 VALUE2 ... VALUEk / ]
  3335. % **     [quantity Q] [at LOC1 LOC2 ... LOCk / ] [from LOC1 to LOC2 by
  3336. % **       LOC_INCREMENT]
  3337. % ** See Subsection 3.2 of the manual for the rules.
  3338.  
  3339. % ** The various options of the  tick  field are processed by the
  3340. % ** \!nextkeyword  command defined below.
  3341. % ** For example, `\!nextkeyword short '  expands to  `\!ticksshort',
  3342. % ** while `\!nextkeyword withvalues' expands to `\!tickswithvalues'.
  3343.  
  3344. \def\!axisticks {%
  3345.   \def\!nextkeyword##1 {%
  3346.     \expandafter\ifx\csname !ticks##1\endcsname \relax
  3347.       \def\!next{\!fixkeyword{##1}}%
  3348.     \else
  3349.       \def\!next{\csname !ticks##1\endcsname}%
  3350.     \fi
  3351.     \!next}%
  3352.   \!axissetup
  3353.     \def\!axissetup{\relax}%
  3354.   \edef\!ticksinoutsign{\!ticksinoutSign}%
  3355.   \!ticklength=\longticklength
  3356.   \!tickwidth=\linethickness
  3357.   \!gridlinestatus
  3358.   \!setticktransform
  3359.   \!maketick
  3360.   \!tickcase=0
  3361.   \def\!LTlist{}%
  3362.   \!nextkeyword}
  3363.  
  3364. \def\ticksout{%
  3365.   \def\!ticksinoutSign{+}}
  3366. \def\ticksin{%
  3367.   \def\!ticksinoutSign{-}}
  3368. \ticksout
  3369.  
  3370. \def\gridlines{%
  3371.   \def\!gridlinestatus{\!gridlinestootrue}}
  3372. \def\nogridlines{%
  3373.   \def\!gridlinestatus{\!gridlinestoofalse}}
  3374. \nogridlines
  3375.  
  3376. \def\loggedticks{%
  3377.   \def\!setticktransform{\let\!ticktransform=\!logten}}
  3378. \def\unloggedticks{%
  3379.   \def\!setticktransform{\let\!ticktransform=\!donothing}}
  3380. \def\!donothing#1#2{\def#2{#1}}
  3381. \unloggedticks
  3382.  
  3383. % ** \!ticks/ : terminates read of tick options
  3384. \expandafter\def\csname !ticks/\endcsname{%
  3385.   \!not {\ifx \!LTlist\empty}
  3386.     \!placetickvalues
  3387.   \fi
  3388.   \def\!tickvalueslist{}%
  3389.   \def\!LTlist{}%
  3390.   \expandafter\csname !axis/\endcsname}
  3391.  
  3392. \def\!maketick{%
  3393.   \setbox\!boxA=\hbox{%
  3394.     \beginpicture
  3395.       \!setdimenmode
  3396.       \setcoordinatesystem point at {\!zpt} {\!zpt}   
  3397.       \linethickness=\!tickwidth
  3398.       \ifdim\!ticklength>\!zpt
  3399.         \putrule from {\!zpt} {\!zpt} to
  3400.           {\!ticksinoutsign\!tickxsign\!ticklength}
  3401.           {\!ticksinoutsign\!tickysign\!ticklength}
  3402.       \fi
  3403.       \if!gridlinestoo
  3404.         \putrule from {\!zpt} {\!zpt} to
  3405.           {-\!tickxsign\!xaxislength} {-\!tickysign\!yaxislength}
  3406.       \fi
  3407.     \endpicturesave <\!Xsave,\!Ysave>}%
  3408.     \wd\!boxA=\!zpt}
  3409.   
  3410. \def\!ticksin{%
  3411.   \def\!ticksinoutsign{-}%
  3412.   \!maketick
  3413.   \!nextkeyword}
  3414.  
  3415. \def\!ticksout{%
  3416.   \def\!ticksinoutsign{+}%
  3417.   \!maketick
  3418.   \!nextkeyword}
  3419.  
  3420. \def\!tickslength<#1> {%
  3421.   \!ticklength=#1\relax
  3422.   \!maketick
  3423.   \!nextkeyword}
  3424.  
  3425. \def\!tickslong{%
  3426.   \!tickslength<\longticklength> }
  3427.  
  3428. \def\!ticksshort{%
  3429.   \!tickslength<\shortticklength> }
  3430.  
  3431. \def\!tickswidth<#1> {%
  3432.   \!tickwidth=#1\relax
  3433.   \!maketick
  3434.   \!nextkeyword}
  3435.  
  3436. \def\!ticksandacross{%
  3437.   \!gridlinestootrue
  3438.   \!maketick
  3439.   \!nextkeyword}
  3440.  
  3441. \def\!ticksbutnotacross{%
  3442.   \!gridlinestoofalse
  3443.   \!maketick
  3444.   \!nextkeyword}
  3445.  
  3446. \def\!tickslogged{%
  3447.   \let\!ticktransform=\!logten
  3448.   \!nextkeyword}
  3449.  
  3450. \def\!ticksunlogged{%
  3451.   \let\!ticktransform=\!donothing
  3452.   \!nextkeyword}
  3453.  
  3454. \def\!ticksunlabeled{%
  3455.   \!tickcase=0
  3456.   \!nextkeyword}
  3457.  
  3458. \def\!ticksnumbered{%
  3459.   \!tickcase=1
  3460.   \!nextkeyword}
  3461.  
  3462. \def\!tickswithvalues#1/ {%
  3463.   \edef\!tickvalueslist{#1! /}%
  3464.   \!tickcase=2
  3465.   \!nextkeyword}
  3466.  
  3467. \def\!ticksquantity#1 {%
  3468.   \ifnum #1>1
  3469.     \!updatetickoffset
  3470.     \!countA=#1\relax
  3471.     \advance \!countA -1
  3472.     \!ticklocationincr=\!axisLength
  3473.       \divide \!ticklocationincr \!countA
  3474.     \!ticklocation=\!axisstart
  3475.     \loop \!not{\ifdim \!ticklocation>\!axisend}
  3476.       \!placetick\!ticklocation
  3477.       \ifcase\!tickcase
  3478.           \relax %  Case 0: no labels
  3479.         \or
  3480.           \relax %  Case 1: numbered -- not available here
  3481.         \or
  3482.           \expandafter\!gettickvaluefrom\!tickvalueslist
  3483.           \edef\!tickfield{{\the\!ticklocation}{\!value}}%
  3484.           \expandafter\!listaddon\expandafter{\!tickfield}\!LTlist%
  3485.       \fi
  3486.       \advance \!ticklocation \!ticklocationincr
  3487.     \repeat
  3488.   \fi
  3489.   \!nextkeyword}
  3490.  
  3491. \def\!ticksat#1 {%
  3492.   \!updatetickoffset
  3493.   \edef\!Loc{#1}%
  3494.   \if /\!Loc
  3495.     \def\next{\!nextkeyword}%
  3496.   \else
  3497.     \!ticksincommon
  3498.     \def\next{\!ticksat}%
  3499.   \fi
  3500.   \next}    
  3501.       
  3502. \def\!ticksfrom#1 to #2 by #3 {%
  3503.   \!updatetickoffset
  3504.   \edef\!arg{#3}%
  3505.   \expandafter\!separate\!arg\!nil
  3506.   \!scalefactor=1
  3507.   \expandafter\!countfigures\!arg/
  3508.   \edef\!arg{#1}%
  3509.   \!scaleup\!arg by\!scalefactor to\!countE
  3510.   \edef\!arg{#2}%
  3511.   \!scaleup\!arg by\!scalefactor to\!countF
  3512.   \edef\!arg{#3}%
  3513.   \!scaleup\!arg by\!scalefactor to\!countG
  3514.   \loop \!not{\ifnum\!countE>\!countF}
  3515.     \ifnum\!scalefactor=1
  3516.       \edef\!Loc{\the\!countE}%
  3517.     \else
  3518.       \!scaledown\!countE by\!scalefactor to\!Loc
  3519.     \fi
  3520.     \!ticksincommon
  3521.     \advance \!countE \!countG
  3522.   \repeat
  3523.   \!nextkeyword}
  3524.  
  3525. \def\!updatetickoffset{%
  3526.   \!dimenA=\!ticksinoutsign\!ticklength
  3527.   \ifdim \!dimenA>\!offset
  3528.     \!offset=\!dimenA
  3529.   \fi}
  3530.  
  3531. \def\!placetick#1{%
  3532.   \if!xswitch
  3533.     \!xpos=#1\relax
  3534.     \!ypos=\!axisylevel
  3535.   \else
  3536.     \!xpos=\!axisxlevel
  3537.     \!ypos=#1\relax
  3538.   \fi
  3539.   \advance\!xpos \!Xsave
  3540.   \advance\!ypos \!Ysave
  3541.   \kern\!xpos\raise\!ypos\copy\!boxA\kern-\!xpos
  3542.   \ignorespaces}
  3543.  
  3544. \def\!gettickvaluefrom#1 #2 /{%
  3545.   \edef\!value{#1}%
  3546.   \edef\!tickvalueslist{#2 /}%
  3547.   \ifx \!tickvalueslist\!endtickvaluelist
  3548.     \!tickcase=0
  3549.   \fi}
  3550. \def\!endtickvaluelist{! /}
  3551.  
  3552. \def\!ticksincommon{%
  3553.   \!ticktransform\!Loc\!t
  3554.   \!ticklocation=\!t\!!unit
  3555.   \advance\!ticklocation -\!!origin
  3556.   \!placetick\!ticklocation
  3557.   \ifcase\!tickcase
  3558.     \relax % Case 0: no labels
  3559.   \or %      Case 1: numbered
  3560.     \ifdim\!ticklocation<-\!!origin
  3561.       \edef\!Loc{$\!Loc$}%
  3562.     \fi
  3563.     \edef\!tickfield{{\the\!ticklocation}{\!Loc}}%
  3564.     \expandafter\!listaddon\expandafter{\!tickfield}\!LTlist%
  3565.   \or %      Case 2: labeled
  3566.     \expandafter\!gettickvaluefrom\!tickvalueslist
  3567.     \edef\!tickfield{{\the\!ticklocation}{\!value}}%
  3568.     \expandafter\!listaddon\expandafter{\!tickfield}\!LTlist%
  3569.   \fi}
  3570.  
  3571. \def\!separate#1\!nil{%
  3572.   \!ifnextchar{-}{\!!separate}{\!!!separate}#1\!nil}
  3573. \def\!!separate-#1\!nil{%
  3574.   \def\!sign{-}%
  3575.   \!!!!separate#1..\!nil}
  3576. \def\!!!separate#1\!nil{%
  3577.   \def\!sign{+}%
  3578.   \!!!!separate#1..\!nil}
  3579. \def\!!!!separate#1.#2.#3\!nil{%
  3580.   \def\!arg{#1}%
  3581.   \ifx\!arg\!empty
  3582.     \!countA=0
  3583.   \else
  3584.     \!countA=\!arg
  3585.   \fi
  3586.   \def\!arg{#2}%
  3587.   \ifx\!arg\!empty
  3588.     \!countB=0
  3589.   \else
  3590.     \!countB=\!arg
  3591.   \fi}
  3592.  
  3593. \def\!countfigures#1{%
  3594.   \if #1/%
  3595.     \def\!next{\ignorespaces}%
  3596.   \else
  3597.     \multiply\!scalefactor 10
  3598.     \def\!next{\!countfigures}%
  3599.   \fi
  3600.   \!next}
  3601.  
  3602. \def\!scaleup#1by#2to#3{%
  3603.   \expandafter\!separate#1\!nil
  3604.   \multiply\!countA #2\relax
  3605.   \advance\!countA \!countB
  3606.   \if -\!sign
  3607.     \!countA=-\!countA
  3608.   \fi
  3609.   #3=\!countA
  3610.   \ignorespaces}
  3611.  
  3612. \def\!scaledown#1by#2to#3{%
  3613.   \!countA=#1\relax%                          ** get original #
  3614.   \ifnum \!countA<0 %                         ** take abs value,
  3615.     \def\!sign{-}%                            **   remember sign
  3616.     \!countA=-\!countA
  3617.   \else
  3618.     \def\!sign{}%
  3619.   \fi
  3620.   \!countB=\!countA%                          ** copy |#|
  3621.   \divide\!countB #2\relax%                   ** integer part (|#|/sf)
  3622.   \!countC=\!countB%                          ** get sf * (|#|/sf)
  3623.     \multiply\!countC #2\relax
  3624.   \advance \!countA -\!countC%                ** ctA is now remainder
  3625.   \edef#3{\!sign\the\!countB.}%               ** +- integerpart.
  3626.   \!countC=\!countA %                         ** Tack on proper number
  3627.   \ifnum\!countC=0 %                          **   of zeros after .
  3628.     \!countC=1
  3629.   \fi
  3630.   \multiply\!countC 10
  3631.   \!loop \ifnum #2>\!countC
  3632.     \edef#3{#3\!zero}%
  3633.     \multiply\!countC 10
  3634.   \repeat
  3635.   \edef#3{#3\the\!countA}%                    ** Add on rest of remainder
  3636.   \ignorespaces}
  3637.  
  3638. \def\!placetickvalues{%
  3639.   \advance\!offset \tickstovaluesleading
  3640.   \if!xswitch
  3641.     \setbox\!boxA=\hbox{%
  3642.       \def\\##1##2{%
  3643.         \!dimenput {##2} [B] (##1,\!axisylevel)}%
  3644.       \beginpicture 
  3645.         \!LTlist
  3646.       \endpicturesave <\!Xsave,\!Ysave>}%
  3647.     \!dimenA=\!axisylevel
  3648.       \advance\!dimenA -\!Ysave
  3649.       \advance\!dimenA \!tickysign\!offset
  3650.       \if -\!tickysign
  3651.         \advance\!dimenA -\ht\!boxA
  3652.       \else
  3653.         \advance\!dimenA  \dp\!boxA
  3654.       \fi
  3655.     \advance\!offset \ht\!boxA 
  3656.       \advance\!offset \dp\!boxA
  3657.     \!dimenput {\box\!boxA} [Bl] <\!Xsave,\!Ysave> (\!zpt,\!dimenA)
  3658.   \else
  3659.     \setbox\!boxA=\hbox{%
  3660.       \def\\##1##2{%
  3661.         \!dimenput {##2} [r] (\!axisxlevel,##1)}%
  3662.       \beginpicture 
  3663.         \!LTlist
  3664.       \endpicturesave <\!Xsave,\!Ysave>}%
  3665.     \!dimenA=\!axisxlevel
  3666.       \advance\!dimenA -\!Xsave
  3667.       \advance\!dimenA \!tickxsign\!offset
  3668.       \if -\!tickxsign
  3669.         \advance\!dimenA -\wd\!boxA
  3670.       \fi
  3671.     \advance\!offset \wd\!boxA
  3672.     \!dimenput {\box\!boxA} [Bl] <\!Xsave,\!Ysave> (\!dimenA,\!zpt)
  3673.   \fi}
  3674.  
  3675.  
  3676. \normalgraphs
  3677. \catcode`!=12 %  *****  THIS MUST NEVER BE OMITTED
  3678.