\message{==================================================================}%
\message{<Paul Taylor's commutative diagrams - version 3.96, December 2019>}%
%%
%%
%% This code runs the LaTeX \ProvidesPackage command iff it is defined.
%% included at the request of Michael Downes <mjd@ams.org> March 2002.
%% Put \listfiles in your LaTeX preamble to see what this is for.
\expandafter\ifx\csname ProvidesPackage\endcsname\relax\toks0=\expandafter{\fi
\ProvidesPackage
   {diagrams}[2019/12/31 v3.96 Paul Taylor's commutative diagrams]%%
\toks0=\bgroup}%%
%%======================================================================%
%%      TeX  macros for drawing category-theoretic diagrams             %
%%                                                                      %
%%                              Paul  Taylor                            %
%%                                                                      %
%%             		www.PaulTaylor.EU/diagrams			%
%%	www.ctan.org/tex-archive/macros/generic/diagrams/taylor/	%
%%			   diagrams@PaulTaylor.EU			%
%%                                                                      %
%%                           PLEASE READ THE MANUAL!                    %
%%                                                                      %
%%      Please ensure that you are registered with me as a user so that %
%%      you can be informed of future releases.  Any electronic mail    %
%%      message with "commutative" or "diagram" in the subject line     %
%%      (such as your request for the package, a question about it, or  %
%%      even an otherwise blank message) automatically registers you.   %
%%                                                                      %
%%                                                                      %
%% CONTENTS:                                                            %
%%  (O) corruption-sensitive hacks    (to approx line 318)              %
%   (1) dimensions and counts                                           %
%   (2) make arrow parts                                                %
%   (3) new arrow                                                       %
%   (4) horizontal state checking and arrow setup                       %
%   (5) syntax of arrow commands                                        %
%   (6) positioning and optional arguments                              %
%   (7) the diagram - options and output                                %
%   (8) the matrix                                                      %
%   (9) horizontals                                                     %
%  (10) piles                                                           %
%  (11) verticals                                                       %
%  (12) transfer to box arrays                                          %
%  (13) paragraph bombing                                               %
%  (14) reformatting objects and crosses                                %
%  (15) LaTeX line characters                                           %
%  (16) diagonals                                                       %
%  (17) stretchable diagonals                                           %
%  (18) PostScript arrows                                               %
%  (19) trigonometry                                                    %
%  (20) PDF-TeX support                                                 %
%  (21) error recovery                                                  %
%%      Arrow components & commands - starts approx line 1234           %
%% (22) auxillary macros for adjustment of components                   %
%% (23) bits of arrows  (\rhvee etc)                                    %
%% (24) arrow commands  (\rTo etc)                                      %
%% (25) miscellaneous                                                   %
%% Apart from these five sections, the rest is intended to be totally   %
%% meaningless in the undocumented version, which is approximately      %
%% 1922  lines long. Please do not waste trees by printing it out.      %
%  This is because I regard my code as private. The comments contain a  %
%  lot of fossils, ideas and other notes to myself which I do not wish  %
%  to make available to others. If you're reading this, please stop now.%
%%                                                                      %
%% COPYRIGHT NOTICE:                                                    %
%%      This package may be copied and used freely for any academic     %
%%      (not commercial or military) purpose, on condition that it      %
%%      is not altered in any way, and that an acknowledgement is       %
%%      included in any published work making substantial use of it.    %
%%                                                                      %
%%      IT IS SUPPLIED "AS IS", WITHOUT WARRANTY, EXPRESS OR IMPLIED.   %
%%                                                                      %
%%      If you are doing something where mistakes cost money (or where  %
%%      success brings financial profit) then you must use commercial   %
%%      software, not this package. In any case, please remember to     %
%%      keep several backup copies of all files, and check everything   %
%%      visually before sending final copy to the publishers.           %
%%                                                                      %
%%      You may use this package as a (substantial) aid to writing an   %
%%      academic research or text book on condition that                %
%%       (i) you contact me at a suitable time to ensure that you have  %
%%           an up-to-date version (and any infelicities can be fixed), %
%%      (ii) you send me a copy of the book when it's published.        %
%%                                                                      %
%% HISTORY                                                              %
%% 3.95 Released 31 December 2014					%
%%	Fixed spurious extra vertical space when running under LuaTeX	%
%	by adding \baselineskip\z@ to \bomb@parameters  14 May 2014	%
%%	with help from Linas Stonys.					%
%% 3.94 Released 11 May 2011						%
%%	defined <= tail							%
%% 3.93 Released 9 June 2009						%
%	added \pdfsyncstop to avoid clash with pdfsync			%
%	\ifx\diagram\isundefined					%
%	removed obsolete \laf \lad \xlad \lahh \lat \xlat \xlahh	%
%       changed \lq and \rq back to ` and ' for catcodes and octals.	%
%%	Added support for XeTeX, with help from Apostolos Syropoulos.	%
%% 3.92 Released 31 December 2007                                       %
%	Made noPS and noPostScript just generate error messages.	%
%       Unknown PS translator is just ignored.				%
%	Swapped \Yup and \Ydown						%
%       Two-year (instead of one-year) time-bombs.                      %
%% 3.91 Released 31 August 2006                                         %
%%	Renamed "noPostScript" option as "UglyObsolete".		%
%       Fixed? "PostScript translator `' unknown"			%
%       \everymath{}\everyhbox{} since pdfsync sets them                %
%% 3.90 Released 11 April 2004                                          %
%%      use PostScript=Rokicki not pure DVI by default                  %
%       pass PS prog name to \bad@ps@prog as #1 not as \@value          %
%       always warn that "labels as positional arguments are obsolete"  %
%       as ``superscript'' labels were introduced 14 years ago          %
%       test \ifx\pdfoutput\relax as well as \undefined                 %
%% 3.89 Released 7 July 2002                                            %
%%      Added support for pdftex, which is recognised automatically.    %
%% 3.88 Released 1 September 2000                                       %
%%      Square hook tail: \newarrow{SquareInto}{sqhook}--->             %
%% 3.87 Released 1 September 1999                                       %
%%      This version was used for the final 1200dpi PS copy of my book  %
%%      ``Practical Foundations of Mathematics'' (Cambridge Univ Press) %
%%      see   http://www.PaulTaylor.EU/Practical_Foundations            %
%% 3.86 Released 1 September 1998                                       %
%%      New options hug and nohug in PostScript mode: [PS,nohug] uses   %
%%      PS for the arrows without rotating the labels, but the way of   %
%%      calculating the actual position of these horizontal labels on   %
%%      will remain subject to alteration for some period of time ---   %
%%      please send me examples if you feel that adjustment is needed.  %
%%                                                                      %
%       flushleft/leftflush with no value retains old one, not 0pt      %
%       Suppress indentation of following text (due to LaTeX change)    %
%       inserted \global before \@ignoretrue                            %
%       Mangle \left@label and \right@label (conflict with Elsevier).   %
%%      midvshaft and snake for vertical arrows                         %
%       labels on verticals are now inside the lower \vbox              %
%%      New option [gap=width] (default=shortfall) to use instead of    %
%%      ~{\;} on horizontals and PS diagonals, as this caused ^ and _   %
%%      labels to be moved too far away from the shaft.                 %
%       Corrected position of hook in \dInto (see \shifthook).          %
%       Added 2pt space separating labels from vertical arrows.         %
%       Corrections to \lhtriangle \dhtriangle \newarrowtail{boldhook}  %
%%      Added >-> and <-< heads and tails, same as >> and << but the    %
%%      shaft goes *through* the extra arrowhead.                       %
%       Identify the cell in which a second-pass error occurs.          %
%       Corrected dot spacing with [dotted] option.                     %
%       (It was using \hfdot or \vfdot not \rf:. or \df:.)              %
%% 3.85 Released 20 August 1997                                         %
%%      New option [crab=distance] shifts horizontals and PS diagonals  %
%%      transversally by the specified distance (positive=upward).      %
%%      New option [snake=distance] shifts midshaft horizontals and     %
%%      PS diagonals longitudinally by the specified distance.          %
%       Set \catcode of :;!? as babel package makes them \active.       % 
%       \dblvert for ``Practical Foundations''                          %
%       Moved pullback symbols slightly further away.                   %
%       Fixed uneven \pile spacing.                                     %
%       Treat empty row as \noalign{\advance\prevdepth-\baselineskip}   %
%       Unknown PostScript translator names recognised.                 %
%       Parse space in $A\rTo^a _b B$ correctly.                        %
%       Big \LaTeX arrowheads with [thick] option.                      %
%%      New option [leftflush], like [flushleft] but reckons alignment  %
%%      from multiple verticals, or from text if there's no vertical.   %
%       Crude implementation of nohug.                                  %
%%      Most of the history has been suppressed from the user version.  %
%  3.84 Released 2 September 1996                                       %
%       Fixed undefined control sequence in \luOnto[dotted,PS]          %
%       moved \let\fill@dot\hfdot from \Horizontal@Map to \@setup@horiz %
%       Use \AtEndDocument to give once only warnings.                  %
%       Report unknown grid correctly.                                  %
%       Provided \NWclck etc 2-cell arrows.                             %
%% 3.83 Released 18 May 1995                                            %
%%      "dotted" option (set dot filler on maps)                        %
%       repositionpullbacks moved 0.25em horizontally                   %
%       fixed bug when \v@grid is longer than required                  %
%       added \relax in \over@print to avoid premature expansion        %
%       (to fix bug with repositionpullbacks \NWpbk and \SWpbk)         %
%       Fixed bug with interaction with amslatex/equation.              %
%       reported by Bruce Pollack; caused by \everycr.                  %
%%      Parallel maps (\pile) outside diagrams stretch correctly.       %
%       Added test \ifinpile to glue in horizontal maps.                %
%       Avoid stepped lines in PostScript by restricting the slopes.    %
%       Define \default@max@fraction=\default@size/5\pixel@size.        %
%       Rightmost width now calculated correctly.                       %
%       \reoutput@cell had spurious \box\cd@cell in it.                 %
%       Fewer "arrow too short" errors (the l> option for eliminating   %
%       birds' feet arrows is only applied in text, l>.5em in diagrams).%
%       Setting \dimen2 in \@setup@horiz, \default@args, \calc@horiz.   %
%       Recovery from "\rTo_\hbox{a}" no longer loops.                  %
%       Match TeX's inserted { with \eegroup instead of \egroup.        %
%       "midshaft" option now works; "midvshaft" ignored.               %
%%      Option "LaTeXeqno" uses LaTeX's equation number and style       %
%%      for "eqno";  LaTeX's \label command picks this up.              %
%%      Suppress warnings & 2nd pass errors with "silent" option.       %
%       Warning if extra material in \pile cell.                        %
%       Recover from square brackets mis-interpreted as options.        %
%  3.82                                                                 %
%% 3.81 Second alpha release 18 July 1994                               %
%       Fixed displaced parenthesis instead of hook tails in manual p8. %
%       By changing \box0 to \box3 in \raisehook (LaTeX2e \boldmath).   %
%       Parentheses and braces (not quite right): see end of source.    %
%%      \overprint{text} sets text in maths and overprints it in the    %
%%      current cell, centered in the column irrespective of other stuff%
%%      "repositionpullbacks" option uses this for \SEpbk etc           %
%%      \newdiagramgrid declaration, grid option and pentagon grid.     %
%% 3.80 Alpha release for adjusted diagonals 15 July 1994.              %
%       Some options can now take (x,y) values.                         %
%       Position during input as (\cd@row,\cd@cell); top left is (1,1). %
%       Name of DVI->PS translator as argument to PostScript option.    %
%       Preliminary code for stretchable diagonals and overprints:      %
%       \missive#1(x,y) anywhere in the diagram overprints #1 at (x,y). %
%       The extra boxes are added to the left of each cell, delimited   %
%       by \penalty-9990; this caused the paragraph builder to discard  %
%       the \hfil\kern(shortfall) on the left, so added \null.          %
%       Improved recovery from missing {} in labels.                    %
%       Recovers from \rTo~\rTo,  \rTo^\hat,  \rTo^\macro,  {\rTo^},    %
%       \rTo^ {&, ...                                                   %
%       Removed error message from \across since this works now.        %
%       Set \boxmaxdepth=\maxdimen for interaction with an old LaTeX.   %
%       Loading after \begin{document} in LaTeX2e possible.             %
%       (By testing whether \DeclareOption has been disabled (yuck).    %
%       Loading before \documentstyle or \documentclass possible.       %
%       (By defaulting \MapBreath and \default@mapbreadth to 0.4pt;     %
%       the latter is \edef'd in \size@dependencies.                    %
%       Equilateral triangle or regular hexagon size options.           %
%       \mathon and \mathoff correctly matched now, it seems.           %
%       Corrected Morse code for "P" (Ralph Loader)                     %
%       Changed all \new@if to \if@blah@. Added \if@in@matrix@.         %
%      Introduced landscape and portrait options.                      %
%       Define PS commands once for each (outermost) diagram needing    %
%       them; previously they were defined for every map.               %
%       Don't hide width of vertical middle components.                 %
%       (Changed \make@vert@part to \hbox in \newarrowmiddle.)          %
%       Negative stretchability in right half of horizontal arrows.     %
%       Added "." map qualifier to set dot filler.                      %
%       Only set \@diagonals@used@ for those set on first pass.         %
%       Parse []-options during label processing.                       %
%       Signal midhshaft with extra \penalty1 just before bomb.         %
%       Made midhshaft work; always set it for single-row diagrams.     %
%       Rewrote \widen@horiz, changing tests for space and handling of  %
%       through and centred horizontals.                                %
%       Maintain distance of each row from the top as \ht\cd@row on     %
%       rows which have been reformatted; used to calculate height of   %
%       diagonals.                                                      %
%       \diagramstyle may be used within diagrams.                      %
%       (Continuation, \after@opt@arg, not set, so did \@@@diagram.)    %
%       \objectwidth reduced from 3em to 1em; was destroying fixed      %
%       diagonals.                                                      %
%       Fixed "very" thick lines by changing \cds@thick.                %
%       All inter-row glue contributes to space.                        %
%       Vertical maps targetted at labels of horizontals avoid them.    %
%       Wide object on right no longer causes "increase width" warning. %
%       (Initialise \far@end@cell=1000 on right, don't complain about   %
%       insufficient space between objects if it still has this value.) %
%       Make these warnings more accurate and informative.              %
%       Fixed decapitated arrows (I think!).                            %
%       Now use \wd\cd@donat for \column@placing ie x-coord of centre.  %
%      Diagonals adjusted to meet their endpoints, at last!!!!         %
%       \min@map@length=0pt inside diagrams (?).                     %
%       Option showfirstpass[=depth].                                   %
%       Fixed intermittent "lower part of vertical too short" errors:   %
%       wasn't collecting the vertical glue below missives.             %
%       Missive aimed at horizontal map caused huge \right@donated: was %
%       overwriting \dimen2; moved most of the code within an \hbox.    %
%  3.29 Released 11 March 1994                                          %
%       Corrected error message when "&" or object is inserted before   %
%       horizontal maps etc outside diagram.                            %
%       \last@map@type initialised to \empty, when we just say "before".%
%       Also when label missing after <>^_~.                            %
%       Switch to centredisplay if flushleft doesn't fit on the page.   %
%       The code was ok when the diagram didn't fit at all, but not in  %
%       the case where it would fit in centredisplay mode.              %
%       Added Y head & tail from St. Mary Rd. font (not yet adjusted).  %
%       First attempt to support LaTeX2e \usepackage options.           %
%       Fixed bug (missing \endgroup and no arrow) with \rTo[opt][opt]. %
%       (The continuation, \after@opt@arg, had got overwritten.)        %
%       Set \mathsurround=0pt for everything within our code.           %
%       Already set in \inner@environment and in \make@horiz@part but   %
%       not when \math@on & math@off are (re)made in \size@dependencies.%
%       Also set it in \default@args for horiz maps outside diagrams.   %
% 3.28 Released 30 November 1993                                       %
%       Fixed bug causing diagram to disappear in vert mode in LaTeX    %
%       caused by \everypar overwriting \box0 - use \box2 instead.      %
%      Peter Freyd's \puncture symbol provided.                        %
%  3.27 Released 26 March 1993                                          %
%       Fixed bug which forced LaTeX slopes on PostScript diagonals.    %
%       Got \max@fraction wrong: moved to condition in \exec@diagonal.  %
%       Renamed \put@PS@horiz as \exec@PS@diagonal. Made \exec@horiz    %
%       exclusively horizontal, moving "extra text" test there.         %
%       Call \calc@horiz and \label@horiz from \exec@diagonal instead.  %
%       Restored \max@fraction{255} to PostScript arrows.               %
%  3.26 Released 11 February 1993                                       %
%       Added [defaultsize=] to set \default@size, used if size unset.  %
%       Added 1pt space between label (strut) and horizontal shaft.     %
% 3.25 Released 30 January 1993                                        %
%       Resolution-dependent fudge (dpi) applied to horizontal arrows.  %
%       Removal of glue from before to after applied to display as well %
%       as textflow, but didn't deal with spurious space after diagram. %
%       Fixed extra height in \rhla.                                    %
%       Fixed \HmeetV vertical profile - bug caused by pixel fudge.     %
%       Defined \if@ignore outside LaTeX, use to control \ignorespaces  %
%       at end of diagram: to cure spurious space in text after         %
%       notextflow diagram.                                             %
%       Added \kern-\displayindent inside $$/$$ to over-ride prevailing %
%       paragraph indentation: to cure shift and over-full \hbox in     %
%       itemized diagram.                                               %
%       Added \make@end@at@line after \egroup in \output@diagram so that%
%       "too wide for page" and "flushleft in $$" can give line numbers.%
%      LaTeX heads made default (unless \tenln undefined, when vee)    %
%       and set (by new \set@default@arrowhead) in horiz outside cd too.%
%       Also cures zero-length shafts of arrows in text in footnotes.   %
%       Made \labelstyle and \objectstyle available as options.         %
%       Diagram options and output as new section; some reorganisation. %
%       New display options give warning if used within maths.          %
%       Catch missing bracket at end of label and misplaced (but not    %
%       missing) bracket at end of \pile.                               %
%       Small adjustments on some heads and tails. hbox option.         %
%       Braces and parentheses as arrows (bits from cmex) commented out.%
%       Bits of double vert arrows use cmex not \Vert\Uparrow\Downarrow %
%      Circle, cross, little vee, little black triangle heads.         %
%       Fixed spaces before & after diagram in display and textflow.    %
%       Catch em-braced arrow commands.                                 %
%       Adjusted hook tails yet again (some theory behind horizontals!).%
%       Smashed height of \rhla \lhla \rtla and \ltla.                  %
%       Default \MapBreadth as TeXbook p447; pixel round on input.      %
%       Apply pixel rounding to \make@vert@part and \shifthook.         %
%      First-use warning when defaulted diagonal components are used.  %
%       Warning if diagonals used & columns stretched significantly.    %
%       Warning if diagonals with repeating components are too short.   %
%       Added \@use@TPIC@false to diagonal dot repeater.                %
%       Changed setup of diagonal maps; now \+To gets immediate control,%
%       sets defaults, calls \rTo (having changed \Horizontal@Map) and  %
%       the test to use PS is after the arguments have been read.       %
%       Local PostScript option (PS, noPS), disabled by noPostScript.   %
%       Collected all size-dependent initialisations in one macro, which%
%       is executed before \diagram, \diagramstyle or text arrows.      %
%       Allowed curly instead of square brackets in \diagramstyle.      %
%       Also \diagramsstyle.                                            %
%      AMSTEX emulation - works at least when amstex not present.      %
%       Check for \diagram options changed to \futurelet (the earlier   %
%       problem with this lay in using \next@token twice), so it now    %
%       catches a blank line after \diagram or \begin{diagram}.         %
%       Fixed \HmeetV yet again.                                        %
%       Added Morse Code signature to every 20th suitable horizontal.   %
%       Position horizontal labels using strut rather than \baselineskip%
%       Change definitions of default components from \def to \let.     %
%       This brought lower \scriptstyle labels closer to horizontals.   %
%       Use \boldmath for littlevee and hooks, if available. (DUBIOUS)  %
%       Vertical position of labels on diagonals had been unset!        %
%       Increased interim assumed \objectheight from .5ex to 1.8ex and  %
%       isolated \interim@shortfall.                                    %
%       Removed \outer from \diagramstyle.                              %
%       Lots of adjustments to bits of arrows (drives me mad!).         %
%% 3.24 Release 7 Sept 1992 advertised to users.                        %
%       Continued fractions, sine, cosine & pythagorean sum.            %
%       \newarrow etc also define \+To \-To \nwTo                       %
%       Rewrote LaTeX diagonal code:                                    %
%       uses continued fractions to find nearest slope and selects      %
%       character; diagonals touch a square around the (maths axis)     %
%       centre of the endpoints; middles; through diagonals.            %
%       \lq and \rq (instead of ` and ') for catcodes and octals.       %
%       Made it consistent with texinfo - for loading, at least.        %
%      PostScript option introduced:                                   %
%       \Rising@Map and \Falling@Map choose the horizontal command and  %
%       run \put@PS@horiz;                                              %
%       labels are rotated together with the arrow,                     %
%       which is set in the first pass                                  %
%       meets a circle and is not yet adjusted for its endpoints.       %
%      LaTeX, vee, curlyvee, triangle & blacktriangle heads & tails    %
%       provided and correctly adjusted; double heads & tails all made  %
%       with \make@double@head.                                         %
%      TPIC option introduced as an alternative to \LaTeX@make@line.   %
%  3.23 (14.5.92) experimental release on 10 July 1992                  %
%       Fixed pilespacing, and horizontal positioning of verticals      %
%       (bugs which arose from Seely's challenge). Also made need extra %
%       message work. Discovered that \get@arg finds \end@cell, not &,  %
%       so removed {} from \tokcase and \catcase, so the \mathord{}s    %
%       disappeared.                                                    %
%       Fixed vmiddle positioning of one-row diagrams.                  %
%       Fixed catastrophic error of empty first cell in nested diagram  %
%       by using \bbgroup\eegroup around the diagram.                   %
%       Moved making of \math@on@box to inside \bombparameters because  %
%       it caused "math formula deleted - insufficient fonts" if loaded %
%       before \documentstyle. deleted \defaultarrowhead{vee} for same. %
%  3.22 (14.5.92) experimental release                                  %
%  3.21 (1.5.92)                                                        %
%       Extra line of paragraph, to contain profile information.        %
%       Implemented \shift (\cd@hshift).                                %
%       Use \wd\cd@donat for column widths.                             %
%       New reformatting program.                                       %
%       Re-arranged the code.                                           %
%       Optional arguments on \diagram, maps and \diagramstyle.         %
%       Horizontal \shift; tight cell width and height (option).        %
%       top, vmiddle, bottom positioning - aligns chosen maths axes     %
%       origin, balance, nobalance horizontal positioning               %
%       Made \PileSpacing between verticals local.                      %
%       Fixed \HonV and \HmeetV profile. Included verticals in width.   %
%       Piles vertically centered ignoring outer labels.                %
%       Labels on horizontal maps positioned using \baselineskip 1.3ex. %
%       Extra .2ex spacing around labels removed, .2em reduced to .1em  %
%       midshaft option to centre labels in horizontal arrow shaft.     %
%       Through horizontals and verticals.                              %
%       \@and\sp\sb\space in \switch@arg; local catcode &,$             %
%       Re-wrote mangletex to substitute our internal command names.    %
%       \CellSize=default on entry, in case the font size is different. %
%       \across adds its with to \cd@hshift                             %
%       Fixed unterminated verticals and cross profiles.                %
%       Move labels away from wide vertical arrow middles.              %
%       Added strut in \get@label to stop verts hitting middle labels.  %
%       Re-wrote \newif to make it manglable.                           %
%  3.20 (29.4.92) early release of version 4                            %
%  3.19 (9.4.92)                                                        %
%       Ensure \enddiagram occurs only at correct {}-level              %
%       by using \aftergroup.                                           %
%       Blank line and \par within diagram =\enddiagram.                %
%       Clashing (horizontal) arrows detected at first pass             %
%       using an automaton;                                             %
%       "&" (etc) inserted, with error & help messages.                 %
%       \Pythagorean@sum.                                               %
%      Postscript arrows (basic code).                                 %
%      Implemented \newarrow \newarrowhead etc.                        %
%       Corruption-sensitive characters avoided wherever possible.      %
%       Reloading prevented.                                            %
%      Horizontal arrows outside diagram can stretch by wordspacing.   %
%  3.18 (18.12.90) bugfix                                               %
%       Diagonals (other than basic ones) moved to extra-diagonals.tex. %
%       Changed \lt and \gt to \lessthan and \greaterthan for Roy Crole.%
%      Added < and > for labels on left and right of arrow;            %
%       also [] for optional arguments on arrows (not used yet);        %
%       also displaced \catcase\bgroup (positional label) to speed up a %
%       bit as this is obsolete.                                        %
%  3.17 (10.9.90) bugfix                                                %
%       \offinterlineskip in \make@vert@part                            %
%       \endgraf instead of \par (because LaTeX changes it)             %
%       \leavevmode before diagram to fix LaTeX-interaction bug         %
%       \cong as a middle (problem was \mathpalatte within \edef)       %
% 3.16 (20.7.90) as mass mailed; only have mangled version             %
%       \DiagonalLineSegments=\ObsCount                                 %
%       \dmcornervert et seq commented out                              %
%  3.15 (1.7.90) numbered boxes for columns                             %
%       left part of horiz arrow in \box2 (\across not yet fixed)       %
%       bugfixes:                                                       %
%       spacing of \pile's                                              %
%       horizontal alignment of top of verticals - remove spurious space%
%       horizontal alignment of verticals - \make@vert@part             %
%       zero height & depth of vertical parts to not force lines apart  %
%  3.14 (1.7.90) bugfix:                                                %
%       parsing \across - remove spurious &                             %
%       horizontal alignment of bottom of multiple verticals.           %
%       \lhla arrow the right way round.                                %
%       add \MapShortFall and \MapCorner                                %
%  3.13 (2.6.90) A lot?                                                 %
%  3.11 (18.4.90)                                                       %
%       Catch obsolete parameters, rename some dimensions, added to     %
%       \bombparameters. Changed template.                              %
%  3.03 (18.4.90) re-arranged code; a lot of changes?                   %
%  3.02 (3-7.2.90)                                                      %
%  3.01 (9.1.90) vertical reformatting; only have mangled version       %
%% -- all following version numbers are post-facto --                   %
%%  3   (Jan 90) stretching vertical arrows                             %
%   2.8 (2.1.90) new reformatting                                       %
%   2.6 (30.12.89) added \pile                                          %
%%  2   (Sept 89) horizontals stretch to objects; "superscript" labels  %
%%  1   (1987) horizontal arrows stretch to edge of cell                %
%%  0   (1986) implementation of Knuth's TeXercise 18.46 for my thesis  %
%                                                                       %
%%======================================================================%

% BUGS
% mangle \@name

% "Commutative Diagram: "&*&" inserted between horizontal map and pile."
% in inline diagram

% Silvio Levy <levy@msri.org> 13 Sept 2006 - see examples
% width of diagram takes account of labels on arrows but not
% the width of the last row of objects

% signature on squashed arrow
% re-sort the obfuscation list, as Robin Houston has found the macros.

% missing } after \pile doesn't recover

% \across doesn't work with grid
% this code wasn't updated when we changed the use of \column@placing
% \ldTo^~p
% \begin{diagram} ended by \end{displaymath} causes havoc!

% When a diagram is immedately followed by a footnote, there is no
% space between the bottom of the diagram and the footnote rule.

% \begin{diagram}[htriangleheight] with default \DiagramCellHeight
% - Volker Schubert <volli@tunix.mathematik.uni-stuttgart.de> 5 Feb 1997

% midshaft on objects in a \pile

% $R:X\rEmbed[heads=littlevee,l>=1.5em] Y$ is not very pretty:
% \verb/$R:X\rEmbed[heads=littlevee,l>=1.5em] Y$/.

% make the rule in \verb/\upperBrace/ thicker and shorter;
% the vertical brace is also ugly.

% switch to balance within flushleft doesn't work

% make bottom right of negative gradient diagonals 2pt less shortfall

% doesn't insert } correctly in
% \uInto<{b_!={!_L^*} \adjoint \dOnto>{b^*}
   
% TO DO THIS TIME
% -     locate option to define origin of coordinates for diagonals
% -     text in the middle of right triangles
% -     diagonal pullback symbols
% -     handle \verb/\qed/

% -     \verb/vtriangle/ is too narrow (or too tall).
% -     we really ought to have curved arrows!
% -     define \verb/\Nanti/ and \verb/\Sclck/ 3/8-circle little arrows
% -     do ``\verb/=/'' middle using two ruled lines.
% -     wavy diagonal lines.

% -     check interaction of landscape with other positioning options
% -     option to set left or right width of object, rather than the shift
%       2-cells near vertices, offset annotation of vertices.
% -     annotation on arrowheads and XYpic adjustable positioning of labels
% -     Font sizes (line10) & \CellSize for slitex and 11pt/12pt (scaling?)
%       default rule breadth in slitex.
% -     give co-ordinates of cells (their line numbers?) in error messages

% TO DO NEXT TIME

% DIAGONALS
% -     steep \rdTo_u places the label very low down
% -     dashed diagonal should perhaps be dotted outside PS
% -     with shallow LaTeX diagonals, measure the width, not the height
% -     option to link diagonals to corners of objects instead of
%       aiming at the centres of the cells.

% OUTPUT OPTIONS
% -     argument to origin option
% -     re-calculate \prevgraf based on height of diagram and \baselineskip
% -     allow for short line before displayed diagram
% -     \output@cell doesn't take account of everything that sticks out.
% -     textflow diagram disappears immediately after displaymath envt.
% -     some rows remain unreformatted: one-line diagram enclosed in
%       \begin{diagram} \end{displaymath} in ptbook.sty.
% -     textflow generating horizontal space in paragraph (manual, page 3)

% BITS OF ARROWS
% -     make test file for all arrow styles and measure shortfall
% -     LaTeX diagonal double tails need to be brought in a bit
% -     option for shaft to go through double arrowhead; use difference in
%       width of head and tail to choose spacing of double heads
% -     curved corners on \HmeetV and half arrows; jumps and solders.
% -     loops on vertices: see Pino's bits
% -     electronic components
% -     \nwarrow etc as (1,1) LaTeX diagonals
% -     horizontal shaft one pixel too low for LaTeX heads and one pixel
%       too high for curlyvee, at 300dpi
% -     pixel adjustment on LaTeX diagonals
% -     move the dots closer together

% DIAGNOSTICS
% -     count number of lines since last & (\end@cell is more accurate)
%       we do this (\cell@at@line), but what for?
% -     make manual a LaTeX2e document.
% -     "maps must never be enclosed in braces" from shifted diagonal
% -     decide and document how much unterminated arrows stretch
% -     lower unterminated downward verticals
% -     allow unterminated maps to stretch to their natural width
% -     classified summary of options in manual; list of errors,
%       shift labels in options description to right
% -     option not to load error messages (ask how many users care about this)
% -     new display options should detect $$ not $ (probably useless in latex)
% -     missing \endcsname in various places:
%       in LaTeX2e \usepackage[flushleft=\mainindent]{diagrams}
%       in zed.sty from <> in diagrams.tex and \newarrow{blah}---->

% IDEAS
% -     make midvshaft work
%       all of the labels on a system of parallel verticals must align
% -     parametrise size of pullback symbols and crosses
% -     rewrite amscd.sty
% -     half arrows
% -     adjunction environment
% -     time bomb
% -     Lamstex & xypic fonts
% -     private version of \def with option to check re-definition; also
%       re- & \global loading - with the aim of doing it on first use
% -     \protect to arrows in section headings
% -     more space around labels on in-text arrows if in \displaystyle


% UNREPEATABLE BUGS
% -     \pile{text\rTo\\text\rTo} doesn't stretch correctly
%       seems to work.
% -     missives addressed to empty cells are lost - give error message
%       they appear to be handled ok.

% COMPLAINTS AND WISHES
% -     \hidewidth in objects causes arrows to overprint
% -     \rTo{}{} puts struts in both labels - forces \pile apart (obsolete)
% -     can't catch runaway argument to \pile
% -     multi-line labels with embedded arrays
%       this would have same problem as \pile in catching missing closing brace
%       long objects doing this automatically (paragraph?)
%       set up complete environment for labels
%       allow Sb and Sp environments for label? can't see any way!
% -     LaTeX center environment is unrestricted horizontal
%       may want restricted horizontal mode behaviour there.
% -     could \catcode`\&=\active etc and re\catcode (for texinfo)
% -     write size information to .aux? what?
% -     draft mode - what should(n't) it do?
% -     strings, Feynman diagrams, ...
% -     curved lines: see /home/leonardo/tex/contrib/Gnu/gs23/escher.ps
%       sorry, this doesn't work with dvips because it does ``bind def''
% -     \diagram[notextflow]..\enddiagram\begin{something}..\end{something}
%       makes \end{something} do \ignorespaces.
% -     prevent pagebreak before textflow diagram? penalties seem ok
% -     Dusko wants automatic hidden line elimination
% -     option to set the width of each column individually using missives
%       (grid option does this ok, I think)
% -     (probably) cannot work with TeX-XeT because of extra whatits
% -     macros as diagram options (Volker Schubert)
%
%%======================================================================%
%%                                                                      %
%%      (1) CORRUPTION-SENSITIVE HACKS                                  %
%           AND PROGRAMMING FEATURES                                    %
%%                                                                      %
%%======================================================================%

%%                      CORRUPTION & \catcode WARNING

%% BITNET (IBM) machines may corrupt certain important characters
%% in transmission by electronic mail:
%%        0123456789=digits, abcdefghijklmnopqrstuvwxyz=lowers,
%%        ABCDEFGHIJKLMNOPQRSTUVWXYZ=uppers, @=at (internal names),
%%        {}=curly braces (grouping), \=backslash (keywords),
%%        %=percent (comment), #=hash/sharp (argument), +=plus, -=minus,
%%        <>=angle brackets (relations \ifnum,\ifdim), ==equals,
%%        ,=comma, .=dot, :=colon, ;=semicolon,  =space
%% $=dollar (maths) is only used in the "bits of maps" section

%% The following characters are marked by a comment including the word "ASCII",
%% except in comments and messages:
%%        &=and (alignment), ~=tilde, |=vertical, []=square brackets,
%%        ^=caret (superscript), _=underline (subscript),
%%        "=double quote (hex), ()=round brackets,
%%        /=slash, ?=query, !=pling/bang, 
%% The following are no longer flagged:
%%        `=grave/backquote (catcodes), '=acute/single quote (octal),

% check by the command:
%       sed -e 's/.*%ascii.*//' -e 's/%.*$//' < diagrams.tex |\
%       grep -n '[][&()*?|~^_/\!\"']

%       Andrew Molitor <amolitor@wesleyan.earn> 27.3.91 says:
%       caret became a space or was eaten entirely, not sure which,
%       and tilde became a caret.

% changed \lq and \rq back to ` and ' 15.10.2008 (v3.93)
% as part of the adaptation to XeTeX proposed by
% Apostolos Sypopoulos <ijdt.editor@gmail.com>

%% The \catcode's marked * are assumed for reading this file:
%%          \=0* {=1* }=2* $=3 &=4 return=5* #=6 ^=7 _=8 ignored=9*
%%          space=10* letter=11* other=12 active=13 %=14* invalid=15
%% If you want to load this package inside Stallman's "texinfo", you must do
%% @catcode`@\=0 \catcode`\%=14 \input diagrams \catcode`\%=12 \catcode`\\=13
%% and then use @diagram @rTo @\ @enddiagram etc. (braces {} stay the same).
%% Also need @catcode`@&=4.

%%*** You *MUST NOT* use the internal commands (with names beginning \CD@)****
%! p \CD@
%! m \across@cells
% m \actually@braces@missing@around@macro@in@label
%! m \add@and
%! m \add@and@and
%! m \add@cr
%! m \add@dollar
%! m \add@empty@and
%! m \add@endpile@and
%! m \add@relax@before@square@bracket
%! m \@adjust@flush@left@false
%! m \@adjust@flush@left@true
%! m \after@diagram
%! m \after@name
%! m \after@names
%! m \after@opt@arg
%! m \amstex@diagram@setup
%! m \amstex@prefix
%! m \@and
%! m \and@in@pile
%! m \and@name
%! m \assign@at
%! m \assign@five
% m \at@
%! m \at@least
%! m \at@line
%! m \at@most
%! m \avoid@object
% m \axisheight
%! m \axis@profile
%! m \@back
%! m \bad@arrow
%! m \bad@end@label
%! m \bad@group@after@map
%! m \bad@pair@opt
%! m \bad@ps@prog
%! m \bbgroup
%! m \begin@at@line
%! m \@begin@cell
%! m \begin@cell
%! m \begin@maths
%! m \begin@pile
%! m \begin@square@name
%! m \better@use@ps
%! m \bgroup@name
%! m \body@
%! m \body@@
%! m \body@@@
%! m \@bomb
%! m \bomb@parameters
%! m \boxc@unt
% m \@brace
%! m \braced@label
% m \break@args
%! m \buffer@to@row
% m \@c
%! m \calc@horiz
% m \@catcode
%! m \@cd@a@false
%! m \cd@and
%! m \@cd@a@true
%! m \cd@balance
%! m \@cd@b@false
%! m \cd@bottom
%! m \cd@box@g
%! m \@cd@b@true
%! m \cd@cell
%! m \@cd@centre@display@false
%! m \@cd@centre@display@true
%! m \@cd@centre@hlabel@false
%! m \@cd@centre@hlabel@true
%! m \@cd@centre@vlabel@false
%! m \@cd@centre@vlabel@true
%! m \cd@cross
%! m \cd@diag@zer
%! m \cd@dim@a
%! m \cd@dim@b
%! m \cd@dim@g
%! m \cd@dim@h
%! m \cd@dim@k
%! m \cd@display
%! m \cd@display@box
%! m \cd@donat
%! m \cd@environment
%! m \cd@eqno
%! m \cd@error
%! m \cd@first@use
%! m \cd@fullwidth
%! m \@cd@g@false
%! m \cdgh@
%! m \@cd@g@true
%! m \cdgv@
%! m \@cd@hbox@false
%! m \@cd@hbox@true
%! m \cd@horiz@positioning
%! m \cd@hshift
%! m \@cd@landscape@false
%! m \@cd@landscape@true
%! m \cd@left
%! m \cd@left@donat
%! m \cd@left@margin
%! m \@cd@leqno@false
%! m \@cd@leqno@true
%! m \@cd@missive@false
%! m \@cd@missive@true
%! m \cd@mode@outside
%! m \cd@name
%! m \cd@num@a
%! m \cd@num@b
%! m \cd@num@c
%! m \cd@num@d
%! m \cd@num@g
%! m \cd@num@h
%! m \cd@obs@count
%! m \cd@obs@dim
%! m \cd@obs@dimq
%! m \cd@obs@msg
%! m \@cd@one@liner@false
%! m \@cd@one@liner@true
%! m \cd@opt@prefix
%! m \cd@penalty
%! m \cdps@  don't mangle any of these!
% m \cdps@Bechtolsheim
% m \cdps@Clark
% m \cdps@dvips
% m \cdps@dvitops
% m \cdps@dvitps
%! m \@cd@PS@horiz@false
%! m \@cd@PS@horiz@true
% m \cdps@IntegratedComputerSystems
% m \cdps@oztex
% m \cdps@RadicalEye
% m \cdps@Rokicki
% m \cdps@Trevorrow
%! m \cd@refmt@error
%! m \cd@right
%! m \cd@right@donat
%! m \cd@row
% m \cds@  don't mangle any of these!
% m \cd@shouldnt
%! m \cd@state
%! m \cd@switch@arg
%! m \cd@text@flow
%! m \@cd@text@flow@false
%! m \@cd@text@flow@true
%! m \@cd@through@false
%! m \@cd@through@true
%! m \@cd@tight@false
%! m \@cd@tight@true
%! m \cd@top
%! m \cd@top@height
%! m \@cd@use@PS@false
%! m \@cd@use@PS@true
%! m \cd@vbottom
%! m \cd@vcentre
%! m \cd@vert@positioning
%! m \cd@vmiddle
%! m \cd@vtop
%! m \cd@warning
%! m \cd@with@opt
%! m \cd@zerowidth
%! m \cell@at@line
%! m \cell@height@to@width
%! m \cell@missive
%! m \check@fated@enddiagram
%! m \check@horiz
%! m \check@part
%! m \check@vert
%! m \Climbingfalse
%! m \Climbingtrue
% m \@cmex
%! m \cmex@vert@part
%! m \column@placing
%! m \completed@depth
%! m \complete@horizontal
%! m \complete@last@row
%! m \@complete@vertical
%! m \complete@vertical
%! m \@complete@vspace
%! m \cont@frac@done
%! m \cont@frac@swap
%! m \co@ordinates
%! m \correct@for@width
%! m \crab@
%! m \cr@name
%! m \cross@names
%! m \cross@profile
%! m \cross@strut
%! m \@d
% m \d@brace
%! m \declared@at@cell
%! m \deepen@donations
%! m \default@args
%! m \default@diagonal
%! m \default@mapbreadth
%! m \default@max@fraction
%! m \default@profile
%! m \default@size
%! m \def@name
%! m \def@ps@turn
%! m \denominator@
%! m \diag@is@horiz
%! m \diag@is@vert
%! m \diagonal@box
%! m \@diagonals@used@false
%! m \@diagonals@used@true
%! m \@@@diagram
%! m \@@diagram
%! m \@diagram
%! m \diagram@cr
% m \diagram@help@messages
%! m \diagram@name
%! m \@di@dah
%! m \dim@in@pts
%! m \div@cclvi
%! m \div@dii
%! m \divide@
%! m \do@after@opt@arg
%! m \do@case
%! m \do@cont@frac
%! m \do@fated@enddiagram
%! m \dollar@name
%! m \do@message@at@end@doc
%! m \do@opt@arg
%! m \do@opt@arg@then
%! m \do@pile@row
%! m \do@set@dot@filler
%! m \dot@filler
%! m \double@LaTeX
% m \d@parenth
% m \eat@space
%! m \edef@name
%! m \eegroup
%! m \egroup@missing@label
%! m \egroup@name
%! m \@em
%! m \empty@filler
%! m \empty@name
%! m \empty@parts
%! m \end@at@line
%! m \end@cell
%! m \@enddiagram
%! m \@enddiagram@endpile
%! m \enddiagram@endpile
%! m \end@diagram@name
%! m \@end@diagram@ok@false
%! m \@end@diagram@ok@true
%! m \end@get@csname
%! m \@end@label
%! m \end@label
%! m \end@maths
%! m \end@mess
%! m \@end@pile
%! m \end@pile
%! m \end@square@name
% m \endswitch
%! m \exec@cross
%! m \exec@diagonal
%! m \execDiagonalLine
%! m \@exec@diagram
%! m \exec@diagram
%! m \exec@horiz
%! m \exec@LaTeX@diagonal
%! m \exec@map
%! m \exec@missive
%! m \exec@PS@diagonal
%! m \exec@vert
%! m \exit@diagram
%! m \expanded@ps@special
%! m \expanded@tpic@special
%! m \far@end@cell
%! m \fated@enddiagram
%! m \@filla
%! m \@fillb
% m \fill@dot % don't mangle as we \let@names{fill@dot}{}
%! m \@filler
% m \@fillh
% m \@fillv
%! m \finish@pile
%! m \first@occur
%! m \firstpass@showboxdepth
%! m \@first@positional@false
%! m \@first@positional@true
%! m \five@args
%! m \found@end@diagram
%! m \gdef@name
%! m \get@arg
%! m \@getcoords
%! m \get@csname
%! m \get@interrow@glue
%! m \@get@label
%! m \get@label
%! m \get@mand@value
%! m \@@getoptarg
%! m \get@opt@arg@list
%! m \get@opt@value
%! m \get@profile@info
% m \get@round@pair
% m \get@square@arg
%! m \glet
%! m \glet@names
% m \greaterthan
%! m \group@after@map
%! m \g@tmp
%! m \@h
%! m \handle@at
%! m \handle@at@
%! m \handle@matrix@row
% m \hbox@maths
%! m \@head
%! m \help@and
%! m \help@and@in@pile
%! m \help@bad@group
%! m \help@endlabel
%! m \help@hext
%! m \help@hpile
%! m \help@newarrow
%! m \help@pilecr
%! m \help@pile@enddiagram
%! m \help@undef@map
%! m \help@vext
%! m \help@vpile
% m \h@grid
%! m \horiz@add
%! m \horiz@extra
% m \horizhtdp
% m \Horizontal@Map
% m \Horizontal@Map
%! m \horizontal@name
%! m \horiz@repeater
%! m \horiz@state
%! m \@hug@false
%! m \@hug@true
%! m \if@adjust@flush@left@
%! m \if@cd@a@
%! m \if@cd@b@
%! m \if@cd@centre@display@
%! m \if@cd@centre@hlabel@
%! m \if@cd@centre@vlabel@
%! m \if@cd@g@
%! m \if@cd@hbox@
%! m \if@cd@landscape@
%! m \if@cd@leqno@
%! m \if@cd@missive@
%! m \if@cd@one@liner@
%! m \if@cd@PS@horiz@
%! m \if@cd@text@flow@
%! m \if@cd@through@
%! m \if@cd@tight@
%! m \if@cd@use@PS@
%! m \if@diagonals@used@
%! m \if@end@diagram@ok@
%! m \if@first@positional@
%! m \if@hug@
%! m \if@in@matrix@
%! m \if@need@PS@lib@
%! m \@@ifoptarg
%! m \@ifoptarg
%! m \if@reformatting@
%! m \if@use@TPIC@
%! m \if@was@pair@
% m \ignore@false
% m \ignore@true
% m \incommdiagfalse
% m \incommdiagtrue
%! m \info@at@end
%! m \@in@matrix@false
%! m \@in@matrix@true
%! m \inner@environment
%! m \inner@pile
%! m \intended@breadth
%! m \interim@shortfall
%! m \inter@row
%! m \iterate@
%! m \iterate@@
%! m \iterate@@@
%! m \@junk
%! m \@l
%! m \label@eat@space
%! m \label@egroup
%! m \label@egroups
%! m \label@horiz
%! m \label@optional
%! m \last@map@type
%! m \LaTeX@arrow@char
%! m \@@LaTeX@diagonal
%! m \LaTeX@dot@filler
%! m \LaTeX@line@char
%! m \LaTeX@make@line
%! m \LaTeX@name
%! m \LaTeX@NE
%! m \LaTeX@SW
% m \l@brace
%! m \left@donated
%! m \left@label
%! m \left@LaTeX@tail
%! m \left@over
%! m \left@part
%! m \left@width
% m \lessthan
%! m \let@names
%! m \lift@map@part
%! m \lift@map@parts
%! m \line@char
%! m \line@font
%! m \loop@on@cells
%! m \loop@on@maps
%! m \loop@on@rows
% m \lower@label
% m \l@parenth
% m \@m
%! m \make@diag@part
%! m \@make@double@head
%! m \make@double@head
%! m \@make@double@through@head
%! m \make@end@at@line
%! m \make@filler
%! m \make@found@end@diagram
%! m \make@horiz@part
%! m \make@line
%! m \makeline
%! m \make@old@fill
% m \make@pbk
%! m \make@profile
%! m \make@vert@part
%! m \math@off
%! m \math@off@box
%! m \math@on
%! m \math@on@box
%! m \maths@display
%! m \matrix@row@to@buffer
%! m \matrix@to@buffer
%! m \max@fraction
%! m \message@at@end@doc
%! m \@middle
% m \middle@label
%! m \min@map@length
%! m \misplaced@enddiagram
% m \missing@label
%! m \missive@diagonal
%! m \missive@outside
%! m \missive@to@cell
%! m \missive@to@row
%! m \mk@new@donat
%! m \modify@cell
%! m \monomial@
%! m \more@dim
%! m \more@donations
%! m \@morse
%! m \multiply@
%! m \multiply@@
% m \@name
%! m \name@prefix
%! m \need@extra
%! m \@need@PS@lib@false
%! m \@need@PS@lib@true
%! m \@new@arrow
%! m \newarrow@mmode
%! m \newarrow@name
%! m \new@arrow@part
%! m \new@diagonal
%! m \new@five@map
%! m \new@half@rpt@map
%! m \new@half@rule@map
%! m \new@help
%! m \new@horiz@map
%! m \new@if
%! m \new@line
%! m \new@map
%! m \new@rule@map
%! m \new@simple@map
%! m \new@slant@map
%! m \new@slope@map
%! m \new@thru@map
%! m \new@vector@map
%! m \new@vert@map
%! m \next
%! m \next@opt@arg
%! m \next@token
% m \no@cd@help
%! m \no@check@vert
%! m \no@error@context
%! m \nohcheck
%! m \no@make@line
%! m \@noptcmd
%! m \no@tenln
%! m \numerator@
% m \objectheight
%! m \object@profile
% m \objectwidth
%! m \obs@across
%! m \@obs@countq
%! m \obs@display
%! m \obs@positional
%! m \odef
%! m \old@horiz@fill
%! m \old@horiz@map
%! m \old@horiz@part
%! m \old@vert@fill
%! m \old@vert@map
%! m \one@sp
%! m \@optcmd
% m \optional@
% m \@outer@active
%! m \outer@empty
%! m \outer@environment
%! m \output@cell
%! m \output@diagram
%! m \outside@diagram
%! m \over@print
%! m \overprint@pbk
%! m \@p
%! m \pair@diagram@end
%! m \@par@enddiagram
%! m \par@enddiagram
% m \@parenth
%! m \par@name
%! m \par@not@allowed
%! m \@parse@opt@arg
%! m \parse@opt@arg
%! m \@parse@pair
%! m \pbk@osh
%! m \pbk@sh
%! m \pbk@shsh
%! m \pending@left
%! m \pending@right
%! m \@pile
%! m \pile@cr
%! m \pile@empty@row
%! m \pile@junk
%! m \pile@state
%! m \pixel@round
%! m \pixel@size
%! m \polar@to@rect
% m \positional@
%! m \PositiveGradientfalse
%! m \PositiveGradienttrue
%! m \ps@prog
%! m \push@queue
%! m \push@stack
%! m \put@cd@box
%! m \put@horiz
%! m \pyth@add@term
%! m \Pythagorean@sum
%! m \@pyth@sum
%! m \@r
% m \r@brace
%! m \reassign@filler
%! m \reassign@parts
%! m \receive@cell@type
%! m \reformat@cell
%! m \reformat@complex
%! m \reformat@empty
%! m \reformat@HmeetV
%! m \reformat@HonV
%! m \@reformat@horiz
%! m \reformat@horiz
%! m \reformat@matrix
%! m \reformat@object
%! m \reformat@pile
%! m \reformat@row
%! m \@reformatting@false
%! m \@reformatting@true
%! m \reformat@vert
%! m \reformat@VonH
%! m \reoutput@cell
%! m \resend@missive
%! m \reset@map@breadth
%! m \right@donated
%! m \right@label
%! m \right@LaTeX@tail
%! m \right@over
%! m \right@part
%! m \right@width
%! m \Rotated@Horizontal
%! m \rounded@breadth
%! m \row@depth
%! m \row@height
%! m \row@to@buffer
% m \r@parenth
% m \@rTo
%! m \rule@depth
%! m \rule@height
%! m \save@begin@at@line
%! m \save@cell@at@line
%! m \save@row@no
% m \@scriptaxis
% m \@scriptaxis
% m \script@axisheight
%! m \see@above
%! m \send@cell@type
%! m \separate@verticals
%! m \set@arrowhead
%! m \set@axis
%! m \set@cmex@axis
%! m \set@cmex@offset@axis
%! m \set@col@width
%! m \set@currentlabel
%! m \set@currentlabel@to@equation
%! m \@set@default@part
%! m \set@default@part
%! m \set@default@parts
%! m \set@dot@filler
%! m \set@fraction
%! m \set@h@grid
%! m \set@map@parts
%! m \set@max@fraction
%! m \set@mil
%! m \set@new@display
%! m \set@offset@axis
%! m \set@resolution
%! m \set@resultion
%! m \@setup@horiz
%! m \setup@pile
%! m \set@v@grid
%! m \showboxname
%! m \showname
%! m \show@prevgraf
%! m \showthename
%! m \@signature
%! m \signature@countdown
%! m \size@dependencies
%! m \skip@case
% m \Slant@Map
% m \Slant@Map
% m \Slope@Map
% m \Slope@Map
%! m \snake@
%! m \spAn
%! m \split@pile@row
%! m \square@fraction
% m \@ssaxis
% m \ss@axisheight
%! m \start@bomb@vlist
%! m \stretch@PS@diagonal
%! m \stretch@vert
%! m \@sub
% m \@super
% m \@super
% m \switch@arg
%! m \switch@label@arg
%! m \@szdep
%! m \@tail
%! m \test@loose@diagonals
%! m \test@signature
%! m \the@bomb
%! m \the@default@head
%! m \then
%! m \the@signature
%! m \this@map@type
% m \tmp
%! m \total@donated
% m \to@z
%! m \tpic@make@line
%! m \@u
% m \u@brace
%! m \unbraced@label
% m \undefined
% m \u@parenth
% m \upper@label
% m \Use@line@char
% m \Use@line@char
%! m \use@line@char
%! m \use@name
%! m \use@newarrow
%! m \@use@TPIC@false
%! m \@use@TPIC@true
%! m \using@ps
%! m \@v
%! m \@value
% m \Vector@Map
% m \Vector@Map
%! m \@vector@setup
%! m \verbatim@ps@special
%! m \vert@extra
% m \Vertical@Map
% m \Vertical@Map
%! m \vertical@name
%! m \vert@outside
%! m \vert@repeater
%! m \vert@wd@in@leftmost
% m \v@grid
%! m \@VonH
%! m \@was@pair@false
%! m \@was@pair@true
%! m \widen@hbox
%! m \widen@horiz
%! m \widen@pile
%! m \word@shrink
%! m \word@stretch
% m \@x % don't mangle as we \let@names{@x}{}
%! m \x@coord
%! m \xlc@ii
%! m \xlc@iv
%! m \x@offset
%! m \y@coord
%! m \y@offset

%! m \@pdf@false
%! m \@pdf@true
%! m \denom@@
%! m \div@@
%! m \do@eturn
%! m \if@pdf@
%! m \make@division
%! m \mk@@div
%! m \mnum@@
%! m \num@@
%! m \rotate@box@z
%! m \use@ps
%! m \dont@use@ps
%! m \use@pdf
%! m \undefined
%! m \cd@nonoPS
%! m \test@pdf
%! m \pdf@literal

%% don't load me twice!
% 19.9.2008 Terrence Bisson <bisson@canisius.edu>
% \undefined had been mangled to \CD@qK
% but in plain TeX, @=other, so got "@qK" in the output.
\ifx\diagram\isundefined\else\message
  {WARNING: the \string\diagram\space command is already defined and
  will not be loaded again}%
  \expandafter\endinput\fi

%% make @ letter, saving its old code to restore at the end of this file
%% look for this on the last line of the file if you think something's missing!
%% the other \catcode assignments are to make it work with texinfo.
\edef\cdrestoreat{%%
\noexpand\catcode`\noexpand\@=\the\catcode`\@%%
\noexpand\catcode`\noexpand\#=\the\catcode`\#%%
\noexpand\catcode`\noexpand\$=\the\catcode`\$%%
\noexpand\catcode`\noexpand\<=\the\catcode`\<%%
\noexpand\catcode`\noexpand\>=\the\catcode`\>%%
\noexpand\catcode`\noexpand\:=\the\catcode`\:%% Johannes L. Braams's
\noexpand\catcode`\noexpand\;=\the\catcode`\;%% Babel languages package
\noexpand\catcode`\noexpand\!=\the\catcode`\!%% makes these \active.
\noexpand\catcode`\noexpand\?=\the\catcode`\?%%
\noexpand\catcode`\noexpand\+=\the\catcode'53%% texinfo @+ is @outer@active
}\catcode`\@=11
\catcode`\#=6 \catcode`\<=12 \catcode`\>=12 \catcode'53=12
\catcode`\:=12 \catcode`\;=12 \catcode`\!=12 \catcode`\?=12

%% Change y to n if pool_size in your implementation of TeX is small.
%% This is reasonable if you have a small ("personal") computer, but if you
%% have a sun, dec, hp, ... workstation or a mainframe, complain to your local
%% system manager and get him/her to install a version of TeX with bigger
%% parameters. The "hash size" (number of command names) gets you next.
\ifx\diagram@help@messages\undefined\let\diagram@help@messages y\fi

%% The following macro is used to include literal PostScript commands in the
%% DVI file for rotation, etc.  Since this goes beyond standard TeX, it is
%% dependent on the convention used by your local DVI-to-PostScript translator.
%% Choose whichever line applies to the program used at your site, or, if
%% yours is not listed, consult the manual, experiment with this macro and
%% (please) tell me what is needed to make it work.
%%
%%
%% dvips (Tomas Rokicki, Radical Eye) labrea.stanford.edu /pub/dvips9999.tar.Z
%% CTAN: dviware/dvips
\def\cdps@Rokicki#1{\special{ps:#1}}%
\let\cdps@dvips\cdps@Rokicki
\let\cdps@RadicalEye\cdps@Rokicki\let\cdps@\cdps@Rokicki
\let\verbatim@ps@special\cdps@Rokicki\let\cdps@\cdps@Rokicki
%%
%% I'm not sure that the rest work.
%%
%% dvitps (Stephan Bechtolsheim, Integrated Computer Systems)
%% arthur.cs.purdue.edu /pub/TeXPS-9.99.tar.Z
\def\cdps@Bechtolsheim#1{\special{dvitps: Literal "#1"}}%% ASCII two dbl quotes
\let\cdps@dvitps\cdps@Bechtolsheim
\let\cdps@IntegratedComputerSystems\cdps@Bechtolsheim
%%
%% dvitops (James Clark)
%% CTAN: dviware/dvitops
\def\cdps@Clark#1{\special{dvitops: inline #1}}%%
\let\cdps@dvitops\cdps@Clark
%%
%% OzTeX (Andrew Trevorrow) cannot be used
\let\cdps@OzTeX\empty\let\cdps@oztex\empty\let\cdps@Trevorrow\empty
%%
%% dvi3ps (Kevin Coombes)
%% CTAN: dviware/dvi2ps/dvi3ps
\def\cdps@Coombes#1{\special{ps-string #1}}%
%\let@names{cdps@dvi3ps}{cdps@Coombes}%
%%
%% psprint (Trevorrow) CTAN: dviware/psprint
%% dvi2ps (Senn) CTAN: dviware/dvi2ps
%% psdvi (Elwell) CTAN: dviware/dvi2ps/psdvi

% there's also an expiry (and \endinput) message further down
\count@=\year\multiply\count@12 \advance\count@\month%%
\ifnum\count@>24300 %% (December 2024)
  \message{***********************************************************}%%ascii
  \message{! YOU HAVE AN OUT OF DATE VERSION OF COMMUTATIVE DIAGRAMS! *}%%
  \message{! it expired in December 2024 and is time-bombed for April *}%%
  \message{! You may get an up to date version of this package from *}%%ascii
  \message{! either www.ctan.org or www.PaulTaylor.EU/diagrams/ *}%%
  \message{***********************************************************}%%ascii
  \ifnum\count@>24303 %% (March 2025)
  \errhelp{You may press RETURN and carry on for the time being.}%
  \message{! It is embarrassing to see papers in conference proceedings}%
  \message{! and journals containing bugs which I had fixed years before.}%
  \message{! It is easy to obtain and install a new version, which will}%
  \errmessage{! remain compatible with your files. Please get it NOW.}%
\fi\fi

\def\glet{\global\let}\def\odef{\outer\def}%
% \let\@let\let\let\@edef\edef\let\@def\def
% \def\glet{\global\@let}%
% \def\odef{\outer\@def}%
% \@def\make@show@define#1{\expandafter\@let\csname\string#1\endcsname#1%
%       \@edef#1##1{\noexpand\message{\string#1\noexpand\string##1^^J}%
%               \csname\string#1\endcsname##1}}%
% \make@show@define\glet\make@show@define\let\make@show@define\def
% \make@show@define\gdef\make@show@define\edef\make@show@define\xdef
% \make@show@define\odef

%% safe names for braces, tab (&) and maths ($), as commands and for messages
{\escapechar\m@ne\xdef\bgroup@name{\string\{}\xdef\egroup@name{\string\}}%%
%%
%% three ASCII ampersands (ands) (&&&) appear on the next line
\catcode`\&=4 \glet\@and=&\xdef\and@name{\string\&}%%ascii three ands
%%
%% ASCII ^ and _ each appear twice on next line
%% six ASCII dollars ($$$$$$) appear on the next two lines.
\catcode`\$=3 \glet\begin@maths=$\glet\end@maths=$%%ascii three dollars
\xdef\dollar@name{\string\$}\gdef\maths@display{$$}%%ascii three dollars
%%
%% two ASCII underlines (__) appear on the next line.
\catcode`\_=8 \glet\@sub=_%%ascii two underlines
%%
%% eight ASCII carets (^^^^^^^^) appear on the next three lines.
\obeylines\catcode`\^=7 \glet\@super=^%%ascii two carets
\ifnum  \newlinechar=10 \gdef\new@line{^^J}%%ascii two carets
\else   \ifnum\newlinechar=13 \gdef\new@line{^^M}%%ascii two carets
\else   \ifnum\newlinechar=-1 \gdef\new@line{^^J}%%ascii two carets
\else   \glet\new@line\space
        \expandafter\message{! input error: \noexpand%ascii
        \newlinechar\space is ASCII \the\newlinechar, not LF=10 or CR=13.}%%
\fi\fi\fi}%%

%% avoid using <> (because I personally re-define them to mean \langle\rangle)
\mathchardef\lessthan='30474 \mathchardef\greaterthan='30476 

%% LaTeX line and arrowhead font
%% the "hit return" comments show up if the font is missing.
% size option?
\ifx\tenln\undefined%%
        \font\tenln=line10\relax%% Hit return - who needs diagonals?
\fi
\ifx\tenlnw\undefined
        \ifx\tenln\nullfont
                \let\tenlnw\nullfont
        \else%%
                \font\tenlnw=linew10\relax%% Hit return - who needs diagonals?
\fi     \fi%%

%% report line numbers in TeX3 only
% \newcount is \outer so cannot appear in skipped or definition text.
\ifx\inputlineno\undefined
        \csname newcount\endcsname\inputlineno\inputlineno\m@ne
        \message{***************************************************}%
        \message{! Obsolete TeX (version 2). You should upgrade to *}%
        \message{! version 3, which has been available since 1990. *}%
        \message{***************************************************}%
\fi

\def\cd@shouldnt#1{\cd@refmt@error{* THIS (#1) SHOULD NEVER HAPPEN! *}}%ascii

%% turn round- and square-bracketed arguments into curly-bracketed
\def\get@round@pair#1(#2,#3){#1{#2}{#3}}%%ascii round brackets ()
\def\get@square@arg#1[#2]{#1{#2}}%%ascii square brackets []
\def\get@opt@arg@list#1{%
    \@was@pair@false
    \let\next@opt@arg\@@getoptarg
    \@@getoptarg#1,],}%%ascii sq brackets
\def\begin@square@name{[}\def\end@square@name{]}%ascii
\def\commdiag#1{{\let\enddiagram\relax\diagram[]#1\enddiagram}}%ascii

%% ASCII open square bracket occurs on next line
\def\@@ifoptarg{{\ifx\next@token[%]%ascii
        \aftergroup\get@square@arg\aftergroup\@optcmd
\else
        \aftergroup\@noptcmd
\fi}}%%
% switch on presence of optional argument:
%   \@ifoptarg{\y}{\n}[arg]     does \y{arg}
%   \@ifoptarg{\y}{\n}          does \n
% are the braces actually necessary to avoid &?
\def\@ifoptarg#1#2{\def\@optcmd{#1}\def\@noptcmd{#2}%
\futurelet\next@token\@@ifoptarg}%

%% ASCII vertical bar (|) occurs on the next line
\def\vertical@name{|}%ascii

% idea: test & separately
% idea: use \meaning
% 14.5.92 DON'T GET & - GET \end@cell ANYWAY!
\def\cd@switch@arg{%% arguments to maps inside diagrams
\tokcase\end@cell:\@cd@a@false% no text between tip and &
                \break@args  ;%
\catcase\@super:\upper@label ;% superscript
\catcase  \@sub:\lower@label ;% subscript
\tokcase    {~}:\middle@label;%%ascii tilde
\tokcase      <:\left@label  ;%%ascii less-than
\tokcase      >:\right@label ;%%ascii greater-than
\tokcase      (:\co@ordinates;%%)%ascii open round bracket
\tokcase      [:\optional@   ;%%]%ascii open square bracket
\tokcase      .:\set@dot@filler;%%ascii dot 12.7.94
\catcase \space:\eat@space   ;% space (ignore)
\catcase\bgroup:\positional@ ;% obsolete positional labels
\default       :\@cd@a@true   % extra text between tip and &
                \break@args  ;% (anything else terminates labels)
\endswitch}

% Since maps are never bombed outside diagrams, glue compensation works
% and we don't have to abort through maps.
\def\switch@arg{%% arguments to horizontal maps outside diagrams
\catcase\@super:\upper@label ;% superscript
\catcase \@sub:\lower@label ;% subscript
\tokcase     [:\optional@   ;%%]%ascii open square bracket
\tokcase     .:\set@dot@filler;%%ascii dot 12.7.94 % ; was : before 15.6.97
\catcase\space:\eat@space   ;% space (ignore)
\catcase\bgroup:\positional@;% obsolete positional labels
\tokcase   {~}:\middle@label;%%ascii tilde (questionable!)
\default      :\@cd@a@false  % no need to allow for extra text
               \break@args  ;% (anything else terminates labels)
\endswitch}

%% That's as much as you get to read "in clear" - the rest is private!

%************************ program constructs *******************
%
\let\then\relax % makes \if...\then...\else...\fi more readable
\ifx\protect\undefined\let\protect\relax\fi
%
\ifx\AtEndDocument\undefined
   \def\message@at@end@doc{\cd@warning}%
   \def\info@at@end#1#2{}%
%
\else  % messages to output at the end of the run (28.7.95)
   \def\message@at@end@doc#1{%
      \edef\next{#1}%
      \expandafter\do@message@at@end@doc\next\end@mess}%
   \def\do@message@at@end@doc#1\end@mess{%
      \AtEndDocument{\typeout{\cd@name: #1}}}%
   \def\info@at@end#1#2{\gdef#1{#2}\AtEndDocument{#1}}%
\fi
% make warning to be given at first use only
\def\cd@first@use#1#2{%
   \def#1{\message@at@end@doc{#2\first@occur\at@line}%
   \glet#1\relax}}%
%
% TeX does not provide for nested loops in same scope!
% Warning: the \relax is needed in case the last command in the body reads
% ahead, for example "\advance\count@ 1".
%
% Why can't you put conditionals inside loops? Try with \toks.
%
\def\loop@on@rows#1\repeat{\def\body@{#1}\iterate@}%
\def\iterate@{\body@\relax\expandafter\iterate@\fi}%
\def\loop@on@cells#1\repeat{\def\body@@{#1}\iterate@@}%
\def\iterate@@{\body@@\relax\expandafter\iterate@@\fi}%
\def\loop@on@maps#1\repeat{\def\body@@@{#1}\iterate@@@}%
\def\iterate@@@{\body@@@\relax\expandafter\iterate@@@\fi}%
%
% as \newif, but simpler and manglable; initialised to false
\def\new@if#1#2#3{\def#2{\let#1\iftrue}\def#3{\let#1\iffalse}#3}%
%
% as \newhelp, but with a suppression option
\if y\diagram@help@messages
        \def\new@help#1#2{%
                \csname newtoks\endcsname#1%
                #1=\expandafter{%
                % I wanted to avoid the \ but it doesnt work
                %\expandafter\escapechar\expandafter\m@ne\expandafter\string
                \csname#2\endcsname}}%
\else
        \csname newtoks\endcsname\no@cd@help
        \no@cd@help{See the manual}%
        \def\new@help#1#2{\let#1\no@cd@help}%
\fi
%
% box definitions used during reformatting
\chardef\left@part=1
\chardef\right@part=2
\chardef\object@profile=5
\chardef\pending@right=6
\chardef\pending@left=7
\chardef\default@profile=9
\dimendef\right@donated=2
\dimendef\left@donated=3
\dimendef\left@width=4
\dimendef\right@width=5
\dimendef\total@donated=6
\dimendef\rule@height=8
\dimendef\rule@depth=9
\skipdef\completed@depth=1
\skipdef\inter@row=2
\skipdef\column@placing=3
\skipdef\horiz@extra=4
\skipdef\vert@extra=5
\skipdef\right@over=6
\skipdef\left@over=7
\skipdef\row@height=8
\skipdef\row@depth=9
\countdef\declared@at@cell=9
\countdef\far@end@cell=8
\countdef\across@cells=7
%
\def\sdef#1#2{\def#1{#2}}%
\def\after@name#1{\expandafter\aftergroup\csname #1\endcsname}%
\def\def@name#1{\expandafter\def\csname #1\endcsname}%
\def\gdef@name#1{\expandafter\gdef\csname #1\endcsname}%
\def\edef@name#1{\expandafter\edef\csname #1\endcsname}%
\def\let@names#1#2{\expandafter\let\csname#1\expandafter\endcsname
\csname#2\endcsname}%
\def\glet@names#1#2{\expandafter\glet\csname#1\expandafter
\endcsname\csname#2\endcsname}%
\def\use@name#1{\csname #1\endcsname}%
\def\showname#1{\expandafter\show\csname #1\endcsname}%
\def\showthename#1{\expandafter\showthe\csname #1\endcsname}%
\def\showboxname#1{\expandafter\showbox\csname #1\endcsname}%
%
\def\cd@name{Commutative Diagram}%
\edef\par@name{\string\par}%
\edef\diagram@name{\string\diagram}%
\edef\end@diagram@name{\string\enddiagram}%
\edef\cr@name{\string\\}%
\def\LaTeX@name{LaTeX}%
%
% LaTeX's switch to do \ignorespaces after an environment
% 11.10.97 inserted \global because LaTeX2e has changed the
% point at which \if@ignore\@ignorefalse\ignorespace\fi
% is executed. (Reported by Arthus Ogus ogus@math.berkeley.edu).
\ifx\@ignoretrue\undefined
    \expandafter\new@if\csname if@ignore\endcsname\ignore@true\ignore@false
    \def\@ignoretrue{\global\ignore@true}%
    \def\@ignorefalse{\global\ignore@false}%
\fi

%
%***************** aside on brace hacking (TeXbook p385) *****************
\def\bbgroup{{\ifnum0=`}\fi}\def\eegroup{\ifnum0=`{\fi}}%
% This is from latex.tex; it does \noalign{\hrule}, but if the next token
% is another \hrule it does \noalign{\hrule\vskip\hrule}.
% The reason why brace-backing is needed is that \ifx\@tempa\hline might
% encounter an & or \cr or \omit or \span. Our version of the same doesn't
% need this; it gets round it by putting the \ifx in braces.
% \def\hline{\noalign{\ifnum0=`}\fi\hrule \@height \arrayrulewidth \futurelet
%   \@tempa\@xhline}
%\def\@xhline{\ifx\@tempa\hline\vskip \doublerulesep\fi
%      \ifnum0=`{\fi}}
% there are other more complex examples for \\ commands for arrays, tables,
% etc. They need brace-hacking to protect \@ifstar - ie for the same reason.
%************************************************************************
% \hbox and \halign need {} or \bgroup\egroup, not \begingroup\endgroup
%************************************************************************
% 
%
% % % **** implement a case-switch construct ****
% % % Note that to protect & and \cr from recognition
% % % we have to em-brace them - \begingroup\endgroup doesn't work.
% % % This is probably the cause of the empty \mathord{} items.
% % % Also tried \def\catcase#1{\expandafter\eat@one{...}}\def\eat@one#1{}.
% % \def\catcase#1:{{%
% % \ifcat      \noexpand\next@token#1%
% % \then       \aftergroup\do@case
% % \else       \aftergroup\skip@case
% % \fi}}%
% % \def\tokcase#1:{{%
% % \ifx        \next@token#1%
% % \then       \aftergroup\do@case
% % \else       \aftergroup\skip@case
% % \fi}}%
% We never got & as \next@token anyway! The \mathord{}s have gone!
\def\catcase#1:{%
\ifcat  \noexpand\next@token#1%
\then   \expandafter\do@case
\else   \expandafter\skip@case
\fi}%
\def\tokcase#1:{%
\ifx    \next@token#1%
\then   \expandafter\do@case
\else   \expandafter\skip@case
\fi}%
\def\do@case#1;#2\endswitch{#1}%
\def\skip@case#1;{}%
\let\endswitch\relax
\def\default:#1;#2\endswitch{#1}% must come last
%
%idea
% \checklist<list><token>
% \def\checklist#1\expand\thenexttoken#2\endlist{%
% \def\rest{##2}%
% \ifx\rest\empty
% \then <not in list>
% \else <is in list>
% \fi}
%
% my initials in Morse code
%\def\@di@dah{\begin@maths{\cdot}{-}{\cdot}\;\;{-}\end@maths}%
%\def@name{rt:dah}{\rlap{\@di@dah}}%
%
%\edef\x{\meaning\year}\edef\y{\string\year} agree
%
% ***************** amstex emulation ***************
%
\ifx\at@\undefined\def\at@{@}\fi% amstex handling of @ defaults to letter
%\edef\amstex@prefix{pt@amstex@at@}%
\edef\amstex@prefix{\bgroup@name pt\egroup@name}%
\def@name{\amstex@prefix>}#1>#2>{\cd@and\rTo\sp{#1}\sb{#2}\cd@and}% horizontals
\def@name{\amstex@prefix<}#1<#2<{\cd@and\lTo\sp{#1}\sb{#2}\cd@and}%
\def@name{\amstex@prefix)}#1)#2){\cd@and\rTo\sp{#1}\sb{#2}\cd@and}%%ascii round
\def@name{\amstex@prefix(}#1(#2({\cd@and\lTo\sp{#1}\sb{#2}\cd@and}%%ascii brack
%
\def\amstex@diagram@setup{%
  \def\endCD{\enddiagram}%
  \def@name{\amstex@prefix A}##1A##2A{\uTo<{##1}>{##2}\cd@and\cd@and}%
  \def@name{\amstex@prefix V}##1V##2V{\dTo<{##1}>{##2}\cd@and\cd@and}%
  \def@name{\amstex@prefix=}{\cd@and\hEq\cd@and}%
  \def@name{\amstex@prefix\vertical@name}{\vEq\cd@and\cd@and}%
  \def@name{\amstex@prefix\string\vert}{\vEq\cd@and\cd@and}%
  \def@name{\amstex@prefix.}{\cd@and\cd@and}%
  \let\cd@and\@and
}%
%
\def\handle@at{%
   \let\tmp\handle@at@
   \ifcat     A\noexpand\next\else
   \ifcat     =\noexpand\next\else
   \ifcat\relax\noexpand\next\else
   \let\tmp\at@\fi\fi\fi
   \tmp}%
\def\handle@at@#1{\let@names{tmp}{\amstex@prefix\string#1}%
     \ifx\tmp\relax\def\tmp{\at@#1}\fi\tmp}%
%
\def\cd@and{}%
%
                                \begingroup\aftergroup
\def                            \aftergroup
    \assign@at                  \aftergroup
              {%
                                \aftergroup
               \def             \catcode`\@\active\aftergroup
                   @%
                                \endgroup
{\futurelet\next\handle@at}}%
%
%=======================================================================%
%                                                                       %
%       (2) DIMENSIONS AND COUNTS                                       %
%                                                                       %
%=======================================================================%
%
% define some scratch variables for our own use
% "gh" means global - use others and box/dimen 0...9 locally only
\newcount\cd@num@a\newcount\cd@num@b\newcount\cd@num@c\newcount\cd@num@d
\newdimen\cd@dim@a\newdimen\cd@dim@b
\new@if\if@cd@a@\@cd@a@true\@cd@a@false
\new@if\if@cd@b@\@cd@b@true\@cd@b@false
\newdimen\cd@dim@h\newdimen\cd@dim@k
\newcount\cd@num@g\newcount\cd@num@h
\newdimen\cd@dim@g\newbox\cd@box@g
\new@if\if@cd@g@\@cd@g@true\@cd@g@false
\newcount\numerator@\newcount\denominator@
%
% make #1 at least (resp at most) #2
\def\at@least#1#2{\ifdim#1<#2\relax#1=#2\relax\fi}%
\def\at@most #1#2{\ifdim#1>#2\relax#1=#2\relax\fi}%
%
\newdimen\one@sp\one@sp=1sp
\newdimen\@em\@em\z@
%
% check whether \@em has changed
% it was initialised to zero, and if "1em" is still zero
% that means there is no font loaded.
\def\size@dependencies{\ifdim\@em=1em\else\@szdep\fi}%
%
% if so, reset default arrowhead and \mathon & \mathoff
\def\@szdep{%
     \@em1em%
     \def\default@mapbreadth{\fontdimen8\textfont3 }%
     \set@arrowhead\set@max@fraction
     %
     % Can't see how to get \mathoff on its own without \null,
     % as it disappears at line breaks.
     % ! Math formula deleted: Insufficient symbol fonts
     \setbox0=\vbox{\bomb@parameters
        \noindent\begin@maths\null\penalty-9993\null\end@maths\null\endgraf
        \setbox0=\lastbox\unskip\unpenalty\setbox1=\lastbox
        \global\setbox\math@off@box=\hbox
                {\unhbox0\unskip\unskip\unpenalty\setbox0=\lastbox}%
        \global\setbox\math@on@box=\hbox
                {\unhbox1\unskip\unpenalty\setbox1=\lastbox}}%
}%
%
%\def\to@z{to\z@}%
%
% anticipate the pixel positioning
\newdimen\pixel@size\pixel@size=1true in \divide\pixel@size 300
%
% round #1 (a dimension or number) to pixels
\def\pixel@round#1{%
   \multiply#1\tw@
   \advance#1\ifnum#1<\z@-\else+\fi\pixel@size
   \divide#1\tw@
   \divide#1\pixel@size
   \multiply#1\pixel@size
}%
%
\def\MapBreadth{\afterassignment\reset@map@breadth\intended@breadth}%
\newdimen\intended@breadth % of ruled lines
\newdimen\rounded@breadth  % \intended@breadth rounded to pixels
\def\reset@map@breadth{%
   \rounded@breadth\intended@breadth
   \at@least\pixel@size{4\one@sp}% make sure we can divide by it
   \at@most\pixel@size\p@       % pixel smaller than point
   \pixel@round\rounded@breadth
   \ifdim\intended@breadth>\z@\at@least\rounded@breadth\pixel@size\fi
   \size@dependencies}%
\def\set@resolution#1{%
   \get@mand@value\count@
   \pixel@size#1%
   \ifnum\count@>\z@\divide\pixel@size\count@\fi
   \reset@map@breadth\set@max@fraction}%
\def\set@max@fraction{% 6 April 1995
   \dimen@\default@size
   \count@\dimen@\divide\count@ 5\divide\count@\pixel@size
   \edef\default@max@fraction{\the\count@}%
   %\expandafter\message
   %{max fraction=\default@max@fraction=\the\dimen@/5x\the\pixel@size}%
   }%
%
% set up for rule centred on maths axis
\def\set@axis{\set@offset@axis\z@}%
\def\set@offset@axis#1{%
   \rule@height\axisheight
   \advance\rule@height#1\relax
   \advance\rule@height-.5\rounded@breadth
   \pixel@round\rule@height
   \rule@depth-\rule@height
   \advance\rule@height\intended@breadth
}%
%
% transverse and longitudinal offset for arrows
\newdimen\crab@\crab@\z@\newdimen\snake@\snake@\z@
%
% set up for rule used with cmex parts (on baseline) 17.7.94
\def\set@cmex@offset@axis#1{%
   \rule@depth#1\relax
   \rule@height\rule@depth
   \advance\rule@height\intended@breadth\relax
}%
%
\def\horizhtdp{height\rule@height depth\rule@depth}%
\def\axisheight{\fontdimen22\the\textfont\tw@}% maths axis from symbols family
\def\script@axisheight{\fontdimen22\the\scriptfont\tw@}% script axis ditto
\def\ss@axisheight{\fontdimen22\the\scriptscriptfont\tw@}% scriptscript axis
\def\default@mapbreadth{0.4pt}%
\def\word@stretch{\fontdimen3\textfont\z@}%
\def\word@shrink{\fontdimen3\textfont\z@}%
%
%
\newdimen\PileSpacing
\newdimen\cd@left@margin        \cd@left@margin\z@
%\newdimen\min@map@length
\def\min@map@length{\ifincommdiag 1.3em\else 2em\fi}%
\newdimen\cd@top@height
%
\def\CellSize{\afterassignment\cell@height@to@width\DiagramCellHeight}%
\newdimen\DiagramCellHeight     \DiagramCellHeight-\maxdimen
\newdimen\DiagramCellWidth      \DiagramCellWidth-\maxdimen
\def\cell@height@to@width{\DiagramCellWidth\DiagramCellHeight}%
%
\def\default@size{3em}%
%
\newdimen\MapShortFall
\def\MapsAbut{\MapShortFall\z@\objectheight\z@\objectwidth\z@}%
%
\newdimen\cd@hshift\cd@hshift\z@ % amount to shift object right in cell
%
% %% this is a mega-hack for extracting as text the value of a \dimen in points
% {\catcode`p=12 \catcode`0=12 \catcode`.=12 \catcode` t=12 
% \gdef\rem@z#1.0.#2,{#1}%
% \gdef\dim@sans@uni#1pt{\rem@z#1.0.,}}%
% \def\dim@in@pts#1{\expandafter\dim@sans@uni\the#1 }
%\def\axis@height@in@pts{\dim@in@pts\axisheight}%
%
%------------------------------------------------------------------------
% 25 Aug 2006: PS & PDF switches moved here
%
% test whether \ifUglyObsoleteDiagrams has been defined and set to \iftrue
%
%\showname{ifUglyObsoleteDiagrams}%
\new@if\if@cd@use@PS@\@cd@use@PS@true\@cd@use@PS@false
\expandafter
   \ifx\expandafter\iftrue\csname ifUglyObsoleteDiagrams\endcsname
        \@cd@use@PS@false
   \else\@cd@use@PS@true
   \fi
\let@names{ifUglyObsoleteDiagrams}{relax}%
\newif\ifUglyObsoleteDiagrams
\def\use@ps{\@cd@use@PS@true\UglyObsoleteDiagramsfalse}%
\def\dont@use@ps{\@cd@use@PS@false\UglyObsoleteDiagramstrue}%
\if@cd@use@PS@\use@ps\else\dont@use@ps\fi
%
%
% are we using PDF-TeX?
\new@if\if@pdf@\@pdf@true\@pdf@false\@pdf@false
% 
% On Fri, 11 Jul 2003, Volodymyr Lyubashenko wrote:
% it seems that version 2002/03/15 v3.89 is incompatible with
% latex commands like
%    \usepackage[dvips]{graphics}
% or \usepackage{color}
% which also uses package `graphics'. It mistakes latex for pdflatex.
% This is ... MiKTeX 2.2 (preloaded format=latex 2000.11.28)
% ! Missing number, treated as zero.
% ! Missing = inserted for \ifnum.
% ! Illegal unit of measure (pt inserted).
% -- so I tried testing for \pdfoutput=\relax
%
\def\test@pdf{%
 \ifx\pdfoutput\undefined\else
 \ifx\pdfoutput\relax\else
 \ifnum\pdfoutput>\z@\use@pdf
 \fi\fi\fi
}
\def\use@pdf{%
   \global\@pdf@true
   \global\@cd@use@PS@true
   \global\UglyObsoleteDiagramsfalse
   \global\let\better@use@ps\empty
   \global\let\dont@use@ps\relax
   \global\let\use@pdf\relax
   \global\let\test@pdf\relax
}%
%\def\pdf@literal#1{\message{pdf: literal #1}\special{pdf: literal #1}}%
\def\pdf@literal#1{\special{pdf: literal #1}}%
\ifx\pdfliteral\undefined\else
\ifx\pdfliteral\relax\else
\let\pdf@literal\pdfliteral
\fi\fi
%
% are we running under XeTeX?
\ifx\XeTeXrevision\undefined\else
   \ifx\XeTeXrevision\relax\else
       \ifdim\XeTeXrevision pt<.996pt
           \expandafter\message{! XeTeX version \XeTeXrevision\space
           does not support PDF literals, so diagonals will not work!}%
       \else
           \expandafter\message{RUNNING UNDER XETEX \XeTeXrevision}%
           \use@pdf
\fi\fi\fi
%
% are we running under pdftex? (this is repeated in the first diagram)
\test@pdf
%
%=======================================================================%
%                                                                       %
%       (2) MAKE ARROW PARTS                                            %
%                                                                       %
%=======================================================================%
%
% \newarrowhead{name}{right}{left}{down}{up}
%                #5     #6    #7    #8   #9
%
\def\newarrowhead  {\new@arrow@part h\make@horiz@part\make@vert@part>}%
\def\newarrowtail  {\new@arrow@part t\make@horiz@part\make@vert@part>}%
\def\newarrowmiddle{\new@arrow@part m\make@horiz@part\hbox@maths\empty}%
\def\newarrowfiller{\new@arrow@part f\horiz@repeater \vert@repeater -}%
%                                  #1   #2              #3          #4
% 12.7.94 removed \make@vert@part from vertical middle,
% because it was hiding the width of wide middles (eg transitors).
%
% idea: []-option to set something instead of #4
% idea: check whether #5 is already defined
\def\new@arrow@part#1#2#3#4#5#6#7#8#9{%
  \def@name{r#1:#5}{#2{#6}}%
  \def@name{l#1:#5}{#2{#7}}%
  \def@name{d#1:#5}{#3{#8}}%
  \def@name{u#1:#5}{#3{#9}}%
 \edef@name{-#1:#5}{\expandafter\noexpand\csname-#1:#4\endcsname
    \noexpand\default@diagonal}%
 \edef@name{+#1:#5}{\expandafter\noexpand\csname+#1:#4\endcsname
    \noexpand\default@diagonal}%
% \let@names{+#1:#5}{+#1:#4}%
% \let@names{-#1:#5}{-#1:#4}%
}%
\cd@first@use\default@diagonal{\LaTeX@name\space diagonals are used unless
    PostScript is set}%
%
% ****************** choose default components *****************
%
% 32 arrow parts in 16 boxes
\def\defaultarrowhead#1{\edef\the@default@head{#1}\set@arrowhead}%
\def\set@arrowhead{%
   \set@default@parts       \the@default@head <>ht%       single arrowheads
  %\set@default@parts{double\the@default@head}{<<}{>>}ht% double heads
   \set@default@parts       \the@default@head <>th%       single tails
  %\set@default@parts{double\the@default@head}{<<}{>>}th% double tails
}%
%
% 8 arrow parts in 4 boxes
\def\set@default@parts#1#2#3#4#5{% #1=choice #2=tailname #3=headname #4=h #5=t
  \set@default@part{r#4}{#3}{l#5}{#2}{r#4:#1}%
  \set@default@part{r#5}{#2}{l#4}{#3}{l#4:#1}%
  \set@default@part{d#4}{#3}{u#5}{#2}{d#4:#1}%
  \set@default@part{d#5}{#2}{u#4}{#3}{u#4:#1}%
}%
%
% do:   if \#1+:#2 is not defined then \newbox\#1+:#2 \fi
%       \def\#1:#2{\copy\#1::#2}
%       \def\#3:#4{\copy\#1::#2}
%       \setbox\#1::#2=\#5
%
\def\set@default@part#1#2#3#4#5{%
\begingroup
        %\expandafter\ifx\csname #1+:#2\endcsname\relax %ascii
        %       \after@name{newbox}\after@name{#1+:#2}%ascii
        %\fi
        \aftergroup\@set@default@part
\after@name{#1+:#2}\after@name{#1:#2}\after@name{#3:#4}\after@name{#5}%ascii
\endgroup}%
%
% use this code first to define the boxes and macros
\def\@set@default@part#1#2#3#4{% #1=boxname #2=partname #3=synonym #4=value
\csname newbox\endcsname#1%
\def#2{\copy#1}%
\def#3{\copy#1}%
\setbox#1=\box\voidb@x}%
%
\def\the@default@head{}%
\set@arrowhead% do it with empty boxes
%
% now re-define the macro so that it just sets the box
\def\@set@default@part#1#2#3#4{\setbox#1=#4}%
%
\ifx\tenln\nullfont
     \def\the@default@head{vee}%
\else\let\the@default@head\LaTeX@name
\fi
%
\def\make@double@head#1#2#3{%
\begingroup
   \aftergroup\@make@double@head\after@name{#1#2:#3#3}\after@name{#1#2:#3}%
   \aftergroup\@make@double@through@head\after@name{#1#2:#3-#3}\after@name{#1#2:#3}%
\endgroup}%
%
\def\@make@double@head#1#2{\def#1{\hbox{\rlap{#2}\kern.4\@em#2}}}%
\def\@make@double@through@head#1#2{%
    \def#1{\hbox{\rlap{#2}\kern.4\@em#2\kern-.4\@em}}}%
\make@double@head lh>%
\make@double@head rt>%
\make@double@head rh<%
\make@double@head rt<%
\def\@make@double@through@head#1#2{%
    \def#1{\hbox{\kern-.4\@em\rlap{#2}\kern.4\@em#2}}}%
\make@double@head rh>%
\make@double@head lh<%
\make@double@head lt>%
\make@double@head lt<%
%
\def\@make@double@head#1#2{%
\def#1{\vbox{\vbox to\z@{#2\vss}\nointerlineskip\kern.4\@em#2}}}%
\def\@make@double@through@head#1#2{%
\def#1{\vbox{\vbox to\z@{#2\vss}\nointerlineskip\kern.4\@em#2\kern-.4\@em}}}%
\make@double@head uh>%
\make@double@head dt>%
\make@double@head dh<%
\make@double@head dt<%
\def\@make@double@through@head#1#2{%
\def#1{\vbox{\kern-.4\@em\vbox to\z@{#2\vss}\nointerlineskip\kern.4\@em#2}}}%
\make@double@head dh>%
\make@double@head ut>%
\make@double@head uh<%
\make@double@head ut<%
%
% old version that did both together every time
% NB \csname undefined\endcsname=\relax LOCALLY - \aftergroup it's \undefined
%\def\@set@default@part#1#2#3#4{% #1=boxname #2=partname #3=synonym #4=value
%\ifx#1\undefined\csname newbox\endcsname#1\fi %if #1 is undefined \newbox#1 fi
%\def#2{\copy#1}\def#3{\copy#1}%
%\setbox#1=#4}%
%
%
% ******************* MAKE MAP PARTS ***********************
%
% idea: use \mathsurround
%
% Clip the margins off Computer Modern symbols.
\def\make@horiz@part#1{%
\hbox{\mathsurround\z@\offinterlineskip
        \begin@maths\mkern-1.5mu{#1}\mkern-1.5mu\end@maths
}}%
%
% Put vertical arrow part into a box, centering it.
% However since there's nothing we can do about the fact the
% reference point of \vrule width\intended@breadth is on the left,
% we make the other repeating boxes compatible with it,
% by centering them (smashed) in a box of the same width.
% 
\def\hbox@maths#1{\hbox{\begin@maths#1\end@maths}}%  17.7.94
\def\make@vert@part#1{\hbox to\intended@breadth{%
   \setbox0=\hbox{%
      \offinterlineskip
      \mathsurround\z@
      \begin@maths{#1}\end@maths % set the vertical arrow part
    }%
   \dimen0.5\wd0\advance\dimen0-.5\rounded@breadth
   \pixel@round{\dimen0}%
   \kern-\dimen0\unhbox0\hss}}%  
%
% version for use with cmex parts 17.7.94 
\def\cmex@vert@part#1{\hbox to2\intended@breadth{% don't understand "2"
   \hss
   \offinterlineskip
   \mathsurround\z@
   \begin@maths{#1}\end@maths % set the vertical arrow part
   \hss}}%  
%\def\cmex@vert@part#1{\hbox to\z@{\hss\begin@maths#1\end@maths\hss}}%
%
%\def\make@vert@part#1{%
%\hbox to\intended@breadth{% arrow-part: centered in 0 to \MapB
%\offinterlineskip\mathsurround\z@
%\hss\begin@maths%\kern\intended@breadth
%{#1}\end@maths\hss}}%
%\def\make@vert@part#1{%
%\hbox to\z@{% arrow-part
%\setbox0=\hbox{\offinterlineskip\mathsurround\z@\begin@maths{#1}\end@maths}%
%\count@\wd0\advance\count@-\intended@breadth\advance\count@\pixel@size
%\divide\count@2\divide\count@\pixel@size
%\dimen0\wd0\advance\dimen0.5\pixel@size\divide\dimen0\pixel@size
%\dimen1\intended@breadth\advance\dimen1.5\pixel@size\divide\dimen1\pixel@size
%\advance\dimen0-\dimen1\divide\dimen0 2\count@\dimen0%
%\kern-\count@\pixel@size\box0\hss}}%
%
\def\make@diag@part#1{\hbox{\mathsurround\z@\begin@maths{#1}\end@maths}}%
%
\def\horiz@repeater#1{\hbox{\kern-.15\@em\begin@maths{#1}\end@maths
        \kern-.15\@em}}%
%
\def\vert@repeater #1{%
  \vbox{\offinterlineskip
    \kern-.2ex%
    \make@vert@part{#1}%
    %\hbox to\intended@breadth{\hss\begin@maths{#1}\end@maths\hss}%
    \kern-.2ex}}%
%
% also dot filler
%
\def\@fillh{\xleaders\vrule\horizhtdp}% default rule filler
\def\@fillv{\xleaders\hrule width\intended@breadth}%
\let@names{rf:-}{@fillh}\let@names{lf:-}{@fillh}%
\let@names{df:-}{@fillv}\let@names{uf:-}{@fillv}%
%
% ****************** empty components *****************
%
% empty arrowhead and middle
\let@names{rh:}{null}\let@names{rm:}{null}\let@names{rt:}{null}%
\let@names{lh:}{null}\let@names{lm:}{null}\let@names{lt:}{null}%
\let@names{dh:}{null}\let@names{dm:}{null}\let@names{dt:}{null}%
\let@names{uh:}{null}\let@names{um:}{null}\let@names{ut:}{null}%
\let@names{+h:}{null}\let@names{+m:}{null}\let@names{+t:}{null}%
\let@names{-h:}{null}\let@names{-m:}{null}\let@names{-t:}{null}%
%
% empty filler (nontrivial size, to avoid division by zero in \xleaders)
% 17.7.94 changed from \def to \let
% 4.7.97 \empty@filler and \empty@parts
\def\empty@filler{\hbox{\vrule height 1pt depth-1pt width 1pt}}%
\def@name{rf:}{\empty@filler}\let@names{lf:}{rf:}\let@names{+f:}{rf:}%
\def@name{df:}{\empty@filler}\let@names{uf:}{df:}\let@names{-f:}{df:}%
\def\empty@parts{\assign@five\null\empty@filler\null\empty@filler\null}%
%
%
%=======================================================================%
%                                                                       %
%       (3) NEW ARROW                                                   %
%                                                                       %
%=======================================================================%
%
% define a family of arrow commands
% \newarrow{Name}{tail}{filler}{middle}{filler}{head}
%
% idea: \catcode`\\ to catch non-text names
% idea: \renewarrow etc, also synonyms & head/tail synonyms
% idea: optional argument to list directions, eg [r,l,d,u] or [nw,ne,sw,se]
%
\edef\newarrow@name{\string\newarrow}% do this now because it's \outer
%
% ******************* \newarrow *******************************
%
\def\newarrow#1#2#3#4#5#6{%
\begingroup
%               ----- components and defaults -----
%
  \edef\@name{#1}%
  \edef\@tail{#2}\edef\@filla{#3}%
  \edef\@middle{#4}\edef\@fillb{#5}\edef\@head{#6}%
  \let\@h\new@horiz@map
  \let\@v\new@vert@map
  \let\@x\new@vector@map   % LaTeX vector
%
%               ----- normalise the components -----
%
% if the tips are the same as the corresponding fillers
% make them empty instead
  \ifx\@tail\@filla\let\@tail\empty\fi
  \ifx\@head\@fillb\let\@head\empty\fi
%
% if the head is empty and the tail isn't (funny!), swap everything around
  \def\@r{r}\def\@l{l}\def\@d{d}\def\@u{u}\def\@p{+}\def\@m{-}%
%  \ifx\@head\empty\ifx\@tail\empty\else
%       \let\@r\@filla          % wrong way round, so switch components
%       \let\@filla\@fillb
%       \let\@fillb\@r
%       \let\@head\@tail        % \@head was \empty anyway
%       \let\@tail\empty
%       \def\@r{l}\def\@l{r}\def\@d{u}\def\@u{d}\def\@p{-}\def\@m{+}%
%  \fi\fi
%
  \ifx\@filla\@fillb
%
%                ----- same filler fore and aft -----
%
%    normalise middle to empty if also same
     \ifx\@middle\@filla\let\@middle\empty\fi
%
     \ifx\@head\empty
        \ifx\@filla\horizontal@name
           \let\@x\new@slant@map % LaTeX \line
        \else
           \let\@x\new@slope@map % unrestricted
     \fi\fi
%
  \else\edef\@back{\@filla\@tail}%
     \ifx\@back\empty
%
%                ----- half-length maps -----
%
         \ifx\@middle\@fillb\let\@middle\empty\fi % normalise middle if same
        %\let\@h\new@half@horiz
        %\let\@v\new@half@vert
  \fi\fi
%
%            ----- are the components actually there? -----
\ifmmode
  \aftergroup\newarrow@mmode
\else
  \@cd@a@true
  \check@part rh{head\space\space}\@head
  \check@part rf{filler}\@filla
  \check@part rm{middle}\@middle
  \ifx\@fillb\@filla\else
     \check@part rf{filler}\@fillb
  \fi
  \check@part rt{tail\space\space}\@tail
%
  \if@cd@a@
%
%             ----- yes - output the definitions -----
%
       \@h % make horizontals
       \@v % make verticals
       \@x % make diagonals
%
        \new@diagonal l-2+2{lu}{nw}\NorthWest   % \diagonal@setup
        \new@diagonal r+2+2{ru}{ne}\NorthEast
        \new@diagonal l-2-2{ld}{sw}\SouthWest
        \new@diagonal r+2-2{rd}{se}\SouthEast
  \else
%             ----- no - output an error message -----
%
        \aftergroup\bad@arrow\after@name{r\@name}%
\fi\fi
\endgroup % \aftergroup collects all the actual definitions here
}%
%
% ******************* \newarrow internals **************************
%
%
\def\new@horiz@map {\new@map\@r\@l rl\Horizontal@Map}%
\def\new@vert@map  {\new@map\@d\@u du\Vertical@Map}%
\def\new@vector@map{\new@map\@p\@m +-\Vector@Map}% LaTeX \vector
\def\new@slant@map {\new@map\@p\@m +-\Slant@Map}%  LaTeX \line
\def\new@slope@map {\new@map\@p\@m +-\Slope@Map}%  unrestricted
%\def\new@half@horiz{\new@half@map\@r r\setup@right@half
%                    \new@half@map\@l l\setup@left@half}%
%\def\new@half@vert {\new@half@map\@d d\setup@bottom@half
%                    \new@half@map\@u u\setup@top@half}%
%
%
%                ----- make one or two user arrow commands -----
%
\catcode`\/=\active %ascii            avoid clash in use of slash delimiter/
%
\def\new@map#1#2#3#4#5{%
\@new@arrow#1#3#5t:\@tail/f:\@filla/m:\@middle/f:\@fillb/h:\@head//%ascii
\@new@arrow#2#4#5h:\@head/f:\@fillb/m:\@middle/f:\@filla/t:\@tail//}%ascii
%
%\def\new@half@map#1#2#3{\@new@arrow#1#2#3m:\@middle/f:\@fillb/h:\@head//}%
%
% internals:
% #1=name prefix, #2=argument prefix, #3=direction command, #4=arguments
\def\@new@arrow#1#2#3#4//{%ascii                        slash is \active here/
\edef\name@prefix{#2}%
\aftergroup\sdef\after@name{#1\@name}\aftergroup{%
        \aftergroup#3%        % setup
        %\after@name{#1\@name}% give it its name (?)
        \after@names#4//%ascii% arguments                    slash is \active/
\aftergroup}}%
%
\def\after@names#1/{%ascii /-separated, //-terminated list   slash is \active/
\edef\next@token{#1}%
\ifx    \next@token\empty
\else   \after@name{\name@prefix#1}%
        \expandafter\after@names%
\fi}%
%
\catcode`\/=12 %ascii                                         restore slash/
%
%                   ----- make a user diagonal command -----
%
% #1=orthogonal direction to use for rotation
% (#2#3,#4#5) vectorial form of direction
% #6 #7 direction prefix for user command name
% #8 direction setup
% do: \def\#6name{\#2name \signGradient \#1name  (#3,#5)}
\def\new@diagonal#1#2#3#4#5#6#7#8{%
  \aftergroup\sdef\after@name{#6\@name}\aftergroup{% \def\#6name
        \after@name{#2\@name}%  diagonal map command eg \+To
        \if#2#4%
             \aftergroup\PositiveGradienttrue
        \else\aftergroup\PositiveGradientfalse
        \fi
        \after@name{#1\@name}%  orthogonal map to rotate eg \rTo
%% ASCII round brackets and comma (,) appear on the next line
        \aftergroup(\aftergroup#3\aftergroup,\aftergroup#5\aftergroup)%ascii
  \aftergroup}%
}%
%
% do: \def\#6name{\diag@setup #7 \#1name \#2name (#3,#5)}
%\def\new@diagonal#1#2#3#4#5#6#7#8{%
%  \aftergroup\sdef\after@name{#6\@name}\aftergroup{% \def\#6name
%       \if#2#4%
%            \aftergroup\Rising@Map
%       \else\aftergroup\Falling@Map
%       \fi
%       %\aftergroup\Diagonal@Map\aftergroup#7%   % \Diagonal@Map #7
%       \after@name{#1\@name}\after@name{#2\@name}% \#1name \#2name
% % ASCII round brackets and comma (,) appear on the next line
%       \aftergroup(\aftergroup#3\aftergroup,\aftergroup#5\aftergroup)%ascii
%  \aftergroup}%
%}%
%
%                    ----- existence of components -----
\def\check@part#1#2#3#4{%
\expandafter\ifx\csname #1#2:#4\endcsname\relax
        \@cd@a@false\cd@warning{arrow#3 "#4" undefined}%ascii
\fi}%
%
\new@help\help@undef@map{All five components must be defined before an arrow.}%
\new@help\help@newarrow{\newarrow@name, unlike \string\HorizontalMap, is a
declaration.}%
%
\def\bad@arrow#1{\cd@error{Arrows \string#1 etc could not be defined}%
\help@undef@map}%
%
\def\newarrow@mmode{\cd@error{misplaced \newarrow@name}\help@newarrow}%
%
%
%=======================================================================%
%                                                                       %
%       (3A) NEW GRID                                                   %
%                                                                       %
%=======================================================================%
%
\def\newdiagramgrid#1#2#3{%
    \def@name{cdgh@#1}{#2,],}%% ASCII close square bracket
    \def@name{cdgv@#1}{#3,],}}%% ASCII close square bracket
%
%=======================================================================%
%                                                                       %
%       (4) HORIZONTAL STATE CHECKING AND ARROW SETUP                   %
%                                                                       %
%=======================================================================%
%
% We use \cd@donat (during the first pass, locally to each cell) to hold a
% "horizontal map state".  Each map type inserts the missing text (giving an
% appropriate error message) shown for each state and changes to the new state.
%
% donated half maps?
%
%                  end of \rTo or                \VonH or
% state              cell   \pile    \dTo   \HonV \HmeetV
% 0 outside diagram     -   ($) 0  forbid  forbid  forbid
% 1 space donated       1       5       3       4       4
% 2 arrow donated       1   {}& 5       3       5       4
% 3 verticals   (in)    1     & 5       3     & 4     & 4
% 4 junction   (this)   1     & 5     & 3     & 4     & 4
% 5 horizontal (cell)   2  &{}& 5     & 3     & 4     & 4
% 6 pile              } 2       7    }& 3    }& 4    }& 4
% 7 pile horizontal   } 2    \\ 7    }& 3    }& 4    }& 4
%
% initial states outside diagram, inside diagram and inside \pile
% signal we're outside \commdiag
\new@if\ifincommdiag\incommdiagtrue\incommdiagfalse
\new@if\if@in@matrix@\@in@matrix@true\@in@matrix@false % 12.7.94
\newcount\cd@donat
\cd@donat=0
\def\pile@state{\cd@donat6 }%
% idea: check number of rows and columns
% assign to \cd@num@g in case the first cell is empty, so \end@cell
% (and hence \send@cell@type) is not called.
% changed to \empty (and initialised as such) from {left edge} 27.12.93
\def\cd@state{\cd@donat1 \global\cd@num@g1 \glet\last@map@type\empty}%
\def\last@map@type{}%
%
% The automaton for horizontal maps; also used by \pile.
% #1="horizontal map" or "pile".
\def\check@horiz#1{\relax
\end@label % in case of missing close brace at end of label
\edef\this@map@type{#1}%
\begingroup
\if@cd@PS@horiz@\else
\ifcase\cd@donat\ifmmode\else%  0% 0 in maths outside diagram ok
   \modify@cell\add@dollar 0\fi%0% 0 outside maths
\or\horiz@state                 5% 1 accept space donation ok
\or\modify@cell\add@empty@and   5% 2 empty object between two horizontals
\or\modify@cell\add@and         5% 3 new cell after vertical
\or\modify@cell\add@and         5% 4 new cell after junction
\or\modify@cell\add@and@and     5% 5 two horizontals (perhaps \pile intended?)
\or\horiz@state                 7% 6 in pile ok
\or\modify@cell\add@cr          7% 7 new row of pile after horizontal
\fi\fi\endgroup         % save up commands to here with \aftergroup
\xdef\last@map@type{#1}}%
%
% The automaton for verticals; also used by \HonV, \VonH and \HmeetV.
% #1=least state requiring insertion, #2=usual new state, #3=exceptional one,
% #4=map type text, #5=command (will do no-op with error in forbidden case).
\def\check@vert#1#2#3#4#5{\relax
\end@label % in case of missing close brace at end of label
\xdef\this@map@type{#4}%
\begingroup
\ifnum  \cd@donat<#1
        \expandafter\horiz@state\ifcase\cd@donat0\or#2\or#3\else#2\fi%
\else   \ifnum  \cd@donat<6
        \then   \modify@cell\add@and            #2%
        \else   \modify@cell\add@endpile@and    #2%
\fi     \fi
\endgroup               % \aftergroup saves up commands to do here
\glet\last@map@type\this@map@type
\ifincommdiag
        \let\exec@map#5%
\else   \let\exec@map\vert@outside
\fi}%
%
% idea: compare with a global variable to check for (wrongly) em-braced maps.
% idea: count no. of rows & columns to check for overflow
%
% Pass the new horizontal state across cell boundary using global variable;
% this is picked up and assigned to \cd@donat in the next template.
\def\send@cell@type{\global\cd@num@g=\ifnum\cd@donat<5 1\else2\fi\relax}%
\def\receive@cell@type{\cd@donat\cd@num@g}%
%
% Set the new state (after \endgroup).
\def\horiz@state#1{\aftergroup\cd@donat\aftergroup#1\aftergroup\relax}%
%
% skip the check ("time nlatex manual")
% with check: 24.7u 1.0s 0:31 83% 0+1568k 0+13io 0pf+0w
% without:    24.6u 0.9s 0:30 83% 0+1572k 0+13io 0pf+0w
\def\nohcheck{%
\def\check@horiz##1{\relax}%
\let\check@vert\no@check@vert
\let\pile@state\relax
\let\cd@state\relax
\let\send@cell@type\relax
\let\receive@cell@type\relax
}%
\def\no@check@vert#1#2#3#4#5{%
\ifincommdiag
        \let\exec@map#5%
\else   \xdef\this@map@type{#4}\let\exec@map\vert@outside
\fi}%
%
% Do insertion, with error message (then change state), after \endgroup.
% [Remember that insertion of & or \\ within #1 causes a lot of extra commands
%  like \begin@cell \end@cell to be executed.
%  We are careful to ensure that conditionals are completed with our own cell.
%  Note sure why, but it does at least mean that the user does not see \fi in
%  the error context.]
\def\modify@cell#1{\aftergroup#1\aftergroup\relax\horiz@state}%
%
% The insertion commands.
\def\add@and{\horiz@add\and@name\help@and\@and}%
\def\add@endpile@and{\horiz@add{\egroup@name\and@name}\help@vpile%
  \end@pile\@and}%
% How can we tell (in the next case) whether there is already an object in
% the cell, so it's just a & which is missing? Perhaps test whether \next@token
% is the first of \check@horiz? [\relax is too common for this]
\def\add@empty@and{\horiz@add{*\and@name}\help@hpile\clubsuit\@and}%ascii
\def\add@and@and{\horiz@add{\and@name*\and@name}\help@hpile\@and\clubsuit%ascii
 \@and}%
\def\add@cr{\horiz@add\cr@name\help@pilecr\\}%
\def\add@dollar{\horiz@add\dollar@name\help@hext\begin@maths}%
\def\vert@outside{\cd@error{\this@map@type\space ignored \outside@diagram}%
  \help@vext}%
%
% Within the $..$ of diagram & pile cells we assign \bad@group@after@map
% to \group@after@map, but make it \empty again in the diagram and pile
% environments. Then \aftergroup\group@after@map at the end of the arrow
% command (in \break@args) causes an error if the next end-of-group occurs
% strictly within the $; the $ itself is supposed to be the end-of-group.
\def\group@after@map{}%
\def\bad@group@after@map{\cd@error{maps must never be enclosed in braces}%
   \help@bad@group}%
%
% This version also complains if you do ${\rTo}$ in text.
%   \def\group@after@map{\ifmmode\expandafter\bad@group@after@map\fi}%
% but I had the following example in my book:
%   $$\denote{\Gamma\rTo^{[f:=\hat g]}(f:(\hat A\to\hat B))}= ... $$
% which seems a reasonable use of braces around arrows in text.
% The only effect is to prevent them stretching with the paragraph.
%
% Help messages
\def\outside@diagram{outside diagram}%
\def\cross@names{\string\HonV, \string\VonH\space and \string\HmeetV}%
\new@help\help@and{The way that horizontal and vertical arrows are terminated
  implicitly means\new@line that they cannot be mixed with each other or with
  \cross@names.}%
\new@help\help@vpile{\string\pile\space is for parallel horizontal arrows;
  verticals can just be put together in\new@line a cell. \cross@names\space
  are not meaningful in a \string\pile.}%
\new@help\help@hpile{The horizontal maps must point to an object, not each
  other (I've put in\new@line one which you're unlikely to want).
  Use \string\pile\space if you want them parallel.}%
\new@help\help@pilecr{Parallel horizontal arrows must be in separate layers
  of a \string\pile.}%
\new@help\help@hext{Horizontal arrows may be used \outside@diagram s, but must
  still be in maths.}%
\new@help\help@vext{Vertical arrows, \cross@names\space\outside@diagram s
  don't know where\new@line where to terminate.}%ascii
\new@help\help@bad@group{This prevents them from stretching correctly.}%
%
% The actual message.
% Before 27.12.93 this tested \ifincommdiag.
\def\horiz@add#1{\cd@error{"#1" inserted %ascii
\ifx\last@map@type\empty
        before  \this@map@type
\else   between \last@map@type
        \ifx    \last@map@type\this@map@type s%
        \else   \space and \this@map@type
        \fi
\fi}}%
%
\count@=\year\multiply\count@12 \advance\count@\month
\ifnum\count@>24307 \message{because this one expired in July 2025!}%
\expandafter\endinput\fi
%
%=======================================================================%
%                                                                       %
%       (5) SYNTAX OF ARROW COMMANDS                                    %
%                                                                       %
%=======================================================================%
%
%
% ************************* MAP SETUP ********************************
%
% The following are available when \exec@map is called, except:
% * indicates \set@map@parts does the assignment
%
% @cd@a@      = there's text between the last argument and the end of the cell
% @cd@through = whether \@filla and \@fillb agree
% \exec@map   = command to execute
% \dimen 1    = left or lower shortfall
% \@head      = leading tip (macro)
%*\box   1    = leading tip (set)
% \@filler    = default filler against which to test for rule
% \@filla     = leading filler: box or rule leaders (empty for right half map)
%*\box   2    = leading repeater, or void for rule
% \dimen 2    = minimum length of arrow (tip-to-tip)
% \skip  2    = glue for leading filler
% \box   3    = middle
% \cd@penalty = penalty code value
% \@fillb     = trailing (right or lower) filler
%*\box   4    = trailing repeater, or void if rule
% \skip  4    = glue for trailing filler
% \@tail      = trailing tip (macro)
%*\box   5    = trailing tip (set)
% \dimen 5    = right or upper shortfall
% \box   6    = leading label or void
% \box   7    = trailing label or void
%
% diagonals only:
% \x@coord    = number of cells through which to pass horizontally
% \DiagramCellWidth = width of current column
% \y@coord    = number of cells through which to pass vertically
% \DiagramCellHeight = height of current row
%
% \rTo ->  \Horizontal@Map \rt: \rf:- \rm: \rf:- \rh:>
% \five@args picks up the five components and calls \get@arg,
% which parses the labels and options and calls \exec@horiz
%
\def\Horizontal@Map{%
\check@horiz{horizontal map}%   % avoid clashes
\default@args\@setup@horiz      % default parameters
%\let\fill@dot\hfdot % 12.7.94; moved to \@setup@horiz 28.7.95
\five@args}%
%
\def\@setup@horiz{%
\cd@penalty-9999                % \penalty code for default horizontal
\let\exec@map\exec@horiz        % continuation for \get@arg
\ifincommdiag
%       \baselineskip 1.4ex     % for positioning of labels in diagrams
%       \lineskip      .3ex
%       \lineskiplimit .3ex
\else   \size@dependencies
%       \dimen2=\min@map@length% min tip-to-tip arrow len 15.4.95
%       \baselineskip  .6ex     % much closer in text
%       \lineskip      .2ex
%       \lineskiplimit .2ex
   \ifinpile\else
        \skip2\z@
          plus 1.5\word@stretch % whole map stretches like three words
          minus .5\word@shrink % but shrinks like one
        \skip4\skip2
\fi\fi
\let\@filler\@fillh
%\let\fill@dot\hfdot % 28.7.95
\let@names{fill@dot}{rf:.}% 30.7.98
}%
%
% \ruTo -> \+To \PositiveGradienttrue \rTo (2,2)
% \+To  -> \Vector@Map \+t: \+f:- \+m: \+f:- \+h:>
% \@vector@setup sets \max@fraction and collects the five diagonal parameters.
% then \rTo is run with an altered definition of \Horizontal@Map
%
%\def\Rising@Map#1#2{\PositiveGradienttrue
%   \if@cd@use@PS@\@cd@PS@horiz@true\expandafter#1\else\expandafter#2\fi}%
%\def\Falling@Map#1#2{\PositiveGradientfalse
%   \if@cd@use@PS@\@cd@PS@horiz@true\expandafter#1\else\expandafter#2\fi}%
\def\Vector@Map{\@vector@setup 4}%
\def\Slant@Map {\@vector@setup{\if@use@TPIC@255\else6\fi}}%
\def\Slope@Map {\@vector@setup\default@max@fraction}% 7.4.95
%
% #1=maxfraction #2=tail #3=filler #4=middle #5=filler #6=head followed by
% gradient assignment and horizontal map to use in PostScript mode
\def\@vector@setup#1#2#3#4#5#6{%
  \default@args
  \def\x@coord{2}\def\y@coord{2}% coordinates for diagonals
  \def\x@offset{1}\def\y@offset{1}% diagonalbase
  %\global\@diagonals@used@true 12.7.94 moved to \exec@diagonal
  \let\Horizontal@Map\Rotated@Horizontal
  \def\max@fraction{#1}%
  \def\reassign@parts{\assign@five#2#3#4#5#6}%
}%
%
\def\Rotated@Horizontal{%
\@setup@horiz
\@cd@PS@horiz@true
\let\exec@map\exec@diagonal
\five@args}%
%
\new@if\if@cd@missive@\@cd@missive@true\@cd@missive@false\@cd@missive@true
\def\cds@missives{\@cd@missive@true}%
\def\exec@diagonal{%
   \if@cd@use@PS@
        \let\max@fraction\default@max@fraction
        \calc@horiz
        % attach labels to horizontal arrow if hug option
        \if@hug@\label@horiz\fi  % hug option 4.7.97
        \setbox0\hbox{\incommdiagfalse\put@horiz}%
        \if@cd@missive@
             % use missives to stretch the arrow in second pass
             % (\box0 and the labels are sent as the data)
             \exec@missive
        \else\global\@diagonals@used@true % 12.7.94
             % set the PS diagonal here on the first pass
             % (only uses \box0, so no labels unless they're in \box0)
             \exec@PS@diagonal
        \fi
        \ifvoid6 \ifvoid7 \@hug@true\fi\fi
        \if@hug@\else
             % 4.7.97 lazy implmentation of nohug option
             % assign empty parts to a LaTeX diagonal arrow
             \empty@parts
             \global\@diagonals@used@true
             \let\make@line\no@make@line % hack!
             \exec@LaTeX@diagonal
        \fi   
   \else\reassign@parts
        \reassign@filler
        \global\@diagonals@used@true % 12.7.94
        \exec@LaTeX@diagonal
   \fi}%
%
%
% default labels etc appropriate to all kinds of arrows
\def\default@args{%
\begingroup             % 
\dimen1=\MapShortFall   % leading shortfall
%\dimen2.5em            % min tip-to-tip arrow len within diagrams 15.4.95 
\dimen2=\min@map@length% minimum tip-to-tip length of arrow
\dimen5=\MapShortFall   % trailing shortfall
\setbox3=\box\voidb@x   % middle label
\setbox6=\box\voidb@x   % upper or left label
\setbox7=\box\voidb@x   % lower or right label
\@first@positional@true   % haven't done \positional@ yet
\mathsurround\z@        %
\skip2\z@ plus1fill minus 1000pt% amount to fill on left
\skip4\skip2            % and right
\@cd@through@false}%
%
\new@if\if@cd@through@\@cd@through@true\@cd@through@false
%
\def\assign@five#1#2#3#4#5{%
\let\@tail#1\let\@filla#2\let\@middle#3\let\@fillb#4\let\@head#5%
\@cd@through@false\ifx\@filla\@fillb\@cd@through@true\fi}%
%
\def\five@args#1#2#3#4#5{\assign@five#1#2#3#4#5\get@arg}%
%
%
%\def\front@args#1#2#3{%
%\let\@tail#3\let\@filla#2\setbox3=#1\let\@fillb\empty\let\@head\null\get@arg}%
%
%\def\back@args#1#2#3{%
%\let\@tail\null\let\@filla\empty\setbox3=#1\let\@fillb#2\let\@head#3\get@arg}%
%
%
% \dTo ->  \Vertical@Map \dt: \df:- \dm: \df:- \df:>
% \five@args picks up these five parameters and calls \get@arg
% which calls \exec@vert
%
\def\Vertical@Map{%
\check@vert433{vertical map}\exec@vert
\default@args
\cd@penalty-9995
\let\@filler\@fillv
%\let\fill@dot\vfdot % 12.7.94
\let@names{fill@dot}{df:.}% 30.7.98
\five@args}%
%
\def\break@args{%
     % If \get@arg happens to be called again,
     % make it do its continuation straight away.
     \def\get@arg{\exec@map}%
     \exec@map          % do the continuation
   \endgroup            % close the map environment
  \aftergroup\group@after@map}% check for enclosing braces
%
\def\set@map@parts{%
\setbox1=\@tail\setbox5=\@head
\ifvoid3 \ifx\@middle\null\else\setbox3=\@middle\fi\fi
\make@filler 2\@filla
\make@filler 4\@fillb
}%
%
%
\def\lift@map@parts#1{%
% lift all map parts by #1
\ifvoid 1\else\lift@map@part 1#1\fi
\ifvoid 2\else\lift@map@part 2#1\fi
\ifvoid 3\else\lift@map@part 3#1\fi
\ifvoid 4\else\lift@map@part 4#1\fi
\ifvoid 5\else\lift@map@part 5#1\fi
}
%
% lift map part #1 by #2
\def\lift@map@part#1#2{\setbox#1\vbox{%
\offinterlineskip
\box#1%
\dimen@\prevdepth
\advance\dimen@-#2\relax
\setbox0\null\dp0\dimen@\ht0-\dimen@
\box0}}%
%
\def\make@filler#1#2{%
\ifx#2\@filler
   \setbox#1=\box\voidb@x
\else
   \setbox#1=#2%
   \def#2{\xleaders\box#1}%
\fi}%
%
%
% ****************** OLD-STYLE MAP SETUP *****************
%
\cd@first@use\use@newarrow{\string\HorizontalMap, \string\VerticalMap\space
and \string\DiagonalMap\new@line are obsolete - use \newarrow@name\space
to pre-define maps}%
%
\def\HorizontalMap#1#2#3#4#5{%
\use@newarrow
\check@horiz{old horizontal map}% avoid clashes
\default@args
\@setup@horiz
\def\@tail{\old@horiz@part{#1}}% left tip, eg \rthookb
\old@horiz@fill\@filla{#2}% filler
\def\@middle{\old@horiz@part{#3}}% middle
\old@horiz@fill\@fillb{#4}% filler
\def\@head{\old@horiz@part{#5}}% right tip, eg \rhvee
\get@arg}%
%
\def\VerticalMap#1#2#3#4#5{%
\use@newarrow
\check@vert433{vertical map}\exec@vert
\default@args
\cd@penalty-9995
\let\@filler\@fillv
\def\@tail{\make@vert@part{#1}}% upper tip, eg \dthooka
\old@vert@fill\@filla{#2}% filler
\def\@middle{\make@vert@part{#3}}% middle
\old@vert@fill\@fillb{#4}% filler
\def\@head{\make@vert@part{#5}}% lower tip, eg \dharrow
\get@arg}%
%
\def\DiagonalMap#1#2#3#4#5{%
\use@newarrow
\default@args
\def\max@fraction{4}%
\let\@filler\undefined
\let\exec@map\exec@LaTeX@diagonal
\def\x@coord{2}\def\y@coord{2}% coordinates for diagonals\default@args
\def\x@offset{1}\def\y@offset{1}% diagonalbase
\def\@middle{\make@diag@part{#3}}%
\ifPositiveGradient
     \let\mv\raise
     \def\@tail{\make@diag@part{#5}}%
     \def\@filla{\make@diag@part{#4}}%
     \def\@fillb{\make@diag@part{#2}}%
     \def\@head{\make@diag@part{#1}}%
\else\let\mv\lower
     \def\@tail{\make@diag@part{#1}}%
     \def\@filla{\make@diag@part{#2}}%
     \def\@fillb{\make@diag@part{#4}}%
     \def\@head{\make@diag@part{#5}}%
\fi
\get@arg}%
%
% \vertical@name was in the "corruption-sensitive" section
\def\horizontal@name{-}\def\empty@name{\empty}%\def\vertical@name{|}
\def\old@horiz@fill{\make@old@fill\horiz@repeater\horizontal@name\@fillh}%
\def\old@vert@fill {\make@old@fill\vert@repeater \vertical@name  \@fillv}%
%
\def\make@old@fill#1#2#3#4#5{\def\next{#5}%
\ifx    \next#2%
        \let#4#3%        rule filler
\else   \let#4\null %    empty filler
\ifx    \next\empty\else
\ifx    \next\empty@name
\else   \let#4\next%     other filler
\fi\fi\fi}%
%
\def\old@horiz@part#1{%
\hbox{\mathsurround\z@\offinterlineskip
        \def\next{#1}%
        \ifx\next\empty\else\ifx\next\empty@name\else
        \begin@maths\mkern-1.5mu{\next}\mkern-1.5mu\end@maths
        \fi\fi
}}%
%
%
%=======================================================================%
%                                                                       %
%       (5A) LABELS                                                     %
%                                                                       %
%=======================================================================%
%
% \get@arg -> \switch@arg -> various -> \break@args -> \exec@map
% ^_<>~    -> \left@label etc -> \get@label -> \@get@label ->
%   \switch@label@arg -> \(un)braced@label -> \@end@label -> \get@arg
%
% Pick up following label and assign it appropriately.
% idea: force expansion of #3 before we read it (but this may execute & or \cr)
% idea: ensure that \box3 (in particular) doesn't shrink
% (\exec@horiz does this)
% vertical positioning of labels with descenders?
%
\def\get@label#1#2{% put label #3 in box #1 (#2 is ^_<>~-)
  \setbox#1=\hbox\bgroup
    \setbox0=\hbox{\begin@maths\labelstyle()\end@maths}%% ASCII round brackets
    \setbox1=\null\ht1\ht0\dp1\dp0\box1
    \kern.1\@em%
    \begin@maths
       \bgroup       % matches user's close brace (\begingroup wouldn't)
          \labelstyle
                                \aftergroup\@end@label
                                \@get@label}%
          %
          %#3%
       %\egroup supplied by the user or in \unbraced@label
                                \def\@end@label{%
    \end@maths
    \kern.1\@em%
  \egroup
    % We used to do the following to the finished box:
    %  \dimen0=\ht#1\advance\dimen0.4ex\ht#1=\dimen0
    %  \dimen0=\dp#1\advance\dimen0.4ex\dp#1=\dimen0
  \get@arg      % continue processing of further arguments
}%
%
% The text of the label is read in the same way as is that of a footnote
% (TeXbook page 363), ie we look at the next token, swallowing it if it is
% an open brace, and use \aftergroup to regain control after the close.
% At various places we do \end@label just in case the closing brace has been
% omitted; this is \empty outside the label text, but causes an error and
% inserts the closing brace inside it. We choose \empty rather than \relax
% because the latter would inhibit correct expansion of \cr\enddiagram.
%
\def\@get@label{\futurelet\next@token\switch@label@arg}%
%
\def\switch@label@arg{%% qualifiers on label arguments
\catcase\bgroup:\braced@label;% label text enclosed in {}
\catcase\egroup:\missing@label;% 
\catcase\space:\label@eat@space;% ignore space
\tokcase     [:\label@optional;%%]%ascii close square bracket 
\default      :\unbraced@label;% single token label text without {}
\endswitch}%
%
%\def\@get@label{%
%  \ifcat\bgroup\noexpand\next@token
%       \expandafter\braced@label
%  \else\expandafter\unbraced@label
%  \fi}%
%
\def\braced@label{%
    \let\end@label\bad@end@label      
    \let\next % pick up and discard user's opening brace (cf \footnote)
    }%
%
%\def\unbraced@label#1{\labelstyle#1\@end@label}% before 28.12.93
%
\def\unbraced@label#1{%
    \let\label@egroup\egroup
    {%
     \let\actually@braces@missing@around@macro@in@label\outer@empty
     \let\end@label\egroup@missing@label
     \let\label@egroup\label@egroups
     #1%
     \actually@braces@missing@around@macro@in@label
    }%
    \label@egroup
}%
\def\actually@braces@missing@around@macro@in@label{\let\next=}%
\def\missing@label{\egroup\cd@error{missing label}\help@endlabel}%
\def\egroup@missing@label{\egroup\missing@label}%
\outer\def\outer@empty{}%
% 14.4.94
% normally, \eat@egroup does nothing and
%    \label@egroup expands (once) to \egroup matching \bgroup above
% if #1 is \egroup, \eat@egroup eats following }, then
%    \label@egroup matches { and then \bgroup (no error message)
% if #1 is \rTo (or some other diagram command beginning \end@label)
%    then \end@label matches { and \bgroup with "missing label" error;
%    later \eat@egroup eats the following } and \label@egroup does nothing.
% if #1 is a macro it takes \missing@braces@around@label@macro as its first
%    argument; however as this is \outer there is an error message;
%    the } prevents the macro from taking \label@egroup as a second
%    argument (it gets \par instead)
%    then } matches { and \label@egroup matches \bgroup.
% if TeX inserts { after #1 (as it does e.g. for \hat), the } matches this
%    and \label@egroup inserts an explicit } token (as many as TeX inserted })
%    until it becomes \egroup, which matches the \bgroup above.
% (If we had assigned \egroup\label@egroup to \label@group the first time,
% the final (empty) \label@egroup would be left to be parsed as the next
% label argument and would fall through \switch@arg.)
% Unfortunately this doesn't pick up the *real* macro arguments,
% and TeX's error recovery is rather messy, but at least doesn't loop.
\def\label@egroup{}%
\def\label@egroups{\eegroup\label@egroup}% 15/4/95 changed from \egroup
%
\def\end@label{}%
%
\def\label@optional% 12.7.94
{\let\after@opt@arg\@get@label\get@square@arg\get@opt@arg@list}%
%
\new@help\help@endlabel{The text which has just been read is not allowed
  within map labels.}%
\def\bad@end@label{\egroup
  \cd@error{missing \egroup@name\space inserted after label}\help@endlabel}%
%
% OLD VERSION
% Catch missing label before closing bracket. ?When can this happen?
% TeX would insert \par for the missing argument, which would then become
% \enddiagram. Perhaps we should just redefine \par locally instead.
% Come to think of it, such a closing bracket has no business to be there
% anyway.
% Other cases can look after themselves by inserting \end@label.
% Could recognise (any kind of) \bgroup and change it to
% \bgroup\aftergroup\end@label to allow label environments.
% \def\@get@label{%
% \ifcat        \next@token\egroup
%       \expandafter\label@is@egroup
% \else \expandafter\@@get@label
% \fi}%
%\def\@get@label#1{#1\end@label}% was \@@get@label
%\def\label@is@egroup{\cd@error{arrow commands must not be em-braced}
%\help@brace
%  \end@label}%
%\new@help\help@label{A closing bracket followed \string
%                           ^, \string
%                              _, \string
%                                 <, \string
%                                    > or \string~.}%
%
% ******************* arrow argument parsing ********************
%
%            ----- Fetch particular labels -----
%
%   \hbox6 gets first/upper/left label & disables positional assignment to it
\def\upper@label {\@first@positional@false\get@label6}%
%   \hbox7 gets second/lower/right label label & disables all positional
\def\lower@label {\def\positional@{\@cd@a@true\break@args}\get@label7}%
\def\middle@label{\get@label3}% \hbox3 is (middle of arrow or) middle label
\new@if\if@first@positional@\@first@positional@true\@first@positional@false
%
\def\left@label{%
\ifPositiveGradient
\then   \expandafter\upper@label
\else   \expandafter\lower@label
\fi}%
\def\right@label{%
\ifPositiveGradient
\then   \expandafter\lower@label
\else   \expandafter\upper@label
\fi}%
\def\positional@{\cd@warning{labels as positional arguments are obsolete}%
\if@first@positional@
\then   %\@first@positional@false
        \expandafter\upper@label
\else   %\let\positional@\break@args % third positional argument terminates
        \expandafter\lower@label
\fi-}% provide dummy second argument (^_<>~) to \getlabel
%
%
%             ----- other argument parsing subroutines -----
%
% Get following token, perform case analysis and repeat or do \exec@map.
\def\get@arg{\futurelet\next@token\switch@arg}%
%
% discard following space and re-read token
\def\eat@space{\afterassignment\get@arg\let\next@token= }%
\def\label@eat@space{\afterassignment\@get@label\let\next@token= }%
%
% get a pair of coordinates, and an optional argument
\def\co@ordinates{\get@round@pair\@getcoords}%
\def\@getcoords#1#2{\def\x@coord{#1}\def\y@coord{#2}\get@arg}%
\def\optional@{\let\after@opt@arg\get@arg\get@square@arg\get@opt@arg@list}%
\def\set@dot@filler.{\do@set@dot@filler\get@arg}% 12.7.94
\def\do@set@dot@filler{% 13.11.94
     \let\@filla\fill@dot\let\@fillb\fill@dot % horizontals or verticals
     \def\reassign@filler{\let\@filla\dfdot\let\@fillb\dfdot}}% diagonals
\def\reassign@filler{}%
%
%=======================================================================%
%                                                                       %
%       (6) OPTIONAL ARGUMENTS                                          %
%                                                                       %
%=======================================================================%
%
%
% - width of each cell individually
%
% blobs:        define . o x O !
% poset (Hasse):size=2em,abut,blobs
% adjunction:
%
%\def\@@getoptarg#1,{%
%   \parse@opt@arg#1,%
%   \let\next\do@opt@arg@then
%   \ifx\@name\end@square@name
%       \let\next\after@opt@arg
%       \let\after@opt@arg\relax
%       \if@was@pair@\bad@pair@opt\fi
%   \fi
%   \next
%}%
%
%\def\do@opt@arg@then{\do@opt@arg\@@getoptarg}%
%
\def\@@getoptarg#1,{%
\parse@opt@arg#1,%
\begingroup
  \ifx\@name\end@square@name
     \if@was@pair@\aftergroup\bad@pair@opt\fi
     \aftergroup\do@after@opt@arg
  \else
        %\batchmode
        \expandafter\def\expandafter\@junk\expandafter{%
            \csname
            \@name%
            \endcsname}%
        %\scrollmode
        \expandafter\get@csname\@junk\end@get@csname
        \ifx\@junk\empty
             \aftergroup\do@opt@arg
             \expandafter\aftergroup\csname\cd@opt@prefix\@name\endcsname
             \expandafter\aftergroup\csname\cd@opt@prefix @\@name\endcsname
        \else
             \gdef\g@tmp{#1}%
             \cd@warning{\string\relax\space inserted before `[\g@tmp'}%
             \message{(I was trying to read this as a \cd@name\ option.)}%ascii
             \aftergroup\add@relax@before@square@bracket
        \fi
  \fi
\endgroup}%
%
\def\get@csname#1#2\end@get@csname{\def\@junk{#2}}%
\def\do@after@opt@arg{\let\next\after@opt@arg\let\after@opt@arg\relax\next}%
%
\def\add@relax@before@square@bracket#1],{%% ASCII close square bracket
  \do@after@opt@arg\relax
  \def\@junk{#1}%
  \ifx\@junk\empty
       \def\@junk{[\g@tmp]}%% ASCII open and close square bracket
  \else\def\@junk{[\g@tmp,#1]}%% ASCII open and close square bracket
  \fi
  \@junk}%
%
\def\do@opt@arg#1#2{%
%\expandafter\let\expandafter\next\csname\cd@opt@prefix @\@name\endcsname
% \next=#1=\csname cds@\@name\endcsname
% #2=\csname cds@@\@name\endcsname
\ifx#2\undefined
     \ifx#1\undefined
          % neither \cds@name nor \cds@@name is defined
          \cd@warning{option `\@name' undefined}%
     \else
          % \cds@name is defined but \cds@@name isn't: execute without pair
          #1%
     \fi
\else
     % \cds@@name#1#2 is defined - the command takes a pair value
     \if@was@pair@
         % this is the second half - execute and reset
         \expandafter#2\@value
         \@was@pair@false
     \else
         % this is the first half - set flag and wait
         \@was@pair@true
\fi  \fi
\next@opt@arg}%
%
\new@if\if@was@pair@\@was@pair@true\@was@pair@false
%
\def\parse@opt@arg#1,{%
   \if@was@pair@
      \ifx\@value\undefined\bad@pair@opt\else
            \expandafter
        \@parse@pair
            \@value
            ,#1,(,),(,)[]%%ASCII 5commas two pairs round, pair square
   \fi\fi
   \if@was@pair@ % tries again if parsing as a pair failed
   \else\@parse@opt@arg#1==,%
   \fi
}%
\def\bad@pair@opt{%
   \cd@warning{option `\@name' needs (x,y) value}%
   \@was@pair@false
   \let\@name\empty}%
%
\def\@parse@opt@arg#1=#2=#3,{%
    \def\@name{#1}\def\@value{#2}\def\@junk{#3}%
    \ifx\@junk\empty\let\@value\undefined\fi
}%
%% ASCII 2commas 2pair round, pair square on next line
\def\@parse@pair#1(#2,#3)#4,(#5,#6)#7[]{%ascii
    \def\@value{{#2}{#3}}%
    \def\@junk{#1#4#5#6}%
    \ifx\@junk\empty
         \def\@junk{#7}%
         \ifx\@junk\empty\bad@pair@opt\fi
    \else\bad@pair@opt
    \fi
}%
%
\def\cd@opt@prefix{cds@}\let\after@opt@arg\relax
%
%
%
\def\get@mand@value#1{%
\ifx\@value\undefined
        \cd@warning{option `\@name' needs a value}%
\else
        #1\@value\relax
\fi}%
%
\def\get@opt@value#1#2{%
\ifx\@value\undefined
        #1#2\relax
\else
        #1\@value\relax
\fi}%
%
\def\cds@@showpair#1#2{\message{x=#1,y=#2}}%
\def\cds@@diagonalbase#1#2{\edef\x@offset{#1}\edef\y@offset{#2}}%
%
\def\ps@prog#1{%
    \def\next{#1}%
    \let@names{@x}{cdps@#1}%
    %\message{PostScript translator `#1` requested.}%
    \ifx\next\empty\bad@ps@prog\next{cannot be used}%
    \else\ifx\next\relax % \csname undefined\endcsname = \relax
         \bad@ps@prog\next{unknown}%
    \else\let\verbatim@ps@special\@x
    \fi\fi
}%
\def\bad@ps@prog#1#2{% 24.8.2003 pass name as #1 instead of \@value
   \cd@warning{PostScript translator `#1' #2}}%
   %\dont@use@ps\let\cds@PS\empty\let\cds@noPS\empty}% removed 30.12.07
%
%
\def\obs@display{}%
\def\set@new@display{\@cd@hbox@false\edef\obs@display{\noexpand
  \cd@refmt@error{\@name\space ignored within maths}}}%
%
\def\diagramstyle{%
  \size@dependencies
  \let\after@opt@arg\relax % 13.7.94
  \@ifoptarg\get@opt@arg@list\get@opt@arg@list}%
\let\diagramsstyle\diagramstyle
%
% ********************** THE ACTUAL OPTIONS *************************
%
%
\new@if\if@cd@text@flow@\@cd@text@flow@true\@cd@text@flow@false
\new@if\if@cd@one@liner@\@cd@one@liner@true\@cd@one@liner@false
\new@if\if@cd@leqno@\@cd@leqno@true\@cd@leqno@false
\new@if\if@cd@centre@display@\@cd@centre@display@true\@cd@centre@display@false
\@cd@centre@display@true
\new@if\if@cd@centre@hlabel@\@cd@centre@hlabel@true\@cd@centre@hlabel@false
\new@if\if@cd@centre@vlabel@\@cd@centre@vlabel@true\@cd@centre@vlabel@false
\new@if\if@use@TPIC@\@use@TPIC@true\@use@TPIC@false
\new@if\if@cd@PS@horiz@\@cd@PS@horiz@true\@cd@PS@horiz@false
\new@if\if@cd@hbox@\@cd@hbox@true\@cd@hbox@false
\new@if\if@cd@landscape@\@cd@landscape@true\@cd@landscape@false % 10.7.94
\new@if\if@need@PS@lib@\@need@PS@lib@true\@need@PS@lib@false % 10.7.94
%
\def@name{cds@ }{}\def@name{cds@}{}% spaces are no-ops
\def@name{cds@1em}{\CellSize1\@em}\def@name{cds@1.5em}{\CellSize1.5\@em}%
\def@name{cds@2em}{\CellSize2\@em}\def@name{cds@2.5em}{\CellSize2.5\@em}%
\def@name{cds@3em}{\CellSize3\@em}\def@name{cds@3.5em}{\CellSize3.5\@em}%
\def@name{cds@4em}{\CellSize4\@em}\def@name{cds@4.5em}{\CellSize4.5\@em}%
\def@name{cds@5em}{\CellSize5\@em}\def@name{cds@6em}{\CellSize6\@em}%
\def@name{cds@7em}{\CellSize7\@em}\def@name{cds@8em}{\CellSize8\@em}%
\def\cds@abut{\MapsAbut\dimen1\z@\dimen5\z@}%
\def\cds@alignlabels{\@cd@centre@hlabel@false\@cd@centre@vlabel@false}%
\def\cds@amstex{%
  \ifincommdiag
       \amstex@diagram@setup
  \else\def\CD{\diagram[amstex]}%%ascii square brackets []
  \fi
  \assign@at\catcode`\@\active
}%
\def\cds@b{\let\cd@vert@positioning\cd@vbottom}%
\def\cds@balance{\let\cd@horiz@positioning\cd@balance}%
\let\cds@bottom\cds@b
\def\cds@center{\cds@vcentre\cds@nobalance}%
\let\cds@centre\cds@center
\def\cds@centerdisplay{%
  \@cd@centre@display@true\set@new@display\cds@balance}%
\let\cds@centredisplay\cds@centerdisplay
\def\cds@crab{\get@opt@value\crab@{.5\PileSpacing}}%
\def@name{cds@crab-}{\crab@-.5\PileSpacing}%
\def@name{cds@crab+}{\crab@.5\PileSpacing}%
\def@name{cds@crab++}{\crab@1.5\PileSpacing}%
\def@name{cds@crab--}{\crab@-1.5\PileSpacing}%
\def\cds@defaultsize{\get@opt@value{\let\default@size}{3em}\set@max@fraction}%
\def\cds@displayoneliner{\@cd@one@liner@false}%
\let\cds@dotted\do@set@dot@filler
\def\cds@dpi{\set@resolution{1truein}}%
\def\cds@dpm{\set@resolution{100truecm}}%
\let\cd@eqno\undefined
\def\cds@eqno{%
  \let\cd@eqno\@value
  \let\set@currentlabel\empty}%
\def\cds@fixed{\@cd@missive@false}%
\new@if\if@adjust@flush@left@\@adjust@flush@left@true\@adjust@flush@left@false
\def\cds@flushleft{%
  \@adjust@flush@left@false % 15.6.97
  \@cd@centre@display@false\set@new@display\cds@nobalance
  \get@opt@value\cd@left@margin\cd@left@margin}%
\def\cds@gap{\set@axis%
  \setbox3=\null\ht3=\rule@height\dp3=\rule@depth 
  \get@opt@value{\wd3=}\MapShortFall}
\def\cds@grid{%
  \ifx\@value\undefined
      \let\h@grid\relax\let\v@grid\relax
  \else
      \let@names{h@grid}{cdgh@\@value}%
      \let@names{v@grid}{cdgv@\@value}%
      \ifx\h@grid\relax
          \cd@warning{unknown grid `\@value'}%
      \else\@cd@tight@true
  \fi\fi}%
\let\h@grid\relax\let\v@grid\relax
\def\cds@gridx{\ifx\@value\undefined\else\cds@grid\fi
  \let\next\h@grid\let\h@grid\v@grid\let\v@grid\next}%
\def\cds@h{\get@mand@value\DiagramCellHeight}%
\def\cds@hcenter{\let\cd@horiz@positioning\cd@fullwidth}%
\let\cds@hcentre\cds@hcenter
\def\cds@heads{%
  \get@opt@value{\let\the@default@head}\the@default@head
  \set@arrowhead
  \if@cd@use@PS@\else\ifx\the@default@head\LaTeX@name\else
        \default@diagonal
  \fi\fi
}%
\let\cds@height\cds@h
\let\cds@hmiddle\cds@balance
\def\cds@htriangleheight{\get@opt@value\DiagramCellHeight\DiagramCellHeight
   \DiagramCellWidth1.73205\DiagramCellHeight}%
\def\cds@htrianglewidth{\get@opt@value\DiagramCellWidth\DiagramCellWidth
   \DiagramCellHeight.57735\DiagramCellWidth}%
\new@if\if@hug@\@hug@true\@hug@false\@hug@true
\def\cds@hug{\@hug@true}
\def\cds@inline{\@cd@hbox@true\let\obs@display\empty}%
\def\cds@inlineoneliner{\@cd@one@liner@true}%
\def@name{cds@l>}{\get@mand@value{\let\min@map@length}\dimen2=\min@map@length}%
\def\cds@labelstyle{\get@mand@value{\let\labelstyle}}%
\def\cds@landscape{\@cd@landscape@true}% 10.7.94
\def\cds@large{\CellSize5\@em}%
\let\set@currentlabel\empty
\def\set@currentlabel@to@equation{%
   \refstepcounter{equation}%
   \def\cd@eqno{\hbox{\@eqnnum}}}%
\def\cds@LaTeXeqno{\let\set@currentlabel\set@currentlabel@to@equation}%
\def\cds@lefteqno{\@cd@leqno@true}%
\def\cds@leftflush{\cds@flushleft\@adjust@flush@left@true}% 15.6.97
\def\cds@leftshortfall{\get@mand@value{\dimen1 }}%
% \def\cds@locate
\def\cds@lowershortfall{\ifPositiveGradient\cds@leftshortfall\else
        \cds@rightshortfall\fi}%
\def\cds@loose{\@cd@tight@false}%
\def\cds@midhshaft{\@cd@centre@hlabel@true}%
\def\cds@midshaft{\@cd@centre@hlabel@true}%
\def\cds@midvshaft{\@cd@centre@vlabel@true}%
%\def\cds@midvshaft{\cd@warning{midvshaft option doesn't work}}%
\def\cds@moreoptions{\@cd@a@true}% tested in \@@@diagram
\let\cds@nobalance\cds@hcenter
\def\cds@nohcheck{\nohcheck}%
\def\cds@nohug{\@hug@false}
\def\cds@nooptions{\def\@@diagram{\exec@diagram}}%
\let\cds@noorigin\cds@nobalance
\def\cds@nopixel{\pixel@size 4\one@sp\size@dependencies}%
\def\cds@UO{\dont@use@ps\global\let\better@use@ps\empty}%
\def\cds@UglyObsolete{\cds@UO\let\cds@PS\empty}% \let\cds@noPS\empty}% 30.12.07
\def\cd@nonoPS#1{\cd@warning{option `#1' renamed as `UglyObsolete'}}% 30.12.07
\def\cds@noPostScript{\cd@nonoPS{noPostScript}}% 30.12.07
\def\cds@noPS{\cd@nonoPS{noPostScript}}% 30.12.07
\def\cds@notextflow{\@cd@text@flow@false}%
\def\cds@noTPIC{\@use@TPIC@false}%
\def\cds@objectstyle{\get@mand@value{\let\objectstyle}}%
\def\cds@origin{\let\cd@horiz@positioning\cd@zerowidth}%
\def\cds@p{\get@mand@value\PileSpacing}%
\let\cds@pilespacing\cds@p
\def\cds@pixelsize{\get@mand@value\pixel@size\reset@map@breadth}%
\def\cds@portrait{\@cd@landscape@false}% 10.7.94
\def\cds@PostScript{\use@ps\global\let\better@use@ps\empty
        \get@opt@value\ps@prog\empty}%
\def\cds@PS{\use@ps\global\let\better@use@ps\empty}%
\info@at@end\better@use@ps{\typeout{\cd@name: try the PostScript option for better results}}%
\def\cds@repositionpullbacks{%
  \let\make@pbk\overprint@pbk\let\pbk@sh\pbk@osh}% 14.11.94
\def\cds@righteqno{\@cd@leqno@false}%
\def\cds@rightshortfall{\get@mand@value{\dimen5 }}%
\def\cds@ruleaxis{\get@mand@value{\let\axisheight}}% 17.7.94
\def\cds@cmex{\let\make@vert@part\cmex@vert@part
\let\set@offset@axis\set@cmex@offset@axis}%
\def\cds@s{\cds@height\DiagramCellWidth\DiagramCellHeight}%
\def\cds@scriptlabels{\let\labelstyle\scriptstyle}%
\def\cds@shortfall{\get@mand@value\MapShortFall
        \dimen1\MapShortFall\dimen5\MapShortFall}%
\def\cds@showfirstpass{\get@opt@value{\let\firstpass@showboxdepth}\z@}%
\def\cds@silent{\def\cd@refmt@error##1{}\def\cd@warning##1{}}%
\let\cds@size\cds@s
\def\cds@small{\CellSize2\@em}%
\def\cds@snake{\get@opt@value\snake@\z@}% 4.7.97
\def\cds@t{\let\cd@vert@positioning\cd@vtop}%
\def\cds@textflow{\@cd@text@flow@true\set@new@display}%
\def\cds@thick{\let\line@font\tenlnw
   \intended@breadth\default@mapbreadth
   \get@opt@value\MapBreadth{2\intended@breadth}%
   \set@arrowhead}% 15.6.97
\def\cds@thin{\let\line@font\tenln
   \get@opt@value\MapBreadth{\default@mapbreadth}%
   \set@arrowhead}% 15.6.97
\def\cds@tight{\@cd@tight@true}%
\let\cds@top\cds@t
\def\cds@TPIC{\@use@TPIC@true}%
\def\cds@uppershortfall{\ifPositiveGradient\cds@rightshortfall\else
        \cds@leftshortfall\fi}%
\def\cds@vcenter{\let\cd@vert@positioning\cd@vcentre}%
\let\cds@vcentre\cds@vcenter
\def\cds@vtriangleheight{\get@opt@value\DiagramCellHeight\DiagramCellHeight
   \DiagramCellWidth.577035\DiagramCellHeight}%
\def\cds@vtrianglewidth{\get@opt@value\DiagramCellWidth\DiagramCellWidth
   \DiagramCellHeight1.73205\DiagramCellWidth}%
\def\cds@vmiddle{\let\cd@vert@positioning\cd@vmiddle}%
\def\cds@w{\get@mand@value\DiagramCellWidth}%
\let\cds@width\cds@w
%
%
%=======================================================================%
%                                                                       %
%       (7) THE DIAGRAM - OPTIONS AND OUTPUT                            %
%                                                                       %
%=======================================================================%
%
%
% The following macros are preparatory to the diagram, picking up optional
% arguments and beginning the main \vbox.
%
% \diagram -> \@diagram -> \@@diagram [-> \@@@diagram] -> \exec@diagram
% -> \@exec@diagram -> \enddiagram=\@end@diagram -> \after@diagram
% (\matrix@to@buffer, \reformat@matrix) -> \output@diagram -> \exit@diagram
%
\def\diagram{\relax\protect\@diagram}%
\def\enddiagram{\protect\misplaced@enddiagram}% real one in \inner@environment
%
\def\diagraminline{\diagram[inline,moreoptions]}%
\def\enddiagraminline{\enddiagram}%
%
\def\@diagram{%
\bbgroup        % {} closed in \exit@diagram
  \save@begin@at@line   % line number for reformatting error messages
  \incommdiagtrue
  \edef\save@row@no{\the\cd@row}% save row number
  \global\cd@row\z@
    %
    % LaTeX pre 15/12/87 had \maxboxdepth\z@; this found its way into
    % a journal style with which Richard Kennaway had a problem.
  \boxmaxdepth\maxdimen % added 3 June 1994
    %
    % amslatex's equation environment sets \everycr;
    % reported by Bruce Pollock <pollock@newton.rutgers.edu> 5 April 1995
  \everycr{}%
    %
    % test for (active) pdftex
  \test@pdf
    %
    % pdfsync package also sets these: 3 Jan 2006
    % Hubert.Flenner@ruhr-uni-bochum.de  Fri May 14 14:31:36 2004
    % Arthur Ogus <ogus@Math.Berkeley.EDU> Tue Jan  3 17:21:02 2006
  \everymath{}%
  \everyhbox{}%
    %
    % That was not enough.  See email 25--30 Jan 2008 with
    % jerome.laurens@u-bourgogne.fr  (author of pdfsync)
    % and Bernd Strieder <strieder@informatik.uni-kl.de> (user).
  \ifx\pdfsyncstop\undefined\else\pdfsyncstop\fi
%  \futurelet\next
  \@@diagram}%
  %
  \def\@@diagram{%
        \@cd@a@false
        \let\after@opt@arg\@@@diagram
   \@ifoptarg\get@opt@arg@list\exec@diagram}%
  %
%  \def\@@diagram{%             % do we have options?
%     \ifx[\next
%       \expandafter\cd@with@opt        % yes
%     \else
%       \expandafter\exec@diagram       % no
%     \fi
%  }%
%  %
%  \def\cd@with@opt{%
%       \@cd@a@false
%       \let\after@opt@arg\@@@diagram
%       \get@square@arg\get@opt@arg@list}% read and execute options
  %
  \def\@@@diagram{%
  \if@cd@a@                     % did we ask for more options?
        \expandafter\@@diagram          % yes (\cds@moreoptions)
  \else \expandafter\exec@diagram       % no
  \fi}%
  %
  \def\exec@diagram{%
   % \next may have been &, which is a dangerous thing to have around
  \let\next@token\relax
  %
  \if@cd@landscape@\if@cd@use@PS@\else % 10.7.94
        \if@pdf@\else % won't be needed when we're finished
       \cd@refmt@error{landscape ignored without PostScript}%
       \@cd@landscape@false
  \fi\fi\fi
  \set@currentlabel
  %
  \setbox2=\vbox\bgroup % avoid \box0 since overwritten by \everypar
     \inner@environment
     \@exec@diagram
     }%
     % \@exec@diagram is in the next section; it eventually calls
     %
     \def\output@diagram{%
     %
     % having provided the following positioning statistics:
     %     \expandafter\message{%
     %       interaxis=\the\dimen1, %
     %       topheight=\the\cd@top@height, %
     %       fullheight=\the\completed@depth, %
     %       bottomdepth=\the\row@depth, %
     %       dimen0=\the\dimen0, %
     %       dimen2=\the\dimen2, %
     %       dimen7=\the\dimen7, %
     %       right over=\the\right@over, %
     %       left over=\the\left@over%
     %       }%
     %
     %  \dimen0:        distance between leftmost and rightmost centres
     %  \dimen1:        distance between top and bottom axes
     %  \dimen2:        right width of rightmost column
     %  \rule@height :  axis height
     %  \cd@top@height: height of top row
     %  \completed@depth :      height from last baseline to top
     %  \right@over :   from centre of leftmost to far edge of rightmost
     %  \left@over :    left width
     %  \row@depth :    depth of bottom row
     %  \cd@top:        number of rows
     %  \cd@right:      number of columns
     %  \vert@wd@in@leftmost: left width of (last) vertical system in column 1
     %                   or \undefined if none (15.6.97)
     %
     %
     % The commands \cd@horiz@positioning and \cd@vert@positioning are assigned
     % by the positioning options to routines which adjust these statistics.
     %
     \if@cd@landscape@ % 10.7.94
          \cd@vtop
     \else\cd@vert@positioning
     \fi
     \cd@horiz@positioning
     %
     % Now force our box to have the required depth and right width.
     \nointerlineskip
     \setbox0=\null\ht0-\row@depth\dp0\row@depth\wd0\right@over
     \box0
     %
     \global\cd@dim@g\left@over % save left width
     \global\cd@num@g\cd@top    % and number of rows
     %
     % alignment adjustment on left (15.6.97)
     \ifx\vert@wd@in@leftmost\undefined
         \global\cd@dim@h\left@over % no verticals - use edge of text
     \else
         \global\cd@dim@h\vert@wd@in@leftmost % width of multiple verticals
     \fi
     %
  \egroup               % end of \setbox2=\vbox\bgroup in \exec@diagram
  \make@end@at@line     % 
  %
  % The following are now available:
  %  \box2:     the completed diagram, with its left width smashed
  %  \cd@dim@g: the left width
  %  \cd@dim@h: the left width alignment adjustment
  %  \cd@num@g: number of rows
  %  mode:      as in the text outside
  %
  \if@cd@landscape@ % 10.7.94
        \setbox2=\hbox to\dp2{%
          %\dp2=\cd@dim@g\ht2\wd2% replaced with vrule 6.10.2001
          \vrule height\wd2 depth\cd@dim@g width\z@
          \global\cd@dim@g\ht2%
          \ht2\z@\dp2\z@\wd2\z@
          \if@pdf@ 
              \pdf@literal{q 0 1 -1 0 0 0 cm}%
          \else
              \global\@need@PS@lib@true
              \verbatim@ps@special{0 1 bturn}%
          \fi
          \box 2%
          \do@eturn %\verbatim@ps@special{eturn}%
          \hss}%
        \@cd@one@liner@false
  \fi
  %
  \ifnum\cd@num@g=1 \else\@cd@one@liner@false\fi
  %
  \global\@ignorefalse
  %
  % decide what to do with the finished diagram
  %
  \if@cd@hbox@\leavevmode\fi
  %
  \ifvmode
     % vertical mode:
     % ie page \vbox or \vadjust, but \ifinner isn't a reliable indication
     % of which it is, as it is \iftrue in \vbox and also \vadjust.
     % This makes it difficult to see how we could handle floats.
     %
     % We must begin a paragraph.  This is because LaTeX uses \trivlist for
     % numerous purposes (center for instance). This sets a flag (\if@newlist)
     % which is cleared (globally) in \everypar. It claims that there is a
     % "missing item" if it finds it true at the end, ie if no paragraph has
     % been created in the meantime.
     %
     % The usual way of forcing a paragraph is \leavevmode or \noindent,
     % but \cd@display uses $$..$$ and LaTeX seems to be happy with this.
     %
     \cd@display
     %
  \else
     \ifmmode           % maths mode
        %\ifinner\else  % can't distinguish $/$$ within \bbgroup\eegroup
           \obs@display
        %\fi
        \put@cd@box
  %
     \else                      % horizontal mode
        \if@cd@one@liner@\@cd@hbox@true\fi
        \ifinner\@cd@hbox@true\fi
        %
        \if@cd@hbox@     \put@cd@box     % hbox or one-liner option
        \else\if@cd@text@flow@
                        \cd@text@flow   % --- flow
             \else      \cd@display     % --- display
        \fi\fi
  \fi\fi
  %
  \exit@diagram}%
  %
  \def\exit@diagram{%
  %
  \global\cd@row\save@row@no\relax % restore row number
  %
  \if@end@diagram@ok@ % was \enddiagram deliberate or anticipated?
         \global\@end@diagram@ok@false  % deliberate
  \else\aftergroup\do@fated@enddiagram  % antipated - give error message
  \fi
  %
  \if@ignore\aftergroup\ignorespaces\fi % ignore spaces after display
  %
\eegroup % main {} begun in \@diagram
\ignorespaces%
}% and go home!
% That's REALLY the end of the diagram as far as we are concerned,
% although LaTeX will do further processing if \end{diagram} has been used;
% in particular it will do \ignorespaces conditionally on \if@ignore.
%
% ***************** positioning options ********************
%
%   VERTICAL
\def\cd@vtop{\advance\row@depth\dimen1\relax}%
\def\cd@vmiddle{\advance\row@depth.5\dimen1\relax}%
\def\cd@vbottom{}%
\def\cd@vcentre{\cd@vtop\advance\row@depth\cd@top@height\divide\row@depth 2
   \advance\row@depth-\axisheight\relax}%
%
%   HORIZONTAL
\def\cd@fullwidth{}%
\def\cd@zerowidth{\left@over\z@}%
%
\def\cd@balance{%
\ifdim  \dimen2>\left@over 
        \left@over \dimen2
\else   \dimen2\left@over 
        \right@over \dimen0
        \advance\right@over \dimen2
\fi}%
%
% ***************** output manipulation ********************
%
\def\cd@text@flow{%
   %
   % Remove all positive glue from before the diagram and save it.
   % same as LaTeX's \@bsphack \@esphack
   \skip0\z@\relax
   \loop   \skip1\lastskip
   \ifdim  \skip1>\z@
           \unskip
           \advance\skip0\skip1
   \repeat
   %
   \vadjust{%
        % Insert glue and penalties as if TeX
        %   had created the display itself.
        \prevdepth\dp\strutbox
        \penalty\predisplaypenalty
        \vskip\abovedisplayskip
        \cd@display@box
        \penalty\postdisplaypenalty
        \vskip\belowdisplayskip
   }%
   %
   \ifdim\skip0=\z@\else        % if there was any glue before the diagram,
        \hskip\skip0            % put it back afterwards and
        \global\@ignoretrue     % do \ignorespaces after \end{diagram}
   \fi
}%
%
% Our own display output when we have a single
% diagram to contribute to the horizontal list.
% ideas:
% What if preceding line of text is short (\predisplaysize)?
% Calculate \prevgraph based on height of diagram?
%
\def\cd@display{%
  \maths@display        % $$
    \kern-\displayindent% undo any prevailing paragraph indentation
    \cd@display@box     % output the box
  \maths@display%       % $$
  \global\@ignoretrue   % do \ignorespaces after \end{diagram}
}%
%
\def\cd@display@box{\hbox to\hsize{%
  %
  % if [leftflush], adjust alignment (15.6.97)
  \if@adjust@flush@left@\ifdim\cd@dim@h=\z@\else
      \advance\cd@dim@g-\cd@dim@h
      \setbox2=\hbox{\kern\cd@dim@h\box2}%
  \fi\fi
  %
  % make the equation number
  \setbox1=\hbox{\ifx\cd@eqno\undefined\else\begin@maths\cd@eqno\end@maths\fi}%
  % insert it on the left if required
  \if@cd@leqno@
     \if@cd@centre@display@\else
        \advance\cd@dim@g\wd1
     \fi
     \wd1\z@
     \box1
  \fi
  % check that the diagram will fit on the page
  \dimen0\wd2
  \advance\dimen0\wd1
  \advance\dimen0-\hsize
  % does it fit on the page with the specified indentation? 2.3.94
  \ifdim\dimen0>-\cd@left@margin
      % no - switch from flushleft to centredisplay
      \@cd@centre@display@true
  \fi
  % does it fit on the page at all?
  \advance\dimen0\cd@dim@g
  \ifdim\dimen0>\z@
      \cd@refmt@error{wider than the page by \the\dimen0 }%
      \@cd@centre@display@true
  \fi
  % space to the left of the diagram
  \if@cd@centre@display@
        \hss
  \else \at@least\cd@dim@g\cd@left@margin
  \fi
  % output the diagram itself
  \put@cd@box
  % space to the right
  \hss\kern-\wd1\box1   % right equation number (already void if left)
}}%
%
% Raw output used in maths, user display, \hbox (eg picture) and one-liner.
% 10.7.94 define PostScript commands here if needed
\def\put@cd@box{%
   \if@need@PS@lib@\if@in@matrix@\else
      \def@ps@turn
      \global\@need@PS@lib@false
   \fi\fi
   \kern\cd@dim@g\box2 }%
%
%
% ***************** notes ********************
%
% For some reason the usual \futurelet method gets tied up
% if the next token is &.
% (Try again: there was another bug, with \cd@state)
%\def\@diagram{\begingroup\@ifoptarg\cd@with@opt\@@diagram}%
%\def\@@diagram{{%
%       \aftergroup\exec@diagram
%       \ifcat  \next@token\@and
%               \aftergroup\replace@and
%       \fi
%}}%
%
%\def\replace@and{\omit\hskip 1sp plus1fil}\def\@@and{\@and}%
%
% nested diagram bug:
% $\begin{array}{ll}\begin{diagram}&A\\B\end{diagram}$
% causes: ! Emergency stop. <recently read> \endtemplate
% not fixed by \relax or by changing \begingroup\endgroup to \bgroup\egroup
% \@@diagram picks up $ (in right template of array) and the log file ends
% (interwoven alignment preambles are not allowed).  (11 July 1992)
% but it is fixed by changing to \bbgroup\eegroup
%
% idea: forbid a list of commands within diagram
%
%\edef\cd@mode@outside  {% code for external mode
%               \ifmmode\ifinner0%      $..$
%                       \else1\fi%      $$..$$  
%       \else   \ifhmode\ifinner2%      \hbox{..}
%                       \else3\fi%      paragraph (maybe in \vbox)
%       \else   \ifvmode\ifinner4%      \vbox{..} or \vadjust{..}
%                       \else5\fi%      current page
%       \fi\fi\fi}%
%
%=======================================================================%
%                                                                       %
%       (8) THE MATRIX                                                  %
%                                                                       %
%=======================================================================%
%
\new@if\if@diagonals@used@\@diagonals@used@true\@diagonals@used@false
%
\def\inner@environment{%
\size@dependencies
\ifdim\DiagramCellHeight=-\maxdimen\DiagramCellHeight\default@size\fi
\ifdim\DiagramCellWidth =-\maxdimen\DiagramCellWidth \default@size\fi
\global\@diagonals@used@false
\@in@matrix@true % 12.7.94
\let\group@after@map\empty
\let\cd@and\@and
\let\overprint\over@print
\let\@bomb\the@bomb             % pull out the pin!
\let\enddiagram\@enddiagram
\let\\\diagram@cr               % for LaTeX users
\let\par\par@enddiagram         % deal with spurious \par inside diagram
\let\end@label\empty            % we put these at the end
\let\switch@arg\cd@switch@arg   % allow &<>() arguments to maps too
\let\shift\cd@hshift            % shift objects
\baselineskip\DiagramCellHeight % minimum line spacing
\lineskip\z@                    % otherwise, just stretch as necessary
\lineskiplimit\z@               %
\mathsurround\z@                % no unnecessary space in cells
\tabskip\z@                     % or between them horizontally (ignored anyway)
\cd@state                       % set up automaton to check horizontal state
}%
%
%
\def\@exec@diagram{%
\penalty-123             % marker - checked in \matrix@to@buffer
\begingroup             % confine the following to the text of the diagram
\@cd@landscape@false    % don't rotate nested diagrams 12.7.94
\aftergroup\after@diagram% execute at corresponding \egroup
%\incommdiagtrue
%
\halign\bgroup          % begin the matrix (see below for template)
\global\advance\cd@row1 % maintain row number in matrix
\vadjust{\penalty1}%    % code below row picked up in \matrix@to@buffer
\global\cd@cell\z@      % initialise column number
\cd@state               % horiz state (\cd@donat) at left is space donation
\begin@cell##\end@cell  % template for leftmost cell
\@and\@and              % "&&" means repeat following indefinitely
\receive@cell@type      % recover horiz state from \send@cell@type
\begin@cell##\end@cell  % template for subsequent cells
\cr                     % end of template
}%
%
% insert the matrix between calling these two macros
%
\def\@enddiagram{%
\end@label              % catch missing close brace after label
\enddiagram@endpile     % ditto after \pile
\crcr                   % catch missing \cr
\egroup                 % end of \halign
\global\@end@diagram@ok@true% signal we meant
\endgroup               % to do \after@diagram (\aftergroup)
}%
%
%
%=======================================================================%
%                                                                       %
%       (8) CELLS                                                       %
%                                                                       %
%=======================================================================%
%
%
%***************************** the template ****************************
%
% The main purpose of the template is to recognise empty cells quickly.
% The \hbox'es produced by the various types of cell are:
% - empty or white:     \glue 1sp plus 1fil
% - \span (\across):    completely empty
% - object:             \hfil\mathon...\mathoff\hfil
% - arrow etc:          \hfil\mathon...\penalty...\mathoff\hfil
%
% \save@cell@at@line?
% do \futurelet and eager expansion advance \inputlineno? - yes
% (may be better to do it during previous \end@cell instead)
\def\begin@cell{%
%\save@cell@at@line
\global\advance\cd@cell 1
\futurelet\next@token\@begin@cell}%
%
% A hack for future reference:
% Without \end@cell, we'd pick up \endtemplate as \thefirsttoken
% however it's \outer, so the only way of testing for it is by \ifx
% with something obtained in the same way. Moreover \theendtemplate
% must be used before it's defined, because it's \outer.
% Knuth is devious, but we've got round him!
% \def\gettheendtemplate{\glet\theendtemplate\thenexttoken}
% \halign{\futurelet\thenexttoken\gettheendtemplate#\cr\cr}
%
%
\def\@begin@cell{%
\ifx    \next@token\end@cell
\then   \hskip 1sp plus 1fil \relax
        \let\end@cell\relax\save@cell@at@line
\else   \hfil\begin@maths\objectstyle
        \let\group@after@map\bad@group@after@map
\fi}%
%
%
% The \halign cell \hbox of an ordinary object cell is
%       \hfil
%       \mathon
%       (text)
%       \penalty -9993
%       \mathoff
%       \null
%       \kern -2\cd@hshift
%       \null
%
% Missing close brace between label and & will probably be picked up by
% TeX anyway.
%
\def\end@cell{%         % idea: deal with crosses in the same way
\end@label\relax        % in case of missing closing bracket
\send@cell@type         % save new horiz state globally across cell boundary
\save@cell@at@line
\global\cd@dim@g\cd@hshift% save object right shift across $
\penalty-9993           % split off profiling info as last line of paragraph
\end@maths\hfil\null    % $\hfil and protect following glue & penalties
%\penalty\profile@code  % profiling option
\kern-2\cd@dim@g        % balance to indicate right shift
\null                   % protect glue, kerns and penalties
}%
%
\def\diagram@cr{\cr}% optional argument? terminate horizontals?
% NB: vertical mode material in cells (\vadjust, \insert, \write) migrates
% when \cr is executed.
%
%************************ across several columns ***********************
%
% what happens if \across is used for all the the cells in some column?
% count cells
% \across must not follow verticals and crosses
%
% \mscount already defined by \multispan
%
% for some reason, \across3\cr doesn't work with the following definition,
% although \across2\cr, \across3 \cr and \across3& do work.
% \multispan appears to have a similar problem.
% \def\across{\span\omit\relax\afterassignment\spAns\mscount=}
% \def\spAns{\relax\loop\relax\ifnum\mscount>2 \spAn\repeat}
%
%\diagram
%      x&\rTo^{\xi}{}\across3&x'\\
%      \dTo^{u^x_y}{}&&&&\dTo_{u^{x'}_{y'}}\\
%      y&&&&y'\\
%      &\SE{\upsilon}{}&&\SW{}{\upsilon'}\\
%      &&y''\\
%\enddiagram
%       drives \rTo through x' and puts \xi near its right tip!
%
%\cd@first@use\obs@across{\string\across\space should be changed to multiple
%\and@name}%
\def\across#1{\span\omit\mscount=#1
\global\advance\cd@cell\mscount
\global\advance\cd@cell\m@ne
\loop@on@cells
\ifnum\mscount>2 \spAn\repeat
\ignorespaces}%
% use original plain TeX \sp@n? LaTeX version? count cells?
\def\spAn{\relax\span\omit\advance\mscount\m@ne}%
%
%\def\across#1{\message{%
%       ! diagrams Warning: \string\across\ must be changed to multiple &}%
%       \global\def\across#1{}}
%
% idea: back up one line (using \baselineskip\z@) or more (dunno)
%
%
%=======================================================================%
%                                                                       %
%       (8A) SIGNATURE                                                 %
%                                                                       %
%=======================================================================%
%
% Now test whether we have enough space to put our Morse Code signature on the
% stretching horizontal. Only do it in diagrams, where both fillers are "-",
% there is no middle, there is enough space and the rule breadth is positive.
% Do it on the 10th and then every 20th subsequent such occasion.
%
\def\test@signature{%
\ifincommdiag
   \ifx\@filla\@fillh
      \ifx\@fillb\@fillh
         \ifdim\dimen3>\z@\else
            \ifdim\dimen2>93\pixel@size % corrected 24.6.94 for P
            \ifdim\dimen2>18\p@ % added 24.6.94 for high resolution
               \ifdim\intended@breadth>\z@
                  \count@\signature@countdown
                  \advance\count@\m@ne
                  \ifnum\count@<\z@
                     \count@ 20%
                     \let\@signature\the@signature
                  \fi
                  \xdef\signature@countdown{\the\count@}%
\fi\fi\fi\fi\fi\fi\fi
%\showthe\skip2 %\expandafter\message{\signature@countdown}%
}%
% Dots, dashes and spaces are 2, 6 and 2 pixels wide, 1 pixel high.
% However at over 596 dpi resolution this unit is increased:
% \dimen2= 3pixels=0.17pt at 1270dpi, and 6pixels=.17pt at 2540dpi
\def\@morse#1{\vrule\horizhtdp width#1\dimen@\kern2\dimen@}%
%
% Paul Taylor =  .--. .- ..- .-..   - .- -.-- .-.. --- .-.
% Code for "P" corrected 24.6.94 (Ralph Loader)
\def\the@signature{\rlap{%
  \dimen@\pixel@size\at@least\dimen@{.182\p@}\pixel@round\dimen@
   \advance\rule@height\dimen@
   \@morse0\@morse0%                                       4
   \@morse2\@morse6\@morse6\@morse2\@morse0\@morse0%    P 28
   \@morse2\@morse6\@morse0\@morse0%                    A 16
   \@morse2\@morse2\@morse6\@morse0\@morse0%            U 20
   \@morse2\@morse6\@morse2\@morse2\@morse0\@morse0%    L 24
%   \@morse0\@morse0%                           space      4
%   \@morse6\@morse0\@morse0%                           T 12
%   \@morse2\@morse6\@morse0\@morse0%                   A 16
%   \@morse6\@morse2\@morse6\@morse6\@morse0\@morse0%   Y 32
%   \@morse2\@morse6\@morse2\@morse2\@morse0\@morse0%   L 24
%   \@morse6\@morse6\@morse6\@morse0\@morse0%           O 28
%   \@morse2\@morse6\@morse2\@morse0\@morse0%%          R 20
%   \@morse0\@morse0%                           space      4
   }}%
\def\signature@countdown{10}%
\def\@signature{}%
%
%=======================================================================%
%                                                                       %
%       (9) HORIZONTALS                                                 %
%                                                                       %
%=======================================================================%
%
% \dimen 0 = kern compensation for through-filler = \dimen5+\wd5
% \dimen 3 = half width of middle (exactly zero iff filler passes through)
% \skip  3 = glue compensation for through-filler - disappears at break
% \dimen 4 = fixed part of right glue
% \dimen 8 = height of rule filler (.5\rounded@breadth + \axisheight)
% \dimen 9 = depth  of rule filler (.5\rounded@breadth - \axisheight)
%
% what is depth of \vbox{\hrule\horizhtdp}?
%
\def\exec@horiz{%
%\show\if@cd@a@\show\if@cd@through@
\if@cd@a@\@cd@through@false\fi % if more text in cell, disable "through"
\calc@horiz\label@horiz\put@horiz}%
%
%\def\shortfall{\kern\MapShortFall}\def\unshortfall{\kern-\MapShortFall}%
%
% ***************** calculations for horizontal arrows ****************
%
% Calculate (unstretched) dimensions of components of horizontal arrow.
\def\calc@horiz{%
\set@offset@axis\crab@               % set \rule@height and \rule@depth
\set@map@parts
\ifdim\crab@=\z@\else\lift@map@parts\crab@\fi
%
% Half width of middle.
% If this is zero and \@filla=\@fillb, can go straight through
% [don't know what to do if it's negative].
\ifvoid3
        \setbox3=\null\ht3\rule@height \dp3\rule@depth 
\else   \at@least{\ht3}\rule@height\at@least{\dp3}\rule@depth
\fi
\dimen3=.5\wd3
\ifdim  \dimen3=\z@
        \if@cd@through@\else\dimen3-\one@sp\fi
\else   \@cd@through@false
\fi
%
% Find the greater length of labels;
% \dimen2 has been set to minimum arrow length.
\at@least{\dimen2}{\wd7}% extend to label widths
\at@least{\dimen2}{\wd6}%
%\at@least{\dimen2}{.5em}% 15.7.94 removed 15.4.95
%
\test@signature
%
\advance\dimen2-2\dimen3        % middle accounts for some of it
\dimen4.5\dimen2
\dimen2\dimen4                  % half each side
\advance\dimen2\snake@          % shift right for snake option 4.7.97
\advance\dimen4-\snake@         % doesn't work
\advance\dimen2-\wd1            % subtract tips
\advance\dimen4-\wd5
%
% make sure middle is as high and deep as the fillers
% and that leaders print at least one copy
\ifvoid2
\else   \at@least{\ht3}{\ht2}%
        \at@least{\dp3}{\dp2}%
        \at@least{\dimen2}{\wd2}%
\fi
\ifvoid4
\else   \at@least{\ht3}{\ht4}%
        \at@least{\dp3}{\dp4}%
        \at@least{\dimen4}{\wd4}%
\fi
% add stretchability to glue
\advance\skip2\dimen2
\advance\skip4\dimen4
%
% \dimen3=\z@ is a code to say that the filler can pass through.
% By manipulating glue, we make it stretch correctly whether or not the
% bomb explodes.
% (\total@donated, \left@donated and \right@donated are used like this
% during reformatting only)
%   <------------------\total@donated----------------->
%   short  tip  leaders-------------->---kern-->bomb
%   -fall               <-----negative glue-----
%                                          short
%                       middle glue-->tip  -fall
%   <----\left@donated----><--\right@donated--->
% If the bomb does not explode, the negative glue compensates for the kern
% and the right glue (remember that the middle has zero width). The arrow
% may be re-set to any required length as if none of these hacks were there.
%
% If the bomb does explode, the glue (being after the break) automatically
% disappears. The natural and stretched widths of the part to the right of
% the bomb are as expected (with the negative glue they would be zero).
% The width of the part to the left is that of the whole arrow.
% The kern ensuring that the leaders go up to the right tip; the right part is
% still stretched to the right width, so that the middle is correctly placed.
%
% Line-breaking cannot occur at these \xleaders and \kern's outside
% a diagram because they're part of a maths formula (TeXbook p96).
% Inside, the bomb is used (by \reformat@cell) to recognise and split
% the arrow, enabling the halves to be stretched by different amounts.
%
% Since these calculations cannot take account of anything which follows
% the arrow command in the cell, \switch@arg suppresses "through" if
% the arrow command is terminated by anything other than \end@cell.
%
\if@cd@through@
        % leaders can pass though - calculate compensating glue
        \advance\skip2\skip4    % add width+glue of right to left
        \dimen0\dimen5
        \advance\dimen0\wd5     % compensating kern
        \skip3-\skip4           % compensating glue
        \advance\skip3-\dimen0  %
        \let\@fillb\empty       % print nothing on the right
\else   \skip3\z@\relax         % otherwise no compenating glue or kern
        \dimen0\z@
\fi
%
}%
%
% ***************** Add sub & superscript (if any)  ****************
%
% Add to middle,
% retaining baseline and width (2\dimen3) of original middle.
% TeX does this as \vbox{[\kern]\hbox\kern\hbox\kern\hbox[\kern]}
%
\def\label@horiz{%
\offinterlineskip\lineskip.2\@em
\ifvoid6
\else   \setbox3=\vbox{%
                \hbox to2\dimen3{\hss\box6\hss}%
                \box3}%
\fi
\ifvoid7
\else   \setbox3=\vtop{%
                \box3
                \hbox to2\dimen3{\hss\box7\hss}}%
\fi}%
%
% ***************** Output unstretched horizontal ****************
%
\def\put@horiz{% make the horizontal cell - here as seen by paragraph builder
%\hfil\mathon(text)     % beginning of cell and text on left
\kern\dimen1            % space before
\box1                   % left tip
\@signature
\@filla\hskip\skip2     % filler: glue, leader or rule
\kern\dimen0            % kern compensation
\ifincommdiag
        \if@cd@centre@hlabel@\penalty1\fi % signal midhshaft 12.7.94
        \kern\dimen3
        \penalty\cd@penalty
        \hskip\skip3
        \null
        \kern-\dimen3
\else   \hskip\skip3
\fi
\box3                   % middle part of arrow
\@fillb\hskip\skip4     % filler
\box5                   % right tip
\kern\dimen5}%          % space on right
%(text)\penalty-9993
%  \mathoff\hfil\null\kern\z@\null
%\rightskip % text and \end@cell
%
% ***************** PostScript rotation of above ****************
%
%+++ INTERIM: ensure at least \objectheight or \objectwidth
\def\interim@shortfall{%
 \ifnum\numerator@>\denominator@
    \at@least{\dimen1}\objectheight
    \at@least{\dimen5}\objectheight
 \else
    \at@least{\dimen1}\objectwidth
    \at@least{\dimen5}\objectwidth
 \fi
}%
%
% Make the (diagonal) \kern needed on a line
% of length \dimen2 width \dimen7 and height \dimen6
% in order to intersect the edge of a rectangle
% of height \dimen8 and width \dimen9
\def\avoid@object{%
\begingroup
%\expandafter\message{line=(\the\dimen7,\the\dimen6)=\the\dimen2 \space
%  object=(\the\dimen9,\the\dimen8)}%
  \ifdim\dimen7=\z@
        \kern\dimen8 % vertical: use height
  \else\ifdim\dimen6=\z@
        \kern\dimen9 % horizontal: use width
  \else
        \dimen5\dimen6 % save height of line
        \dimen6\dimen9 % width of rectangle
        \set@fraction  % proportion of length
        \dimen4\dimen2 
        \multiply@{\dimen4}%
        \dimen6\dimen5 % restore height of line
        %
        \dimen7\dimen8 % height of rectangle
        \set@fraction  % proportion of length
        \divide@{\dimen2}%
        %
%\expandafter\message{kern=(\the\dimen2,\the\dimen4)}%
        \ifdim\dimen2<\dimen4
                \kern\dimen2 % hit left or right edge
        \else   \kern\dimen4 % hit top or bottom edge
  \fi\fi\fi
\endgroup   
}%
% Stretch a horizontal arrow in \hbox0
% as the diagonal of a rectangle of height \dimen6 and width \dimen7
% avoiding objects
%  above: 
%  below:
%
\def\stretch@PS@diagonal{%
\Pythagorean@sum % hypotenuse=\dimen2 x=\denominator@ y=\numerator@
\setbox\z@\hbox{%
    \lower\axisheight\hbox to\dimen2{%
    \if@reformatting@
        % profile of left object
        \ifPositiveGradient
             % lower left
             \dimen8\ht\object@profile 
             \dimen9\right@width
        \else% upper left
             \dimen8\dp3
             \dimen9\dimen1
        \fi
    \else
       \dimen8 \ifPositiveGradient\objectheight\else\z@\fi \dimen9\objectwidth
    \fi
    \advance\dimen8 \ifPositiveGradient-\fi\axisheight
    \avoid@object% 
    \unhbox\z@
    \if@reformatting@
        % profile of right object
        \ifPositiveGradient
             % upper right
             \dimen8\dp3
             \dimen9\dimen0
        \else% lower right
             \dimen8\ht\object@profile
             \dimen9\left@width
        \fi
    \else
       \dimen8 \ifPositiveGradient\z@\else\objectheight\fi \dimen9\objectwidth
    \fi
    \advance\dimen8 \ifPositiveGradient\else-\fi\axisheight
    \avoid@object%
}}}%
%
\def\exec@PS@diagonal{%
\dimen6 \y@coord\DiagramCellHeight
\dimen7 \x@coord\DiagramCellWidth
\stretch@PS@diagonal
%
\ifPositiveGradient
     \advance\dimen7-\x@offset\DiagramCellWidth
\else\dimen7 \x@offset\DiagramCellWidth
     \dimen6\z@
     %\multiply\numerator@\m@ne % \rotate@box@z does this now
\fi
\advance\dimen6-\y@offset\DiagramCellHeight
%
\rotate@box@z
%
\setbox0=\rlap{%
   \kern-\dimen7
   \lower\dimen6\box\z@}%
\ht0\z@\dp0\z@\raise\axisheight\box0
}%
%
\def\rotate@box@z{%
\setbox0\hbox{%
        \ht\z@\z@\dp\z@\z@\wd\z@\z@
        \if@pdf@  
           \expandafter\pdf@literal{q
              \denom@@\space\num@@\space\mnum@@\space\denom@@\space
              0 0 cm}%
        \else
           \global\@need@PS@lib@true
           \expanded@ps@special{%
           \the\denominator@\space
           \ifPositiveGradient\else-\fi\the\numerator@\space
           bturn}%
        \fi
      \box\z@
      \do@eturn}%
}%
%
% ***************** Complete reformatted horizontal ****************
%
% Initial processing of horizontal arrows at the point of declaration during
% reformatting is in the simple reformatting section.
%
% Output a completed horizontal arrow (see also \widen@pile).
% Result is appended to \box\cd@cell using \output@cell.
% Set up new horizontal donation to left.
%
% The pending horizontal arrow or space donation is saved in \box\pending@left
%  (and \box\pending@right).
%   space:              \box\pending@left  void (\box\pending@right  undefined)
%   \left@donated :     accumulating amount of (left) donation (cell--a)
%   single horizontal:  \hbox\pending@left  is left component,
%                       \hbox\pending@right  right component
%   pile:               \vbox\pending@left  is pile
%   \right@donated :            required right width of horizontals (a--b)
%   \declared@at@cell:  cell number where arrow was declared
%   \far@end@cell:      ditto for obstruction
%
\def\complete@horizontal{%
\advance\left@donated-\right@width 
\total@donated\left@donated\advance\total@donated\right@donated
%
\ifvoid\pending@left
        % no arrow, but check that there is some space between objects
        \ifdim\total@donated<.1em\ifnum\far@end@cell=\@m\else
                \more@dim h\total@donated<.1em:objects overprint:%
                        \cd@cell\far@end@cell
        \fi\fi
\else   \ifhbox\pending@left
                \widen@horiz
        \else   \widen@pile
        \fi
        \advance\total@donated\right@width 
        \output@cell{-\right@width}{\box\pending@left}{\total@donated}\z@
\fi
\left@donated -\left@width      % new space donation to left
                        % - \box\pending@left  is already void
\far@end@cell\cd@cell   % save our column number
\right@donated \z@
}%
%
% re-set single horizontal map, where
% \hbox\pending@left  is left part, width required to be \left@donated,
% cols \cd@cell to \declared@at@cell
% \hbox\pending@right  is right part, width \right@donated,
%  cols \declared@at@cell to \far@end@cell
% \total@donated=\left@donated+\right@donated
%
% before entry:
%   right: DO strip glue/penalty, restore \math@off and re-set naturally
%          DON'T restore \math@on
%   left:  DON'T strip glue/penalty, restore \math@off, or re-set
%          (already has \math@on anyway)
%
\def\widen@horiz{% reorganised 12.7.94
% reset parts to natural width, removing \rightskip & \penalty-9999
\setbox\pending@left=\hbox{\unhbox\pending@left\unskip\unpenalty}%
\setbox\pending@right=\hbox{\unhbox\pending@right\unskip\unpenalty}%
%\showbox\pending@left
%\showbox\pending@right
%
\setbox\pending@left=\hbox to\total@donated{%
        %
        % get the left part, saving its natural width
        \cd@dim@a\wd\pending@left
        \unhbox\pending@left
        %\showboxbreadth=999 \showlists
        %
        % 15.4.95: swapped \kern with midshaft \penalty
        % because penalties got lost at line breaks
        % save the \kern in \cd@dim@b and restore it
        %
        % test for through filler (\kern 0pt)
        \cd@dim@b\lastkern\unkern
        \ifdim  \cd@dim@b=\z@
                \@cd@through@true
                % calculate natural width of left part alone
                \advance\cd@dim@a-\wd\pending@right
        \else   \@cd@through@false
        \fi
        %
        % test for midhshaft (\penalty1)
        \ifnum\lastpenalty=\z@\else
                \@cd@centre@hlabel@true
                \unpenalty
        \fi
        \kern\cd@dim@b
        %
        %\expandafter\message{^^J%
        %       midshaft=\if@cd@centre@hlabel@ true\else false\fi,
        %       through=\if@cd@through@ true\else false\fi,^^J%
        %       natural  \the\cd@dim@a\space and  \the\wd\pending@right^^J%
        %       donated  \the\left@donated\space and  \the\right@donated}%
        %
        % if insufficient space on either side, set midshaft
        \ifdim\left@donated<\cd@dim@a\@cd@centre@hlabel@true\fi
        \ifdim\right@donated<\wd\pending@right\@cd@centre@hlabel@true\fi
        %
        % adjust right length for midshaft
        \if@cd@centre@hlabel@
                \right@donated\total@donated
                \advance\right@donated-\cd@dim@a
                \advance\right@donated\wd\pending@right
                %
                \ifdim\right@donated<2\wd\pending@right % not enough
                     \more@dim h\right@donated<2\wd\pending@right:%
                        arrow too short:\cd@cell\far@end@cell
                \fi
                %
                % give half of it to the right
                \divide\right@donated\tw@
                \left@donated\total@donated % don't need this
                \advance\left@donated-\right@donated
                %\expandafter\message{^^Jfinally
                %       \the\left@donated\space and \the\right@donated}%
        \fi
        %
        % if "through" expand left into right
        \if@cd@through@\kern-\right@donated\fi
        %
        \hbox to\right@donated{\unhbox\pending@right}%
        \math@off
}}%
%
%=======================================================================%
%                                                                       %
%       (10) PILES                                                      %
%                                                                       %
%=======================================================================%
%
%
% \hbox of cell containing \pile:
%       \glue(\hfil)
%       \mathon
%       \vbox
%               \hbox                   top line
%                   \glue\tabskip
%                   \hbox
%                   \glue\tabskip
%               \glue\baselineskip
%               \hbox                   second line
%               ...
%               \hbox                   bottom line
%       \penalty-9998
%       \rightskip                      added by paragraph builder
%       \mathoff                        from here is discarded
%       \glue(\hfil)
%
% uneven \pile separation, for example in
%      X & \pile{\rOnto^p\\\\\lInto~n\\\\\rTo_v} & Y
% because .5\PileSpacing is too little to accommodate the label ``n'',
% so \lineskip is used in the \vbox instead of \baselineskip.  
% Also, the empty line is
% \hss\kern\mathon\hfil\mathon\mathoff\kern\hss
%
%
%********************* phase 1 & 2 *****************************
%
% vertical position of pile?
% idea: optional argument to set width when outside diagram
% idea: get map labels and pass them to maps inside (eg adjunctions)
%
% It's not possible to catch a run-away argument to \pile.
% If we read it as an ordinary argument (#1), then if there is no matching
% closing brace anywhere before the end of the paragraph, the rest of the
% paragraph is lost and we get (a TeX error and) \par as the argument; this
% will expand to \enddiagram, which will at least close the \pile cleanly.
% On the other hand, if we do not read it as an argument, but leave the
% closing brace to TeX to parse later, it must end the \halign without giving
% us the opportunity to insert \crcr, and we can't regain control, because
% it is not possible to do \halign\bgroup\aftergroup.
%
% At various places we do \end@pile just in case the closing bracket has been
% put in too late. Since \pile{...\dTo...}\next translates into
% \begin@pile...\dTo...\end@pile\next we never see the original closing brace
% again, but \end@pile stands in for it. Since \dTo wants to force \end@pile,
% it inserts one and gives its own error message; the original becomes
% innocuous because (being no longer in the scope begun by \begin@pile) it is
% \empty. We choose this rather than \relax so that \\\enddiagram, which
% translates to \cr\end@pile\crcr\egroup, does not get an extra \cr.
% Perhaps these dummy \end@label and \end@pile commands should give error
% messages? Maybe, but it's quite likely that TeX or we have already given one.
% \let\end@label\empty
%
\new@if\ifinpile\inpiletrue\inpilefalse\inpilefalse
%
\def\pile{\protect\setup@pile\protect\@pile}%
\def\@pile#1{\begin@pile#1\end@pile}%
\def\setup@pile{%
\check@horiz{pile}%     % ensure correct horizontal state
\setbox0=\vtop\bgroup   % we want to know the height of the top level
\aftergroup\finish@pile % do this after the corresponding \egroup
%\incommdiagtrue                % signal we're NOT inside \commdiag
\inpiletrue
\let\group@after@map\empty
\let\pile\inner@pile    %
\let\end@pile\@end@pile %
\let\enddiagram@endpile\@enddiagram@endpile
\pile@state             % horiz state (\cd@donat) within \pile is either 6 or 7
\baselineskip.5\PileSpacing%
\lineskip.1\@em\relax   %
\lineskiplimit\lineskip %
\mathsurround\z@        % \m@th
\tabskip\z@             % \ialign
\let\\\pile@empty@row
}%
\def\begin@pile{%
\glet\last@map@type\empty% initialise horiz error message (27.12.93)
\halign\bgroup          % matrix of 1-column rows [\ifincommdiag\else to..\fi]
   \hfil
   \begin@maths
      \let\group@after@map\bad@group@after@map
      \let\\\pile@cr
      ##\end@label
   \end@maths
   \hfil
   \@and
   \and@in@pile##\cr% the template
}%
% idea: use second column to catch misplaced &
%
\new@help\help@and@in@pile{pile only allows one column.}%
\new@help\help@pile@enddiagram{you left it out!}%ascii
\def\and@in@pile{\end@pile\@and\relax
  \cd@error{missing \egroup@name\space inserted after \string\pile}%
  \help@and@in@pile}%
%
\def\@end@pile{\end@label\crcr\egroup\egroup}%
\def\enddiagram@endpile{\end@label}%
\def\@enddiagram@endpile{\end@label\relax\end@pile
   \cd@error{missing \egroup@name\space inserted between \string\pile\space
   and \end@diagram@name}\help@pile@enddiagram}%
%
% no point in warning about misplaced or anticipated \end@pile, because
% we've already got to that line and should have given some error message,
% since the argument to \pile is em-braced.
\def\end@pile{\end@label}%
%
% have the pile in \vbox0; do \vcenter without regard to outer labels
\def\finish@pile{%
\vbox  {\dimen1\dp0             % total height apart from this
        \unvbox0                % re-set \pile
        \setbox0=\lastbox       % get bottom layer
        \advance\dimen1\dp0     %
        \nointerlineskip
        \box0                   % restore bottom layer
        \nointerlineskip
        \setbox0=\null\dp0.5\dimen1\ht0-\dp0
        \box0}%                 % sink by half top-bottom axis distance
\ifincommdiag
\then   \penalty-9998           % flag this was a \pile
\fi
\xdef\last@map@type{pile}%
}%
%
% \\ inside \pile after some text
\def\pile@cr{\cr}%
%
% empty row in \pile (\\ at beginning of cell)
% fiddle the depth of the previous row
% to make \baselineskip or \lineskip do the work
\def\pile@empty@row{\noalign{%
   % this is really \advance\prevdepth-\baselineskip
   \skip@\prevdepth
   \advance\skip@-\baselineskip
   \prevdepth\skip@}}%
%
% Nested pile generates its own matrix in the same way, contributing the
% result to the main pile vertical list using \noalign (yes, this works).
%\def\inner@pile#1{\noalign\bgroup\begin@pile#1\end@pile}%
\def\inner@pile#1{#1}% I'm sure this will do!
%
% % \def\Atop#1#2{{%                     upper and lower parts
%   \setbox0\hbox{\strut\begin@maths#1\end@maths}\dp0\z@
%   \setbox1\hbox{\strut\begin@maths#2\end@maths}\ht1\z@
%   \vtop{\vbox{\kern-0.7ex\box0\hrule width\z@ height0.7ex depth0.93ex}
%     \nointerlineskip\box1}
% }}
% 
% The idea was to take apart (the definition of) the two arrows and
% re-assemble them. At the TeX end this wouldn't be very difficult to
% do, but it would have produced awful DVI (like visiting the houses
% in a street in numerical order, rather than going up the odds and down
% the evens). Experience has shown that all DVI drivers (it seems) are
% so careless with rounding DVI->pixel conversions that the result would
% be unspeakably ugly.
%
% \def\ExtractMapPartsA#1#2#3#4#5{%
% \def\mapA{#1}\def\tailA{#2}\def\headA{#3}\def\fillerA{#4}\def\middleA{#5}}
% \def\ExtractMapPartsB#1#2#3#4#5{%
% \def\mapB{#1}\def\tailB{#2}\def\headB{#3}\def\fillerB{#4}\def\middleB{#5}}
% 
% % eg "\ParallelMap\rTo\bot\lTo f g" or
% "\ParallelMap\uTo\adjoint\dTo f g" f-|g
% % \def\ParallelMap#1#2#3{%
% \expandafter\ExtractMapPartsA #1%     eg \rTo
% \setbox4=\hbox{\begin@maths#2\end@maths}%     middle bit, eg \bot or \adjoint
% \setbox5=\hbox{}\wd5=\wd4\ht5=\ht4\dp5=\dp4
% \expandafter\ExtractMapPartsB #3%     eg \lFrom
% \def\ke{\kern0.1\@em\copy5\kern0.1\@em}%
% \ifx\mapA\HorizontalMap\let\tbox\vcenter\else\let\tbox\hbox\fi
% \mapA{\tbox{\tailA\ke\tailB}}{\tbox{\headA\ke\headB}}%
%{\tbox{\fillerA\ke\fillerB}}
%{\tbox{\middleA\kern0.1\@em\box4\kern0.1\@em\middleB}}}
%
%
%********************* phase 4 *****************************
%
% \vbox\pending@left  contains the pile, as created by \halign above.
% \left@donated  is the required left width and \right@donated  the right width
% \total@donated is sum of these
% Result goes back in \box\pending@left . (\vcenter, \hbox or what?)
% \hbox3, \hbox4, \dimen0, \cd@dim@a, \skip0 scratch - local to \vbox
%
% When splitting the \vbox, we first put it on the stack (current vertical
% list) adding the following:
%       \penalty3 (stopper)
%       \hbox   (top map)
%       \baselineskip
%       ...
%       \baselineskip
%       \hbox (bottom map)
%
\def\widen@pile{%
\setbox\pending@left=\vbox{%
\unvbox\pending@left            % turn \vbox into a vertical list
\setbox1=\lastbox       % sinking box
\setbox0=\box\voidb@x   % accumulate new pile
%
\loop@on@maps % in the list
        \setbox\pending@left=\lastbox
\ifhbox\pending@left
        \do@pile@row
\repeat
\unvbox0                % put it back in the vertical list
\global\cd@dim@g\horiz@extra    % save extra cell width across closing braces
}%                      % complete \vbox
\horiz@extra\cd@dim@g}% % restore extra cell width
%
\def\do@pile@row{%
\if@cd@centre@hlabel@
        % unwrap box from \hbox{\tabskip\hbox{<-+->}\tabskip}
        \setbox\pending@left=\hbox{%
                \unhbox\pending@left
                \unskip
                \setbox\pending@left=\lastbox\unskip\unhbox\pending@left}%
        \ifdim\total@donated<\wd\pending@left 
                \more@dim h\total@donated<\wd\pending@left:%
                        arrow in pile too short:%
                        \cd@cell\far@end@cell
        \else   \setbox\pending@left =\hbox to\total@donated{\unhbox\pending@left}%
        \fi
\else   
        \split@pile@row
\fi
\setbox0=\vbox{% add the stretched row to the top of the completed pile
        \box\pending@left 
        \nointerlineskip
        \ifvoid0
        \then   \box1           % bottom layer - restore sinking box
        \else   \vskip\skip0    % restore interlayer glue
                \unvbox0
        \fi}%
\skip0=\lastskip\unskip % save \baselineskip above this row
}%
%
%  \box\pending@left =\hbox{
%       \tabskip
%       \hbox
%           (left part)
%           \penalty-9999
%           (right part)
%       \tabskip}
%
% Split each line of the pile, using the paragraph builder again, so
% the following is added to the stack (current vertical list):
%       FOR A MAP               FOR AN "OBJECT"
%       \parskip                \parskip
%       \baselineskip           \baselineskip
%       \hbox   (left part)     \hbox   (the object)
%       \baselineskip
%       \hbox   (right part)
%
%       \vbox0: completed pile
%       \box1   box to sink depth to do \vcenter without regard to labels
%       \hbox\pending@right : right part or object
%       \hbox\pending@left : row to be split, then left part, then result
%       \left@donated : the required left width
%       \right@donated : the required right width
%       \skip0: \baselineskip above it
%
\def\split@pile@row{%
\penalty7                       % mark the \parskip
\noindent
\unhbox\pending@left            % \tabskip\hbox\tabskip
\unskip                         % remove \tabskip
\setbox\pending@left=\lastbox   % get the \hbox (cell)
\unskip                         % remove \tabskip
\unhbox\pending@left            % split the box
\endgraf                        % using the paragraph builder
%
\setbox\pending@right=\lastbox\unskip% object or right part, and \baselineskip
\setbox\pending@right=\hbox{%
        \math@on
        \unhbox\pending@right
        \unskip\unskip\unpenalty % \parfillskip\rightskip\penalty10000
        }%
%
\ifcase\prevgraf\cd@shouldnt P% row of \pile contains wrong number of parts
%
% ONE line: a centered "object" between the maps
\or     \ifdim\total@donated<\wd\pending@right
                \more@dim h\total@donated<\wd\pending@left:%
                        object in pile too wide:%
                        \cd@cell\far@end@cell
                \setbox\pending@left =\hbox to\total@donated{\hss
                        \unhbox\pending@right
                        \hss}%
        \else
                \setbox\pending@left =\hbox to\total@donated{\hss
                        \kern\left@donated
                        \unhbox\pending@right
                        \kern\right@donated 
                        \hss}%
        \fi
%
% TWO lines: a map
\or     \setbox\pending@left=\lastbox\unskip  
                % get left part & discard \baselineskip
        \widen@horiz
                % re-set \hbox\pending@left using
                % \box\pending@right \right@donated
                % \box\pending@left  \left@donated  \total@donated
%
\else\cd@shouldnt Q\fi % row of \pile contains wrong number of parts
%
\unskip\unpenalty}% remove \parskip and marker (7)
%
%
%=======================================================================%
%                                                                       %
%       (11) VERTICALS                                                  %
%                                                                       %
%=======================================================================%
%
%
% idea: amount to fill? don't think it's worth the trouble
% at least ht & dp of other boxes
% idea: rotate text of labels
\def\exec@vert{%
\set@map@parts
\ifvoid3
        \setbox3=\null\ht3\axisheight\dp3-\ht3
        \dimen3.5\intended@breadth
\else   \dimen4\dp3
        \dimen3.5\wd3
        \setbox3=\make@vert@part{\box3}% re-center middle
        \dp3\dimen4                     % but preserve its depth
        \ifdim\ht3=-\dp3 \else\@cd@through@false\fi
\fi
%
\dimen0\dimen3                  % half original width of middle
\advance\dimen0-.5\intended@breadth
%
% attached labels to middle as overlaps
% preserving the size of \box3
% save widths for later phantom
\setbox0\null\ht0\ht3\dp0\dp3\wd0\wd3 % save size because we're reboxing
\ifvoid6\else
    \setbox6\hbox{\unhbox6\kern\dimen0\kern 2pt}\dimen0\wd6
\fi
\ifvoid7\else
    \setbox7\hbox{\kern 2pt\kern\dimen3\unhbox7}\dimen3\wd7
\fi
\setbox3\hbox{%
    \ifvoid6\else\kern-\dimen0\unhbox6\fi
    \unhbox3
    \ifvoid7\else\unhbox7\kern-\dimen3\fi
}%
\ht3\ht0\dp3\dp0\wd3\wd0
\if@cd@through@
        \dimen4=\ht\object@profile
        \advance\dimen4\dp5
        \advance\dimen4\dimen1  % lower tip plus shortfall
        \let\@fillb\empty       % lower filler is space
\else   \dimen4\ht3             % phantom middle
\fi
\setbox0\null
\ht0\dimen4
\offinterlineskip
%
\setbox8=\vbox spread2ex{%      % upper part with nominal extension
        \kern\dimen5            % shortfall above
        \box1                   % upper tip
        \@filla\vfill           % filler
        \if@cd@through@\else
            \kern\snake@        % user's adjustment
        \fi
        \box0}%                 % phantom middle provides baseline (depth zero)
        \ht8=\z@                % zero height so as not to force lines apart
\setbox9=\vtop spread2ex{%      % lower part with nominal extension
        \kern-\ht3              % top of box at baseline
        \kern-\snake@           % user's adjustment
        \box3                   % middle
        \@fillb\vfill           % filler [amount to fill?]
        \box5                   % lower tip
        \kern\dimen1}%          % shortfall below (\vbox would put \dp=0)
        \dp9=\z@                % zero depth so as not to force lines apart
%
\hskip\dimen0plus.0001fil       % phantom left label plus a tiny amount of glue
\box9                           % lower part
\kern-\intended@breadth         % backspace to overprint the two parts
\box8                           % upper part
\if@cd@centre@vlabel@\penalty2 \fi % code to say centre label vertically
\if@cd@through@\penalty1 \fi    % code to say filler goes through
\kern\PileSpacing               % code the locally required spacing
\kern-\PileSpacing              % and undo its effect
\kern-.5\intended@breadth       % centre penalty horizontally in shaft
\penalty\cd@penalty
\null
\kern\dimen3}%                  % phantom label (was \box7)
%
%
%********************* phase 3 *****************************
%
% \hbox\right@part  is rightmost, \hbox\left@part next,
% rest as lines of paragraph on current vertical list
% transfer them to \hbox\cd@donat
% calculate widths
%
% The format of each arrow \hbox is
%       \hfil
%       \mathon
%       \hbox(left label)
%       \kern
%       \vtop (lower part)
%       \kern (space adjustment)
%       \vbox (upper part)
%       \penalty2   \if@cd@centre@vlabel@ (midvshaft) 
%       \penalty1   \if@cd@through@ (filler goes through)
%       \kern\PileSpacing
%       \kern-\PileSpacing
%       \kern (space adjustment)
%       \penalty-9995
%       \rightskip
%
\def\reformat@vert{%
\ifhbox\cd@donat
        \cd@refmt@error{clashing verticals}%
        \ht\object@profile.5\dp\cd@donat
        \dp\object@profile-\ht5
        \complete@vertical
        \ht\object@profile\z@\dp\object@profile\z@
\fi
% save what will be our height
\dimen1\dp\cd@donat
%
% initialise accumulation of parts
\cd@num@d\prevgraf
\unvbox\cd@donat
\cd@num@c\lastpenalty\unpenalty % row number of top
\setbox\cd@donat=\null
%
% re-set rightmost part to natural width
%\setbox\right@part\hbox{\math@on\unhbox\right@part\math@off}% should be enough
\setbox\right@part =\hbox{%
        \math@on
        \unhbox\right@part 
        \unskip                 % \rightskip
        %\count@\lastpenalty    % code -9993
        \unpenalty
        %\setbox\junk\lastbox   % \hbox(right label)
        %\unkern                % 
        %\setbox\junk\lastbox   % \null
        \dimen0\lastkern\unkern % adjustment
        \unkern                 % un\PileSpacing
%\global\cd@dim@g\lastkern      % \PileSpacing
        \unkern
        \kern\dimen0            % replace adjustment
        \math@off
        }%
%
%
% and next-to-rightmost part, from which \rightskip and \penalty-9995
% have already been removed.
\setbox\left@part=\hbox{%
        \unhbox\left@part
        \dimen0\lastkern\unkern % adjustment
        \unkern                 % un\PileSpacing
\global \cd@dim@g\lastkern      % \PileSpacing
        \unkern
        \kern\dimen0            % replace adjustment
        }%
%
% copy all but leftmost & rightmost parts to donations box
\loop@on@maps
\ifnum  \cd@num@d>4
        \separate@verticals
\repeat
%
% remove \baselineskip and \parskip from vertical list
\unskip\unskip
%
% start by centering arrow system without regard to outermost parts
% (\left@width and \right@width initialised by \get@profile@info)
\advance\left@width.5\wd\cd@donat
\advance\left@width\wd\left@part
\advance\right@width.5\wd\cd@donat
\advance\right@width\wd\right@part 
%
% if this is the leftmost column of the diagram,
% remember how wide the system of verticals is (15.6.97)
\ifnum\cd@cell=\cd@left
    \cd@dim@a .5\wd\cd@donat
    \edef\vert@wd@in@leftmost{\the\cd@dim@a}%
\fi
%
% add outermost parts to donation, and codes for row numbers
\setbox\cd@donat=\hbox{%
        \kern-\left@width       % smash left width
        \box\left@part          % leftmost
        \unhbox\cd@donat        % middle
        \box\right@part         % rightmost
        \kern-\right@width      % smash right width
        \penalty\cd@num@c       % row number of top
        \penalty\cd@row}%       % row number of middle
%
% restore our height and depth, and the intercolumn width
\ht\cd@donat\dimen1
\dp\cd@donat\z@
\wd\cd@donat\column@placing
%
% use \left@width and \right@width  to obstruct horizontal
\complete@horizontal
}%
%
\def\separate@verticals{%
\ifdim\wd\left@part<\cd@dim@g
   \setbox\left@part=\hbox to\cd@dim@g{\math@on\unhbox\left@part}%
        % stretch to \PileSpacing apart
\fi
\advance\cd@num@d\m@ne
\setbox\cd@donat=\hbox{\box\left@part\unhbox\cd@donat}%
        % add back to donations box
\unskip                                 % remove \baselineskip
\setbox\left@part=\lastbox
\setbox\left@part=\hbox{%
        \unhbox\left@part
        \unskip                 % \rightskip
        %\count@\lastpenalty    % code -9995
        \unpenalty              %
        \dimen0\lastkern\unkern % adjustment
        \unkern                 % un\PileSpacing
\global \cd@dim@g\lastkern      % \PileSpacing
        \unkern
        \kern\dimen0            % replace adjustment
        }%
}%
%
%*************************** phase 4 ****************************
%
% Format of \box\cd@donat
%       either: space:  \vbox{  \penalty(row no. of upper obstruction)}
%       or:     arrows: \hbox{  \hbox(leftmost arrow)   -- see below
%                               ...
%                               \hbox(rightmost arrow)
%                               \hbox(right label)
%                               \penalty(row no. of upper obstruction)
%                               \penalty(row no. where declared)
%                               }
%
\def\complete@vertical{%
\dimen1\dp\cd@donat
\ifhbox\cd@donat
        \@complete@vertical
\else   \@complete@vspace
\fi
%
% make new space donation downwards
\setbox\cd@donat=\vbox{\penalty\cd@row}%save our row number
\dp\cd@donat-\dp\object@profile                         % amount of space
\wd\cd@donat\column@placing                       % intercolumn width to left
}%
%
\def\@complete@vspace{%
\unvbox\cd@donat
\cd@num@c\lastpenalty\unpenalty
\ifdim\dimen1<\ht\object@profile 
        \more@dim v\dimen1<\ht\object@profile:rows overprint:\cd@row\cd@num@c
\fi}%
%
\def\@complete@vertical{%
\dimen0=\ht\cd@donat    % height
%\dimen1=\dp\cd@donat   % depth
% vertical centering (questionable) - idea: make use of natural \ht & \dp
%\if@cd@centre@vlabel@
%        \advance\dimen0\dimen1
%        \dimen1.5\dimen0
%        \dimen0\dimen1
%\else  \cd@dim@b\z@
%\fi
%
\setbox\cd@donat=\hbox\bgroup
        \advance\dimen1-\ht\object@profile  %### forgot this in centre@vlabel!
        \unhbox\cd@donat
        \cd@num@d\lastpenalty\unpenalty % row number of middle
        \cd@num@c\lastpenalty\unpenalty % and of top
\global \cd@dim@h-\lastkern\unkern      % right width (local to \hbox)
        \setbox0=\lastbox               % right label (don't touch)
%
        \loop@on@maps
                \setbox\cd@donat=\hbox{\box0\unhbox\cd@donat}%
                \setbox0=\lastbox
        \ifhbox0
                \stretch@vert
        \repeat
\global \cd@dim@k-\lastkern\unkern      % left width
\global \cd@dim@g\vert@extra            % save extra cell height across \egroup
        \unhbox\cd@donat
\egroup
\vert@extra \cd@dim@g                   % restore extra cell height
\output@cell{\cd@dim@k}{\box\cd@donat}{\cd@dim@h}{\dimen1}}%
%
% local to \hbox:
% \hbox0:  upper part
% \dimen0: required height of upper part, depth \dimen2
% \hbox1:  lower part
% \dimen1: required depth of lower part, height \dimen2
% \dimen2: adjustment for midvshaft
% \dimen7: right adjustment
% \dimen6: left adjustment
%
\def\stretch@vert{%
\setbox0=\hbox to\wd0\bgroup
\unhbox0
\unskip\unpenalty       % \rightskip, \penalty-9995
\dimen7\lastkern\unkern % right adjustment
\ifnum  \lastpenalty=1
        \unpenalty
        \@cd@through@true
\else   \@cd@through@false
\fi
\ifnum  \lastpenalty=2
        \unpenalty
        \dimen2.5\dimen0\advance\dimen2-.5\dimen1\advance\dimen2-\axisheight
\else   \dimen2\z@
\fi
\setbox0=\lastbox       % upper part
\dimen6\lastkern\unkern % left adjustment
\setbox1=\lastbox       % lower part
%
% stretch upper part (\dp\z@ since ends in \hbox\dp\z@ or \kern)
\setbox0=\vbox{%
        \unvbox0
        \if@cd@through@
             \kern-\dimen1   % for filler to go through
        \else\ifdim\dimen2=\z@\else
             \kern\dimen2    % for midvshaft
        \fi\fi}%
\ifdim\dimen0<\ht0
        \more@dim v\dimen0<\ht0:upper part of vertical too short:%
                {\if@cd@through@\cd@row\else\cd@num@c\fi}\cd@num@d
\else   \setbox0=\vbox to\dimen0{\unvbox0}%
\fi
%
% stretch lower part
% NB (see TeXbook p81)
% \vbox would make \dp=0 (because ends \kern\MapShortFall) so \ht=total;
% but \vtop makes \ht=0 (because begins \box), so \dp=total.
\setbox1=\vtop{\unvbox1}%
\ifdim\dimen1<\dp1
   \more@dim v\dimen1<\dp1:lower part of vertical too short:\cd@row\cd@num@c
\else   \setbox1=\vtop to\dimen1{%
        \ifdim\dimen2=\z@\else
             \kern-\dimen2
        \fi
        \unvbox1
        }%
\fi
%
\box1                   % put lower part back
\kern\dimen6            % left adjustment
\box0                   % upper part
\kern\dimen7            % right adjustment
\math@off
\global\cd@dim@g\vert@extra     % save extra cell height neede across \egroup
\egroup                 % end of \hbox
\vert@extra\cd@dim@g\relax}%    %
%
%
%=======================================================================%
%                                                                       %
%       (12) TRANSFER TO BOX ARRAYS                                     %
%                                                                       %
%=======================================================================%
%
% TeX has 256 boxes, some (not, in fact, very many) of which are allocated
% (using \newbox and \newinsert)
% for specific purposes by plain.tex, latex.tex and other packages, including
% this one. Those from 10 to \boxc@unt have been allocated by \newbox and
% those from \insc@unt to 255 by \newinsert, but most of them are unused.
% We use those in between, allocated locally, as a scratch array for our
% reformatting. (\box0..\box9 are also used for scratch). By convention,
% the pointer to the loweset-numbered box in an allocation is to that box,
% whilst that to the highest is to the one above.
%
\countdef\boxc@unt=14 % [cf \insc@unt] number of last \box allocation
%
% \box0..9                                      available as scratch
% 10..\boxc@unt                                 allocated to various packages
% \cd@bottom=\boxc@unt+1..\cd@top-1             used for rows of matrix
% \cd@left@donat=\cd@top..\cd@right@donat       used for vertical donations
% \cd@right@donat+1..\cd@left-1                 unused
% \cd@left..\cd@right-1                         used for cells of current row
% \insc@unt=\cd@right..254                      allocated for footnotes etc
% 255                                           is the current page
%
\newcount\cd@bottom     % \box\cd@bottom is the bottom row
\newcount\cd@top        % \box{\cd@top-1} is top row
\newcount\cd@row        % \box\cd@row is current row
\let\cd@right\insc@unt  % \box{\cd@right-1} is rightmost cell of current row
\newcount\cd@cell       % \bot\cd@cell is current ditto
\newcount\cd@left       % \bot\cd@left is leftmost ditto
\let\cd@left@donat\cd@top% \box\cd@left@donat is leftmost vertical donation
%\cd@donat already defd % \box\cd@donat is current ditto
\newcount\cd@right@donat% \box{\cd@right@donat-1} is rightmost ditto
%
% After each row has been reformatted and output, its height \ht\cd@row
% is set to the current value of \completed@depth, ie the distance from
% the top of the diagram. (10.7.94)
%
% This is called just after we've finished building the vertical list
% which comprises the matrix. The rows of the matrix may be extracted
% one by one in reverse order (with glue between them), and then each
% row is similarly decomposed, also in reverse order.
% At the beginning this vertical list looks like this:
%          \penalty-123  % marker placed by \diagram
%          \hbox        % top row
%               \glue\tabskip
%               \hbox   % leftmost cell (see template and maps for format)
%               \glue\tabskip
%               \hbox   % second cell
%               ...
%               \glue\tabskip   
%               <<<<<<<<<<<<<<<<<<<<< \reformat@row is called here
%          \penalty 1   % code that this is a row, mot a missive
%          \glue\baselineskip
%          \hbox        % second row
%          \penalty 1   % code that this is a row, mot a missive
%          \glue\baselineskip
%          ...
%          \hbox        % bottom row
%          <<<<<<<<<<<<<<<<<<<<<<<<<< \reformat@matrix is called here
%
% reformatting goes from right to left in each row,
% top row to bottom row.
%
% IDEAS:
%  -    collect overprints and diagonals, adding them to the left of the
%       appropriate row boxes (making new ones void first if necessary)
%  -    similar use column widths to set vertical donations (as \wd\vbox)
%       void boxes for unspecied ones and warning for repeated specification
%
% MISSIVES:
% \vadjust{} called within a cell puts its material into the vertical list
% below the row (so it appears to \lastbox, \lastpenalty, etc before the row).
% Instead of the \hbox\penalty1 of the row, this is encoded as follows:
%           \hbox{missive material}
%           \penalty (column number; 1=leftmost)
%           \penalty (row number; 1=topmost)
%           \penalty (missive code number, >1)
% The missive material may contain overprints, diagonals, etc.  In the case of
% diagonals, the row and column numbers are those of the upper (and, for
% horizontals, leftmost) cell involved; the other end of the arrow is
% encoded as penalties contained in the missive material.
%
% \missive@to@row is called when such a \penalty is found whilst the vertical
% list produced by \halign is being taken apart. It appends the missive to the
% left of the \hbox containing the row to which it is addressed in the format
%           \hbox{missive material}
%           \penalty (column number)
%           \penalty (missive code)
% \missive@to@cell is called whilst the row \hbox is being taken apart.
% It appends the missive to the left of the cell \hbox in the format
%           \hbox{missive material}
%           \penalty (missive code)
%
%********************* transfer rows of matrix to array **********************
%
\new@if\if@reformatting@\@reformatting@true\@reformatting@false\@reformatting@false
%
\def\firstpass@showboxdepth{-1}%
%
\def\after@diagram{%
\ifnum\firstpass@showboxdepth<\z@\else % 15.7.94
    \begingroup
       \scrollmode % 17.7.94 %%% but this is now set globally 16/4/95
       \showboxdepth\firstpass@showboxdepth
       \showboxbreadth\maxdimen
       \showlists
    \endgroup
\fi
\@reformatting@true
\make@end@at@line
\cd@bottom=\boxc@unt            % allocate array from \boxc@unt upwards
\advance\cd@bottom1             % for bottom and other rows of matrix
\cd@top=\cd@bottom              %
% during the first pass, we counted the rows (globally) in \cd@row
% if only one row, center the labels on the horizontal maps 12.7.94
\ifnum\cd@row=1 \@cd@centre@hlabel@true\fi
\advance\cd@top\cd@row          % top
\dimen1\z@                      % height of previous row
\skip0\z@                       % interline space below this row
\count@=\insc@unt
\advance\count@\boxc@unt
\divide\count@2                 % greatest register which may be used for rows
%\showboxdepth999\showboxbreadth999%\showlists
%
\ifnum\cd@top>\count@
    \cd@refmt@error
     {The diagram has too many rows! It can't be reformatted.}%ascii
\else
    \matrix@to@buffer  % rows in boxes, collect diagonals, etc (easy to abort)
    \reformat@matrix   % re-align (skip this for draft mode?)
\fi
\output@diagram
}%
%
\def\matrix@to@buffer{%
\cd@row\cd@bottom
\loop@on@rows                   % clear rows
\ifnum\cd@row<\cd@top % 12.7.94
        \setbox\cd@row\box\voidb@x
        \advance\cd@row 1\relax
\repeat
%
\cd@row\cd@bottom
\skip\z@\z@ % inter-row glue
\loop@on@rows
        \cd@penalty\lastpenalty\unpenalty % get the code
\ifnum\cd@penalty>\z@           % is anything there?
        \handle@matrix@row
\repeat
%
\ifnum  \cd@penalty=-123        % We inserted this check at the beginning
\then   \unpenalty              %  of \diagram; now remove it.
\else   \cd@shouldnt D% failed to unpack all of the rows of the matrix
\fi
%
% set row heights from grid
\ifx\v@grid\relax\else
   \cd@row\cd@top\advance\cd@row\m@ne
   %\tracingcommands1 \tracingmacros1
   \expandafter\set@v@grid\v@grid
   %\tracingcommands0 \tracingmacros0
\fi
%
%\cd@left@donat=\cd@top%(\let)  % initialise donations buffer
\cd@right@donat\cd@left@donat   %
\column@placing\z@
\mk@new@donat
%
% set column widths from grid
\ifx\h@grid\relax\else
   %\tracingcommands1 \tracingmacros1
   \expandafter\set@h@grid\h@grid
   %\tracingcommands0 \tracingmacros0
\fi
%
\count@\cd@top
\advance\count@\m@ne
\cd@top@height\ht\count@
%\expandafter\message{left=\the\cd@left, right=\the\cd@right,
%   left donat=\the\cd@left@donat, right donat=\the\cd@right@donat}%
}%
%
\def\handle@matrix@row{%
\ifcase\cd@penalty
\or     \matrix@row@to@buffer
\else   \cd@num@a-\lastpenalty\unpenalty % negative of row number
        \cd@num@b\lastpenalty\unpenalty % column number
        \setbox0=\lastbox
        \missive@to@row
\fi
\get@interrow@glue % 13.7.94
}%
\def\get@interrow@glue{\skip1\lastskip\unskip\advance\skip0\skip1
\ifdim\skip1=\z@\else\expandafter\get@interrow@glue\fi}%
%
\def\matrix@row@to@buffer{%
\setbox0=\lastbox       % get a row
\row@depth\dp0
\advance\row@depth\skip\z@\skip\z@\z@
\advance\inter@row\row@depth    % between our baseline and next below
\if@cd@tight@\ifnum\cd@row>\cd@bottom
        \inter@row\DiagramCellHeight    % if tight, reset to prescribed amount
        \row@depth\inter@row
        \advance\row@depth-\row@height
\fi\fi
\row@height\ht0         % save height for next time
\inter@row\row@height
% save the row on the left hand end of the row box register
\setbox\cd@row\hbox{\unhbox\cd@row\unhbox0}%
\dp\cd@row\row@depth                  % include space in depth of row
\ht\cd@row\row@height
\advance\cd@row 1       % allocate a box register for it
}%
%
\def\missive@to@row{%
% \cd@num@a = -1 for top row, -2 for next, etc
%\expandafter\message{missive type \the\cd@penalty\space to
%   (\the\cd@num@a,\the\cd@num@b)}%
\ifnum\cd@num@a<\z@
   \advance\cd@num@a\cd@top % row number as a box number
   \ifnum\cd@num@a<\cd@bottom
        \missive@outside
   \else
        \cd@dim@a\dp\cd@num@a\cd@dim@b\ht\cd@num@a
        \setbox\cd@num@a\hbox{%
            \box\z@
            \penalty\cd@num@b
            \penalty\cd@penalty
            \unhbox\cd@num@a}%
        \dp\cd@num@a\cd@dim@a\ht\cd@num@a\cd@dim@b
   \fi
\else
    \missive@outside
\fi
}%
\def\missive@outside
{\cd@refmt@error{diagonal goes outside diagram (lost)}}%ascii
%
\def\resend@missive{%
%\expandafter\message{missive type \the\cd@penalty\space to
%   (\the\cd@num@a,\the\cd@num@b)}%
\advance\cd@num@a\cd@top % row number as a box number
\ifnum\cd@num@a<\cd@bottom
    \missive@outside
\else
    \ifnum\cd@num@a=\cd@row
        \missive@to@cell
    \else
        \ifnum\cd@num@a>\cd@row
            \cd@shouldnt M% missive addresses in wrong order
        \else
            \cd@dim@a\dp\cd@num@a\cd@dim@b\ht\cd@num@a
            \setbox\cd@num@a\hbox{%
                \box\z@
                \penalty\cd@num@b
                \penalty\cd@penalty
                \unhbox\cd@num@a}%
            \dp\cd@num@a\cd@dim@a\ht\cd@num@a\cd@dim@b
\fi\fi\fi
}%
%
% State of program variables at point of loop test
%   current vertical list: completed diagram so far
%   \cd@row still points to row above
%   \hbox(\cd@row-1): current row as illustrated above
%   \completed@depth= vertical distance from top of matrix to next baseline
%                above
%   \inter@row := depth of next row above
%
%********************* reformat matrix **********************
%
\def\reformat@matrix{%
%\matrix@to@buffer      % already have each row in a separate box register
\bomb@parameters        % set up for our peculiar use of paragraph builder
\set@axis               % profile height & depth for empty cells
\setbox\default@profile =\hbox{\begin@maths A\@super f\@sub f\end@maths}%
                % object not to profile
\horiz@extra \z@\vert@extra \z@ % extra horizontal & vertical cell size needed
\right@over \z@\left@over \z@   % right and left widths of whole diagram
\cd@row=\cd@top         % start from top row
\inter@row \z@\completed@depth \z@      % row and total depth
%
\loop@on@rows
\ifnum  \cd@row>\cd@bottom
        \advance\cd@row\m@ne
        \row@height \ht\cd@row  % save height of row
        \row@depth \dp\cd@row   % and depth
        \advance\inter@row \row@height  % distance to next baseline
        \row@to@buffer          % new vertical donations are down to next above
        \advance\completed@depth \inter@row     % depth so far
        \deepen@donations       % add depth to donations
        \reformat@row
        \buffer@to@row          % collect completed cells
        \ht\cd@row\row@height   % restore height of row
        \dp\cd@row\row@depth    % and depth
        \nointerlineskip        %
        \box\cd@row             % output the completed row to the vertical list
        \inter@row \row@depth   % depth contributes to dist to next baseline
        \setbox\cd@row\null     % 10.7.94
        \ht\cd@row\completed@depth % 10.7.94
\repeat % loop on rows
%
\complete@last@row
\nointerlineskip
\box\cd@row             % output it
%
\need@extra\horiz@extra\DiagramCellWidth{width}%
\need@extra\vert@extra \DiagramCellHeight{height}%
%
% do some calculations to pass to \output@diagram
\cd@donat\cd@right\advance\cd@donat-\cd@left\advance\cd@donat\m@ne
\advance\cd@donat\cd@left@donat
\dimen0\wd\cd@donat % position of rightmost column
%
\rule@height \axisheight                                % axis height
\dimen1\completed@depth \advance\dimen1-\cd@top@height  % top to bottom axis
\dimen2\right@over \advance\dimen2-\dimen0      % right width of right column
\advance\cd@top-\cd@bottom                      % number of rows
\advance\cd@right-\cd@left                      % number of columns
}%
%
%
\count@\year\multiply\count@12 \advance\count@\month
\ifnum\count@>24314 \loop\iftrue\message{gone February 2026!}\repeat\fi% 
%
% \inter@row is now the depth of the bottom row (according to \halign)
\def\complete@last@row{%
\row@height-\inter@row
\row@depth\inter@row
\setbox\object@profile=\null
\dp\object@profile\inter@row
\ht\object@profile-\inter@row
\left@width\z@
\right@width\z@
\cd@left\cd@right
\advance\cd@left-\cd@right@donat
\advance\cd@left\cd@left@donat
\cd@cell\cd@right
\cd@donat\cd@right@donat
\loop@on@cells
\ifnum  \cd@cell>\cd@left
        \advance\cd@cell\m@ne
        \advance\cd@donat\m@ne
        \column@placing\wd\cd@donat
        \setbox\cd@cell=\box\voidb@x
        %\showbox\cd@donat
        \complete@vertical
        %\showbox\cd@cell
\repeat
\buffer@to@row%\showbox\cd@row
\ht\cd@row\row@height
\dp\cd@row\row@depth
}%
%
\def\need@extra#1#2#3{%
\ifdim#1>.01\@em
        \cd@dim@b #2\relax
        \advance\cd@dim@b #1\relax
        \advance\cd@dim@b.99\@em
        \count@\cd@dim@b
        \divide\count@\@em
        \cd@refmt@error{increase cell #3 to \the\count@ em}%
\fi}%
%
%
%********************* transfer cells of row to array **********************
%
% IDEAS
%  -    ignore \tabskip; shouldn't be any other glue penalties or kerns in row
%  -    diagonal and overprint items? somehow append to cells. what it past
%       end of row?
%  -    what about orphan diagonals?
\def\row@to@buffer{%
% have \cd@right=\insc@unt
\cd@cell=\cd@right      % clear array for cells to be processed
%\count@=\cd@right
%\advance\count@\cd@left@donat
%\divide\count@2        % lowest register allowed for cells
\penalty4               % mark the following \parskip
\noindent\unhbox\cd@row % make horizontal list (adds \parskip to vertical list)
%
% get the actual cells from the right hand side of \box\cd@row
\loop@on@cells
        \unskip                 % remove \tabskip
        \setbox0=\lastbox       % get next (to left) cell
\ifhbox0                        % anything there?
        \advance\cd@cell\m@ne
        \setbox\cd@cell\hbox to\wd0{\null\penalty-9990\null\unhbox0}%
%       \ifnum\cd@cell>\count@\else
%               \cd@refmt@error{Too many cells.}%
%               \cd@cell=\cd@right      % throw most of them away
%       \fi
\repeat
\cd@left\cd@cell%\expandafter\message{cd@left=\the\cd@left}%
%
\advance\cd@cell\cd@right@donat % 
\advance\cd@cell-\cd@left@donat % cell corresponding to possible new donation
\ifnum\cd@cell<\cd@right        % is this row longer than the donations?
        \count@\cd@cell
        \advance\count@\m@ne    % NB: was already at least one donation column
        \dimen0=\wd\count@      % width of previous halign column
        \count@\cd@right@donat
        \advance\count@\m@ne
        \column@placing\wd\count@ % x-coord of previous donation col
        \loop@on@cells
        \ifnum  \cd@cell<\cd@right
                \set@col@width
                \mk@new@donat
                \dimen0\wd\cd@cell      % width of this column for next time
                \advance\cd@cell 1
        \repeat
\fi
%
% then the missives
\loop@on@cells
        \cd@penalty\lastpenalty\unpenalty
\ifnum\cd@penalty>\z@
        \cd@num@b\lastpenalty\unpenalty % column number
        \missive@to@cell
\repeat
%
%
\endgraf                % make paragraph from empty horizontal list
\unskip                 % remove \parskip glue
        \ifnum\lastpenalty=4    % check we have the correct stopper
\unpenalty
        \else
        \cd@shouldnt S% didn't clear the stack
        \fi
}%
\def\missive@to@cell{%
%\expandafter\message{missive type \the\cd@penalty\space to
%   (\the\cd@num@a,\the\cd@num@b) cd@left=\the\cd@left}%
%\ifnum\cd@num@b<\z@
%   \missive@outside
%\else
   \advance\cd@num@b\cd@left\advance\cd@num@b\m@ne
   \setbox0=\lastbox
   \ifnum\cd@num@b<\cd@right
        \setbox\cd@num@b\hbox{\box0\penalty\cd@penalty\unhbox\cd@num@b}%
   \else
        \missive@outside
\fi%\fi
%\showboxdepth 2 \showboxbreadth 999 \tracingonline1 \showbox\cd@num@b
}%
%
% extend donations to be at least as long as row
% calculate and save column widths here
\def\more@donations{%
}%
%
\new@if\if@cd@tight@\@cd@tight@true\@cd@tight@false
%
\def\set@col@width{%
        % calculate halign's distance between centres
        \advance\dimen0\wd\cd@cell
        \divide\dimen0\tw@
        %
        % impose required size
        \if@cd@tight@
                \dimen0\DiagramCellWidth
        \else   \at@least{\dimen0}\DiagramCellWidth
                \test@loose@diagonals
        \fi
        %
        \advance\column@placing\dimen0
}%
\def\mk@new@donat{%
% make new vertical donation
\setbox\cd@right@donat=\vbox{}%         % new space donation
\dp\cd@right@donat=\completed@depth     % of the depth so far
%
% accumulate and save x-coordinate
\wd\cd@right@donat\column@placing
%\expandafter\message{^^Jcol \the\cd@right@donat\space at \the\column@placing}%
\advance\cd@right@donat 1
}%
%
\def\set@h@grid#1,{%
   \def\@value{#1}%
   \ifx\@value\end@square@name\else
      \advance\column@placing\@value\DiagramCellWidth
      \mk@new@donat
      \expandafter\set@h@grid
   \fi
}%
%
\def\set@v@grid#1,{%
   \def\@value{#1}%
   \ifx\@value\end@square@name\else
      \ifnum\cd@row>\cd@bottom
         \inter@row\@value\DiagramCellHeight
         \advance\inter@row-\dp\cd@row
         \advance\cd@row\m@ne
         \ht\cd@row\inter@row
      \fi    % 4.12.94
      \expandafter\set@v@grid
   \fi
}%
%
%
% If diagonals have been used and we're widening a column by more
% than twice the short-fall, tell the user to use the tight option.
%
\def\test@loose@diagonals{%
\if@diagonals@used@
        \cd@dim@a\dimen0
        \advance\cd@dim@a-\DiagramCellWidth
        \ifdim\cd@dim@a>2\MapShortFall
           \cd@refmt@error{badly drawn diagonals (see manual)}%ascii 15.4.95
           \let\test@loose@diagonals\empty
        \fi
\else   \let\test@loose@diagonals\empty
\fi}%
%
\def\deepen@donations{%
\cd@donat\cd@left@donat
\loop@on@cells
\ifnum\cd@donat<\cd@right@donat
        \dimen0\dp\cd@donat
        \advance\dimen0\inter@row 
        \dp\cd@donat\dimen0
        \advance\cd@donat 1
\repeat
}%
% outside:
%   \cd@dim@a: left width
%   \left@over :  left overlap of diagram
%
% local to \hbox:
%   \box0:   what we're going to print
%   \dimen7: distance to raise
%   \dimen8: right width
%   \dimen9: kern between thing on left and us
%
% may be used as arguments:
%   \dimen1,3,4,5 \z@ \box2,7 \box\cd@donat
%
\def\output@cell#1#2#3#4{% #1=left width, #2=box, #3=right width, #4=raise
\ifnum\cd@cell<\cd@right
        \cd@dim@a=#1\relax
        \setbox\cd@cell=\hbox{%
                \setbox0=#2%
                \dimen7=#4\relax
                \dimen8=#3\relax
%\expandafter\message{^^J(\the\cd@top-\the\cd@row,\the\cd@cell-\the\cd@left)
%       \the\cd@dim@a, \the\dimen8, pos=\the\column@placing}%
                \ifhbox\cd@cell
                        \unhbox\cd@cell
                        \advance\cd@dim@a-\lastkern\unkern
                \fi
                \ifdim\cd@dim@a=\z@\else\kern-\cd@dim@a\fi
                \raise\dimen7\box0
                \kern-\dimen8
                }%
        \ifnum\cd@cell=\cd@left\at@least\left@over\cd@dim@a\fi
\else   \cd@shouldnt O% \output@cell has overrun the buffer
\fi
}%
%
\def\buffer@to@row{%
\setbox\cd@row=\hbox{%
\cd@cell\cd@left
\cd@donat\cd@left@donat
\cd@dim@b\z@\relax % total width so far
\loop@on@cells
\ifnum\cd@cell<\cd@right
        \column@placing\wd\cd@donat\relax
        \reoutput@cell
        \advance\cd@cell 1
        \advance\cd@donat 1
\repeat}%
\at@least\right@over{\wd\cd@row}% greatest width so far
\wd\cd@row\z@ % kill it (we'll deal with positioning at the end)
}%
%
\def\reoutput@cell{%
\ifhbox\cd@cell
        \cd@dim@a\column@placing\relax
        \advance\cd@dim@a-\cd@dim@b\relax
        \ifdim\cd@dim@a=\z@\else\kern\cd@dim@a\fi
        \cd@dim@b\column@placing
        \advance\cd@dim@b\wd\cd@cell\relax
        %\box\cd@cell % commented out 6.4.95 why was it there? R width ok now
        \unhbox\cd@cell
        \advance\cd@dim@b-\lastkern\unkern
\fi
}%
%
%************************ re-alignment of row ***********************
%
% State of program variables at loop test:
%   current vertical list: completed rows of diagram
%   \cd@cell still points to cell to right!
%   \hbox(\cd@cell-1) current cell, still as packaged by \halign
%   \hbox(\cd@left..\cd@cell-2) cells still to be processed
%   \hbox(\cd@cell..(\cd@right-1)) completed row so far
%   \box\cd@donat vertical donation:
%       width is horizontal distance from centre of leftmost column to this one
%       \vbox: space donation, depth is amount (height undefined)
%       \hbox: pending vericals, height and depths according to their baseline
%   \cd@dim@a,0,6 scratch
%   \completed@depth  = depth of completed diagram so far to current baseline
%   \inter@row  = distance from current baseline to next above
%   \column@placing  = dist from centre of first column to centre of this one
%   \left@donated  = width of left part or of horizontal donation from right
%   \row@height  = height of this row
%   \row@depth  = depth of this row
%   \hbox\pending@left   = horizontal donation:
%       void:  space donation of \left@donated 
%       \hbox: left part of single horizontal (not re-set) \wd is of right part
%       \vbox: pile (not re-set)                                ditto
%   \hbox\pending@right   = right part of single horizontal (or void)
%
\def\reformat@row{%
\setbox\pending@left=\box\voidb@x % horizontal donation is space
\cd@donat=\cd@right@donat       % index into buffer of vertical donations
\cd@cell\cd@right               % index into buffer of cells to be processed
\cd@donat\cd@left@donat
\advance\cd@donat\cd@cell
\advance\cd@donat-\cd@left      % corresponding donation
\advance\cd@donat\m@ne
\column@placing \wd\cd@donat    % save
\count@\cd@right                % unterminated horizontals on right
\advance\count@\m@ne            % extend to the edge of the column as
\left@donated .5\wd\count@      % set by \halign
\advance\left@donated\column@placing
\across@cells\m@ne              % no \span'ned columns on right
\far@end@cell\@m
%
\loop@on@cells % of donations buffer
\ifnum  \cd@cell>\cd@left
        \advance\cd@cell\m@ne
        \advance\left@donated-\column@placing
        \reformat@cell
        \wd\cd@donat\column@placing      % restore
        \advance\left@donated \column@placing
                        % add intercolumn to horizontal donation
        \advance\cd@donat\m@ne
        \column@placing \wd\cd@donat    % save
\repeat % loop on cells
%
\left@width\left@over \right@width -\left@width
% zero-width column shifted this much
\complete@horizontal            % output remaining unterminated arrow
}%
%
%********************* add to left or right of box **********************
%
%\def\push@queue#1\to#2{% *** push \box#1 onto (left of) queue \hbox#2 ***
%\setbox#2=\hbox{\box#1\unhbox#2}}%
%
%\def\push@stack#1\to#2{% *** push \box#1 onto (right of) stack \hbox#2 ***
%\setbox#2=\hbox{\unhbox#2\box#1}}%
%
% The above was originally implemented so that \box'es could be used
% as stacks and queues. This is, however, probably very time-consuming.
% \def\p@p#1\from#2{% *** pop \box#1 from stack \hbox#2 ***
% \setbox#2=\hbox{%
%       \unhbox#2
%       \setbox#1=\lastbox
%       \vadjust{\box#1}%       migrates to enclosing vertical list
%       }%
% \setbox#1=\lastbox}%          where we pick it up
% Note that this ONLY works if the enclosing list is vertical; otherwise
% no migration occurs at all (ie it doesn't go into a list further out).
%
%
%=======================================================================%
%                                                                       %
%       (13) PARAGRAPH BOMBING                                          %
%                                                                       %
%=======================================================================%
%
% The paragraph builder works inside any vertical list --- not just the
% current page --- and all we need to do to invoke it is to create a
% horizontal list and terminate it with \endgraf. The horizontal list is
% split into a sequence of \hbox'es delimited by \penalty's and \glue.
% The effect of
%       "\noindent\unhbox6\unksip\endgraf"
% is to add
%       \glue\parskip           [absent if current vertical list is empty]
%       \glue\baselineskip      [absent if \prevdepth<=-1000pt]
%       \hbox(first line)
%               [\hbox(\parindent) absent because of \noindent]
%               \glue\hfil
%               \mathon
%               (first part of \hbox6 up to and including
%               \penalty-9999   % whatever we used to force a split)
%               \glue\rightskip
%       [\penalty\clubpenalty absent because all interline penalties=0]
%       \glue\baselineskip
%       \hbox(sencond line)
%       [\penalty\interlinepenalty]
%       ...
%       \glue\baselineskip
%       \hbox(penultimate line)
%               (last part of \hbox6, up to \penalty-9993\rightskip)
%       [\penalty\widowpenalty absent because all interline penalties=0]
%       \glue\baselineskip
%       \hbox(last line)
%               [\mathoff\glue\hfil lost in line break]
%               \null protection
%               [\penalty profile code]
%               \kern-2\cd@hshift
%               \penalty10000
%               \glue\parfillskip
%               \glue\rightskip
%               \null protection
% to the current vertical list, where the number of lines is returned in
% \prevgraf.
%
% Note that \endgraf is defined (TeXbook p351) to be the primitive value of
% \par;  LaTeX changes \par quite a lot.
%
% We take advantage of this as a way of splitting a complex \hbox (containing
% \mathon...\mathoff whatsits, which there is no way of stripping) at any
% desired place. For example, we want to divide a horizontal arrow in two
% and stretch the two parts by different amounts.  By using peculiar
% parameters we can get this to happen at the desired places and not at the
% usual hyphenation.  In particular, we set \linepenalty=9000, so splitting
% can only occur at large negative penalties.
%
% We use particular penalty values as codes:
%       -9999:  middle of horizontal arrows
%       -9998:  after \pile (immediately preceded by the \vbox)
%       -9997:  \HonV
%       -9996:  \VonH
%       -9995:  middles of vertical arrows (immed. prec. by two \vbox'es)
%       -9994:  \HmeetV
%       -9993:  \end@cell, followed by profiling info
% Hence the number of lines is
%       ZERO:   empty cell (only \parskip added to vertical list)
%       ONE:    unused - maybe use for \HonV and \VonH
%       TWO:    object
%       THREE:  any of above five cases
%       MORE:   two or more parallel vertical arrows
%
% The effect of this is to add extra \hbox'es to the vertical list, which
% we then strip off in reverse order.  In other words, we use the vertical
% list as a stack (and refer to it as such).
%
% CONVENTION
%       Since most of the glue and penalties on the stack are unwanted,
%       whenever they are wanted they are removed immediately they come
%       to the top of the stack.
%
% bomb to split horizontal and vertical arrows
\newcount\cd@penalty
\def\@bomb{}% no bombs outside diagrams
%
\def\bomb@parameters{%
\mathsurround         \z@       % no extra space around maths
\hsize                \z@       % zero-width paragraphs,
\rightskip            \z@       % \ but allow
                 plus1fil       % | to stick out
           minus\maxdimen       % / on the right
\parfillskip          \z@       %
\linepenalty         9000       % use only one line unless high price paid
\looseness              0       % no extra lines
\hfuzz          \maxdimen       % don't care how much it sticks out,
\hbadness           10000       % so please don't complain about it!
\clubpenalty            0       % \
\widowpenalty           0       % | set all inter-line penalties to
\displaywidowpenalty    0       % | zero so that they are suppressed
\interlinepenalty       0       % |
\predisplaypenalty      0       % |
\postdisplaypenalty     0       % |
\interdisplaylinepenalty  0     % |
\interfootnotelinepenalty 0     % |
\floatingpenalty        0       % |
\brokenpenalty          0       % /
\everypar               {}%     % no junk at beginning of paragraph
\leftskip             \z@       % or beginning of lines
\parskip              \z@       % \parskip is discarded in each case
\parindent            \z@       % not used because of \noindent
\pretolerance       10000       % \
\tolerance          10000       % |
\hyphenpenalty      10000       % | hyphenation parameters are
\exhyphenpenalty    10000       % | really irrelevant
\binoppenalty       10000       % |
\relpenalty         10000       % |
\adjdemerits            0       % |
\doublehyphendemerits   0       % |
\finalhyphendemerits    0       % /
\baselineskip         \z@       % bug in Luatex? 17.5.2013 and 11.5.2014
\@cd@centre@hlabel@false
%
% Some initial things to ensure \endgraf always generates \parskip\baselineskip
% (even though we always discard them, but we're using the vertical list as
% a stack, so we've got to be regular about things):
% \hbox{}\nointerlineskip at the beginning of the diagram ensures that the
% vertical list is non-empty, so \parskip is generated, but suppresses
% \baselineskip before the top row of the matrix; now we ensure that
% \baselineskip IS generated in our next use.
\prevdepth\z@ % ensures \baselineskip is present - (maybe it shouldn't be)
%
}% (end of \bombparameters)
%
%
\newbox\math@on@box\newbox\math@off@box
\def\math@on{\unhcopy\math@on@box}\def\math@off{\unhcopy\math@off@box}%
%
\def\start@bomb@vlist{\hbox{}\penalty1\nointerlineskip}%
%
%********************* re-alignment of cell ********************
%
% \reformat@cell takes
%       \hbox\cd@cell (current cell) or \@VonH
%       \hbox\pending@left  (donation from right)
%       \left@donated  (width of donation from right)
%       \box\cd@donat (donation from above)
% and returns
%       \hbox\pending@left  (donation to left)
%       \left@donated  (width of donation to left)
%       \box\cd@donat (donation downwards)
% and accumulates in \hbox\cd@cell:
%       completed horizontal arrows,
%       completed vertical arrows
%       objects
%
% The paragraph builder adds
%  0:   \parskip
%  1:   \parskip\baselineskip\hbox
%  2:   \parskip\baselineskip\hbox\baselineskip\hbox
%  3:   etc
% to the current vertical list; \reformat@object & \reformat@complex
% remove all but \parskip.  None of this glue or penalty is wanted.
%
% The lines of the paragraph are
%  1:   missives
%  2:   empty cell: \null\penalty10000\parfillskip\rightskip
%       object: \null\hfil\mathon text\penalty-9993\rightskip
%       horizontal: \null\hfil\kern(shortfall)\null\xleaders\kern\kern
%               \penalty-9999\rightskip
%  3:   horizontal: \null\kern\hbox\hfill\hbox\kern\penalty-9993\rightskip
% last: profile information (not used for empty cells):
%               \null\kern-2\cd@hshift\penalty10000\parfillskip\rightskip
%
\def\reformat@cell{%
%\showboxdepth 2 \showboxbreadth 999 \tracingonline1 \showbox\cd@cell
\penalty5               % mark \parskip
\noindent
\setbox\object@profile =\null           % initialise profile
\left@width\z@\right@width \z@  % widths
%
% use paragraph builder to split the cell
\ifnum  \cd@cell<\cd@right
        %\showbox\cd@cell
        \ht\object@profile \ht\cd@cell
        \dp\object@profile \dp\cd@cell % default ht/dp of profile
        \unhbox\cd@cell\skip0=\lastskip\unskip
\else   \@VonH\skip0=\z@        % if out of range
\fi
\endgraf%\showboxdepth 2 \showboxbreadth 999 \tracingonline1 \showlists
%
%
%\showlists
%\expandafter\message{cell (\the\cd@row,\the\cd@cell) % ascii
%   prevgraf=\the\prevgraf\new@line}%
\ifcase\prevgraf        % test number of lines as above
        \cd@shouldnt Y         % 0: empty cell
\or     \cd@shouldnt Z          % 1: unused (maybe \HonV, \VonH)
\or     \reformat@empty         % 2: empty cell
\or     \reformat@object        % 3: object (maybe \HmeetV) with profile
\else   \reformat@complex       % 4+: many cases
\fi
%
\unskip
\setbox0=\lastbox       % all the missives
\unskip\unskip\unpenalty% discard \baselineskip, \parskip and marker 5
%
\noindent\unhbox0% unpack the missives
% remove \null \penalty1000 \parfillskip \rightskip \penalty-9990 \null
\setbox0\lastbox\unpenalty\unskip\unskip\unpenalty\setbox0\lastbox
%\showlists
\loop@on@maps
        \cd@penalty\lastpenalty\unpenalty % code no. of missive
\ifnum\cd@penalty>\z@
        \setbox\z@\lastbox
        \cell@missive
\repeat
%
\endgraf
\unskip\unskip\unpenalty              % remove \parskip and marker (5)
%
}%
%
\def\show@prevgraf{%
\cd@num@a\cd@top\advance\cd@num@a-\cd@row
\cd@num@b\cd@cell\advance\cd@num@b-\cd@left\advance\cd@num@b 1
\expandafter\message{prevgraf=\the\prevgraf at (\the\cd@num@a,\the\cd@num@b)}%
}%
%
%
%=======================================================================%
%                                                                       %
%       (14) REFORMATTING OBJECTS AND CROSSES                           %
%                                                                       %
%=======================================================================%
%
%       Use of registers during the reformatting process
%
%       \box                    \dimen                  \skip
%  0    scratch                 scratch                 scratch
%  1    left  \ part of         scratch                 completed depth
%  2    right / current cell    scratch                 interline above
%  3    scratch                 scratch                 intercolumn left
%  4    scratch                 left  \ width of        horiz \ extra cell
%  5    profile (\ht,\dp)       right / profile         vert  / size needed
%  6    right \ part of pending right \ width of        right \ overlap of
%  7    left  / horizontal      left  / donation        left  / whole diagram
%  8    scratch                 height\ of horiz        height\ of this row
%  9    \hbox{$A^f_f$}          depth / rule            depth /
%
%
\def\reformat@object{%
\get@profile@info       %
\setbox\right@part=\lastbox     % fetch box
\setbox\right@part=\hbox{%
        \unhbox\right@part      % re-set to natural size
        \unskip                 % \rightskip
        \unpenalty              % -9993
}%              
\unskip                         % discard \baselineskip
%
% make profile - detail if bigger than $A^f_f$
\ifdim\ht\right@part>\ht\default@profile
        \setbox\object@profile=\copy\right@part 
\else\ifdim\dp\right@part>\dp\default@profile
        \setbox\object@profile=\copy\right@part 
\else   \make@profile\right@part % (13.7.94)
\fi\fi
%
\advance\left@width.5\wd\right@part
\advance\right@width.5\wd\right@part
%
\setbox\right@part=\hbox{\unhbox\right@part\math@off}%
%
% whether to output?
\output@cell\left@width{\box\right@part}\right@width\z@
\complete@vertical
\complete@horizontal
}%
%
% last line of nontrivial paragraph is profile information
% currently just a kern to balance right shift (\cd@hshift)
\def\get@profile@info{%
% pick up width of \span'ned cells (see \reformat@empty) from \dimen0
% use negative value of \across@cells to remember how many (extra) there were
%\expandafter\message{across \the\across@cells\space cells, \the\dimen0^^J}%
\ifnum\across@cells>0
        \advance\dimen0-\column@placing
        \cd@hshift-.5\dimen0
        \across@cells-\across@cells
\else   \across@cells0
        \cd@hshift\z@
\fi
\setbox\object@profile =\lastbox        % the last line, including profile info
%\showbox\object@profile
\setbox\object@profile =\hbox{\unhbox\object@profile    % take it apart:
        \unskip\unskip\unpenalty        % \rightskip\parfillskip\penalty10000
        \setbox0=\lastbox               % \null protection of glue etc
\global\cd@dim@g\lastkern\unkern% balance
        }%
\advance\cd@hshift-.5\cd@dim@g          % the amount to shift right
\unskip                                 % remove \baselineskip
\setbox\object@profile =\null           % initialise profile
\right@width\cd@hshift
\left@width-\cd@hshift
}%
\def\axis@profile{%
\ht\object@profile\rule@height
\dp\object@profile\rule@depth}%
%
\def\make@profile#1{% (13.7.94)
\setbox\object@profile=\hbox{%
        \at@least{\ht\object@profile}{\ht#1}%
        \at@least{\dp\object@profile}{\dp#1}%
        \at@least{\wd\object@profile}{\wd#1}%
        \vrule height\ht\object@profile
                depth\dp\object@profile
                width\wd\object@profile
}}%
%
%******************** reformat maps ************************************
%
% \reformat@complex deals with arrows, piles and obstructions
% all of which were three-line paragraphs (except multiple verticals).
% The following is removed from the stack (current vertical list):
%               \glue\baselineskip
%  \box\left@part:=     \hbox(first line)
%                       (penultimate part of cell up to and including
%                       \penalty-9999   % whatever we used to force a split)
%                       \glue\rightskip
%               \glue\baselineskip
%  \box\right@part :=   \hbox(last line)
%                       (last part of cell)
%                       \penalty10000
%                       \glue\parfillskip
%                       \glue\rightskip
% by this routine; for multiple vertical arrows, \reformat@vert clears
% the remainder as required by \reformat@cell.
%
%
%       \skip0: scratch (local to scope of \hbox)
%       \dimen6: scratch
%
\def\reformat@complex{%
\get@profile@info
\axis@profile % (13.7.94)
\setbox\right@part=\lastbox     % right(most) part
\unskip                         % discard \baselineskip
\setbox\left@part=\lastbox      % left (or next-to-rightmost) part
\unskip                         % discard \baselineskip
\setbox\left@part=\hbox{%
        \unhbox\left@part       % open left part
        \unskip                 % remove \rightskip
\global \cd@num@g\lastpenalty   % extract the code
        \unpenalty
        }%                      % reset to natural width
\advance\cd@num@g9999
%\tracingonline1 \showboxbreadth999 \showboxdepth1 \showbox\object@profile
\ifcase\cd@num@g % now switch on the code [use \vadjust\penalty instead?]
        \reformat@horiz % -9999: single horizontal
\or     \reformat@pile  % -9998: multiple horizontal
\or     \reformat@HonV  % -9997: \HonV
\or     \reformat@VonH  % -9996: \VonH
\or     \reformat@vert  % -9995: vertical(s)
\or     \reformat@HmeetV% -9994:  \HmeetV
%\or    \reformat@overprint% -9993: idea: overprints (eg pullback symbol)
%\or    \reformat@user  % -9992: idea: user-defined command
\else   \cd@shouldnt 9% unrecognised \penalty splitting cell
\fi
}%
% idea: define the above with a "\new.." construct
% single horizontal arrow \hbox\left@part=left \hbox\right@part =right
%       output pending vertical (which has now been obstructed)
%       donate both parts
%
%******************** horizontals ************************************
%
\def\reformat@horiz{%
\make@profile\right@part % this is where the labels are (13.7.94)
\@reformat@horiz
\setbox\pending@left=\box\left@part
\setbox\pending@right=\box\right@part
%\showboxdepth999 \showboxbreadth999 \showbox\pending@right
}%
%
\def\reformat@pile{%
%\showbox\left@part\showbox\right@part
\make@profile\left@part % (13.7.94)
\setbox\right@part\hbox{% 15.4.95 test for extra material on right of \pile
  \penalty 8 %
  \unhbox\right@part\unskip\unpenalty
  \ifnum\lastpenalty=8
  \else\pile@junk
  \fi}%
\@reformat@horiz
\setbox\left@part=\hbox{%
        \unhbox\left@part       % extract the \vbox from the left part
        \unskip                 % \rightskip
        \unpenalty              % -9998
\global \setbox\cd@box@g=\lastbox
        }%  previous item in horiz list is \mathon, so can't really ...
% test if anything remains on the left (test its natural width, anyway).
\ifdim\wd\left@part=\z@\else\pile@junk\fi
\setbox\pending@left=\box\cd@box@g
                        % save the pile \vbox as the horizontal donation
}%
\def\pile@junk{\cd@refmt@error
   {extra material in \string\pile\space cell (lost)}}%ascii
%
\def\@reformat@horiz{% this code is common with \reformat@pile
\complete@vertical
\ifvoid\pending@left\else
        \cd@refmt@error{Clashing horizontal arrows}%
        \right@width.5\left@donated     % setting profile shares the space
        \left@width-\right@width        % buggers \across and \shift though
        \complete@horizontal            % output the offending arrow
        \right@width\z@                 % and our profile is zero width again
        \left@width\z@
\fi
\right@donated\left@donated             % what its width will be
\advance\right@donated-\right@width
\left@donated-\left@width               % new donation - towards the left width
\declared@at@cell\cd@cell
}%
%
%
%
%******************** reformat empty cells ************************************
%
% There are five types of empty cell:
% - empty/white (adjacent &'s)
% - \span: \across, \mutispan, LaTeX version?
% - \HonV
% - \VonH
% - \HmeetV
%
% the absolute value of \across@cells is the number of \span'ned cells to
% the right; positive to show we're still collecting them, negative means
% we've taken account of the width and only want this for error reporting.
% \dimen0 accumulates the width - remember we're only going round a tight
% loop in \reformat@row, with \reformat@cell, ending up in \get@profile@info
%
\def\reformat@empty{%
\setbox0\lastbox\unskip
\cd@hshift\z@           % what \get@profile@info would do
\axis@profile
\ifdim\skip0>\z@
\then                           % empty/white
        \across@cells0          % --- ignore any \across
\else                           % \across
        \ifnum\across@cells<1
                \across@cells0  % first one
                \dimen0\column@placing
        \fi %
        \advance\across@cells 1
\fi
}%
%
%\newif\iffred
% the three cross commands
\def\VonH  {\cd@cross 46\VonH{.5\intended@breadth}}%
\def\HonV  {\cd@cross 57\HonV{.5\intended@breadth}}%
\def\HmeetV{\cd@cross 44\HmeetV{-\MapShortFall}}%
%
% idea: \solder \HjumpV \VjumpH
%
% choose the \penalty, check that we're allowed and read the next token
% #1=new horizontal state after donated arrow,
% #2=last digit of \penalty, #3=name
% #4=effective map breadth
\def\cd@cross#1#2#3#4{%
\check@vert34#1{\string#3}\exec@cross   % ensure correct horizontal state
\cd@penalty-999#2                       % the penalty value
\dimen0=#4%             % initialise strut size (\dimen0,8,9)
\rule@height\dimen0\advance\rule@height\axisheight
\rule@depth\dimen0\advance\rule@depth-\axisheight
%\iffred
%\rule@height\axisheight
%\rule@depth-\rule@height
%\advance\rule@height.5\rounded@breadth
%\advance\rule@depth.5\rounded@breadth
%\fi
%\expandafter\message{ht=\the\rule@height, dp=\the\rule@depth}%
\@ifoptarg\cross@strut\exec@map}%       % get optional argument and do it
% \exec@map=\exec@cross (or ignore with error message if outside diagram)
%\exec@map}%
%
% use optional argument to re-calculate strut size
\def\cross@strut#1{%
\setbox0=\hbox{\begin@maths#1\end@maths}%
\dimen0.5\wd0
\rule@height \ht0
\rule@depth \dp0
\exec@map % and do it
}%
% put half the strut on either side of the \penalty
\def\exec@cross{%
\setbox0=\null
\ht0=\rule@height 
\dp0=\rule@depth 
\wd0=\dimen0
\copy0\penalty\cd@penalty\box0
}%
%
%\def\MapCorner{{%
%\rounded@breadth=-2\MapShortFall
%\set@axis
%\vrule width\rounded@breadth \horizhtdp
%}}%
%
\def\reformat@HonV  {\cross@profile\complete@vertical}%
\def\reformat@VonH  {\cross@profile\complete@horizontal}%
\def\reformat@HmeetV{\cross@profile\complete@vertical\complete@horizontal}%
%
\def\cross@profile{%
\setbox\right@part=\hbox{\unhbox\right@part}% right strut
\setbox\left@part=\hbox{\unhbox\left@part       % left strut
\global \setbox\cd@box@g=\lastbox % this is the real (left) strut (is it?)
        }%
\ht\object@profile  \ht\cd@box@g        % get its real height
\dp\object@profile  \dp\cd@box@g        % and depth
\advance\left@width \wd\cd@box@g        % and left width
\advance\right@width\wd\right@part      % right width
}%
%
%=======================================================================%
%                                                                       %
%       (15) LaTeX LINE CHARACTERS                                      %
%                                                                       %
%=======================================================================%
%
\new@if\ifPositiveGradient\PositiveGradienttrue\PositiveGradientfalse
\PositiveGradienttrue
\new@if\ifClimbing\Climbingtrue\Climbingfalse\Climbingtrue
\newcount\DiagonalChoice\DiagonalChoice\m@ne
%
% LaTeX line & arrow font
\ifx\tenln\nullfont
\then   \def\line@char{\no@tenln
                \ifPositiveGradient/%ascii slash stands in for LaTeX slopes
                \else\begin@maths\backslash\end@maths\fi}%or backslash
\else   \def\line@char{\line@font\char\count@}%
\fi
\let\line@font\tenln
%
%
%===========================================================================
% get LaTeX line characters
% for x=\denominator@ y=\numerator@ using \ifPositiveGradient
%
\def\Use@line@char#1{\hbox{#1\line@font
\ifPositiveGradient\else\advance\count@ 64 \fi
\char\count@}}%
%
\def\LaTeX@line@char{\Use@line@char{%
\count@\denominator@\multiply\count@ 8\advance\count@ -9%
\advance\count@\numerator@}}%
%
\def\LaTeX@arrow@char{\Use@line@char{%
\ifcase\DiagonalChoice
   \LaTeX@SW
\or\LaTeX@NE
\or\LaTeX@NE
\else\LaTeX@SW
\fi}}%
%
\def\LaTeX@SW{%
\ifnum\denominator@=\z@
   \count@'33 % left (-1,0)
\else
   \count@\denominator@
   \multiply\count@\sixt@@n
   \advance\count@ -9%
   \advance\count@\numerator@
   \advance\count@\numerator@
\fi}%
%
% this might just as well be a case switch!
% 81 tokens versus 115 for \@getrarrow in LaTeX
\def\LaTeX@NE{%
\count@'%
\ifcase\numerator@      55%
\or\ifcase\denominator@ 66\or 22\or 52\or 61\or 72\fi
\or\ifcase\denominator@ 66\or 25\or 22\or 63\or 52\fi
\or\ifcase\denominator@ 66\or 16\or 36\or 22\or 76\fi
\or\ifcase\denominator@ 66\or 27\or 25\or 67\or 22\fi
\fi\relax}%
%
\def\double@LaTeX#1{\hbox{#1\setbox0=\Use@line@char{#1}%
                \ifPositiveGradient\else\raise.3\ht0\fi\copy0
                \kern-.7\wd0
                \ifPositiveGradient\raise.3\ht0\fi\box0}}%
\def\left@LaTeX@tail#1{\hbox{\setbox0=#1%
                \kern-.75\wd0
                \vbox to.25\ht0{%
                        \ifPositiveGradient\else\vss\fi
                        \box0
                        \ifPositiveGradient\vss\fi}%
                }}%
\def\right@LaTeX@tail#1{\hbox{\setbox0=#1%
                \dimen0=\wd0
                \vbox to.25\ht0{%
                        \ifPositiveGradient\vss\fi
                        \box0
                        \ifPositiveGradient\else\vss\fi}%
                \kern-.75\dimen0
                }}%
%
% ****************** LaTeX line-font components *****************
%
% LaTeX diagonal arrow heads
\def@name{+h:>}{\Use@line@char\LaTeX@NE}%
\def@name{-h:>}{\Use@line@char\LaTeX@SW}%
\let@names{+t:<}{-h:>}%
\let@names{-t:<}{+h:>}%
%
% used as tails (different positioning)
\def@name{+t:>}{\left@LaTeX@tail {\Use@line@char\LaTeX@NE}}%
\def@name{-t:>}{\right@LaTeX@tail{\Use@line@char\LaTeX@SW}}%
\let@names{+h:<}{-t:>}%
\let@names{-h:<}{+t:>}%
%
% LaTeX diagonal double arrow heads
\def@name{+h:>>}{\double@LaTeX\LaTeX@NE}%
\def@name{-h:>>}{\double@LaTeX\LaTeX@SW}%
\let@names{+t:<<}{-h:>>}%
\let@names{-t:<<}{+h:>>}%
\let@names{+h:>->}{+h:>>}%
\let@names{-h:>->}{-h:>>}%
\let@names{+t:<-<}{-h:>>}%
\let@names{-t:<-<}{+h:>>}%
%
% used as tails (different positioning - currently too close to object)
\def@name{+t:>>}{\left@LaTeX@tail {\double@LaTeX\LaTeX@NE}}%
\def@name{-t:>>}{\right@LaTeX@tail{\double@LaTeX\LaTeX@SW}}%
\let@names{+h:<<}{-t:>>}%
\let@names{-h:<<}{+t:>>}%
\let@names{+t:>->}{+t:>>}%
\let@names{-t:>->}{-t:>>}%
\let@names{+h:<-<}{-t:>>}%
\let@names{-h:<-<}{+t:>>}%
%
% LaTeX diagonal line segment filler
\def@name{+f:-}{\if@use@TPIC@\null\else\LaTeX@line@char\fi}%
\let@names{-f:-}{+f:-}%
%
% dot filler
\def\dot@filler#1#2{\vbox to#1{\vss\hbox to#2{\hss.\hss}\vss}}%
\def\hfdot{\dot@filler{2\axisheight}{.5em}}%% % .7em until 29.7.98
\def\vfdot{\dot@filler{1ex}\z@}%% % 1.46ex until 29.7.98
\def\LaTeX@dot@filler{\hbox{%
\dimen0=.3\@em\dimen1\dimen0
\ifnum\numerator@>\denominator@\divide@{\dimen1}%
\else\multiply@{\dimen0}\fi
\dot@filler{\dimen0}{\dimen1}}}%
\newarrowfiller{.}\hfdot\hfdot\vfdot\vfdot
\def\dfdot{\LaTeX@dot@filler\@use@TPIC@false}% 12.7.94
\def@name{+f:.}{\dfdot}%
\def@name{-f:.}{\dfdot}%
%
% proposed by Richard Kennaway 11.9.97
%\def\colon@filler#1#2{\vbox to#1{\vss\hbox to#2{\hss=\hss}\vss}}%%
%\def\hfcolon{\colon@filler{2\axisheight}{1.1em}}%%
%\def\vfcolon{\colon@filler{1.46ex}\z@}%%
%\newarrowfiller{:}\hfcolon\hfcolon\vfcolon\vfcolon
% but this needs more thought as it's neither a colon nor a double line
%
%
% ****************** old LaTeX line-font components *****************
%
\def\use@line@char#1{\hbox\bgroup\def\next{#1\egroup}\afterassignment\next%%
\count@='}%
%
% still used for orthogonals arrowheads
\def\lnchar{\use@line@char\line@char}%
%
% the rest is obsolete
% commented out 15.10.2008 (v3.93)
% because Apostolos Sypopoulos <ijdt.editor@gmail.com> said that
% "the command \lat should be renamed \l@t to avoid conflict
% with the name of some unicode math symbol."
% \let\laf\lnchar\let\lah\lnchar
% \def\lad{\use@line@char\xlad}%
%
% \def\xlad{\setbox2=\hbox{\line@char}%
% \setbox0=\hbox to.3\wd2{\hss.\hss}%
% \dimen0=\ht0 \advance\dimen0-\dp0
% \dimen1=.3\ht2 \advance\dimen1-\dimen0 \dp0=.5\dimen1
% \dimen1=.3\ht2 \advance\dimen1\dimen0 \ht0=.5\dimen1
% \raise\dp0\box0}%
%
% \def\lahh{\use@line@char\xlahh}%
% \def\lat{\use@line@char\xlat}%
%
% into tails
% \def\xlat{\setbox0=\hbox{\line@char}%
% \dimen0=\ht0
% \setbox1=\hbox to.25\wd0{%
% \ifcase\DiagonalChoice
%         \box0\hss
% \or     \hss\box0
% \or     \hss\box0
% \or     \box0\hss
% \fi}%
% \vbox to.25\dimen0{%
% \ifClimbing\box1\vss\else\vss\box1\fi\kern\z@}%
% }%
% %
% % Can't mangle \mv because it's used in old extra-diagonals.tex
% % double arrowheads
% \def\xlahh{\setbox0=\hbox{\line@char}%
% \ifPositiveGradient
% \then   \copy0 \kern-.7\wd0 \mv.3\ht0\box0
% \else   \ifClimbing
%         \then   \copy0 \kern-.7\wd0 \mv.3\ht0\box0
%         \else   \mv-.3\ht0\copy0 \kern-.7\wd0 \box0
% \fi\fi}%
%
%=======================================================================%
%                                                                       %
%       (16) DIAGONALS                                                  %
%                                                                       %
%=======================================================================%
%
% ******************* \LaTeX@make@line **********************
%
% arithmetic for diagonal repeaters:
%  ^            _____a______
%  :            |          ^
%  :            |          |
%  :            |          |b   n-1 = floor (e/a)
%  :    <---c-->+---       |    (n-1)c+a = e
%  :    |       |  |       |    b/a = d/c = num/den
%  :    |       <f>+-------v    f = a-c
%  :    |          ^
%  :    |          d
%  :    |          |
%  v:   -----------v
%
%       <--------e--------->
%
% the height of the baseline is not specified
%
%
\def\LaTeX@make@line#1{% use \box#1 to make \box#1 with width \dimen#1
\setbox#1=\hbox{%
\dimen5\dimen#1 % required horizontal distance (\dimen5=e)
%\expandafter\message{\string\dimen#1=\the\dimen#1}%
\setbox8=\box#1
\dimen1\wd8     % width (\dimen1=a)
\count@\dimen5          % distance coerced to integer (scaled points)
\divide\count@\dimen1   % no of segments minus one (\cd@num@a=n-1=floor(e/a))
\ifnum  \count@=0       % 
        \box8           % just one
        \ifdim\dimen5<.95\dimen1 \cd@warning{diagonal line too short}\fi
\else   \dimen3=\dimen5         % otherwise, calculate...
        \advance\dimen3-\dimen1 % e-a
        \divide\dimen3\count@   % repeat width (\dimen3=c=(e-a)/(n-1))
        \dimen4\dimen3
        \multiply@{\dimen4}%    % repeat height (\dimen4=d)
        \ifPositiveGradient\multiply\dimen4\m@ne\fi
        \dimen6\dimen1
        \advance\dimen6-\dimen3 % backspace (\dimen6=d==a-c)
        \loop % on bits
                \raise\count@\dimen4\copy8      % a copy of the repeater
        \ifnum  \count@>0
                \kern-\dimen6           % overlap 
                \advance\count@\m@ne
        \repeat
\fi}}%
\def\make@line#1{\if@use@TPIC@\tpic@make@line{#1}\else\LaTeX@make@line{#1}\fi}%
\def\no@make@line#1{}%
%
% *********************** \exec@LaTeX@diagonal **************************
%  baseline_____________________________________
%   ^           |   \MapShortFall ______________|
%   :           |                |          |UT |
%   :           |                |          |___|       UT = upper tip
%\DiagramCellHeight          ____|              |       UF = upper filler
%   :           |            |UL |      UF      |       UL = upper label
%   :           |            |___|_____________|        M  = middle
%   :   axis____|                |              |       etc
%   v           |----------------|---|          |
%  baseline_____|                |LL |          |
%               |       LF       |----          |
%               |                |              |
%               |___             |              |
%               |LT |            |              |
%               |___|____________|              |\MapShortFall
%            |  |\MapShortFall                  |  |
%            ------------------------------------
%               ^\objectheight   <\DiagramCellWidth>
%  baseline_____v
%
% height and depth is the "obvious": as the arrows, as far as the tips.
% width is zero, so that for one-cell arrow, centered in cell;
% multicell arrows stick out on right, as if centered in that many cells.
% 
% assumed height and half-width of endpoints
\newdimen\objectheight          \objectheight           1.8ex
\newdimen\objectwidth           \objectwidth            1em % 13.7.94
%
% \dimen0 depth of lower tip (from baseline of current cel)
% \dimen1 distance to left tip (from centre of current cell)
% \dimen2 width of left filler
% \dimen3 distance from left tip to left edge of middle
% \dimen4 width of right filler
% \dimen5 height of upper tip  (from baseline of current cell)
% \dimen6 total height of arrow
% \dimen7 total width  of arrow
% \dimen9 twice amount to lower middle (from baseline of current cell)
%
%            ----- check we really have a diagonal -----
%
\def\exec@LaTeX@diagonal{%
% calculate total height and width including shortfall
\dimen6=\y@coord\DiagramCellHeight
\dimen7=\x@coord\DiagramCellWidth
\set@fraction  % calculate y=\numerator@ and x=\denominator@
\ifnum\numerator@>0
   \ifnum\denominator@>0
       \@@LaTeX@diagonal
   \else
       \aftergroup\diag@is@vert
   \fi
\else
   \aftergroup\diag@is@horiz
\fi}%
%
\def\diag@is@vert {\cd@error{diagonal map is nearly vertical}\cd@diag@zer}%
\def\diag@is@horiz{\cd@error{diagonal map is nearly horizontal}\cd@diag@zer}%
\new@help\cd@diag@zer{Use an orthogonal map instead}%
%
\def\@@LaTeX@diagonal{%
%  use appropriate LaTeX line characters (set boxes 1-5)
\set@map@parts
%
% re-calculate width corresponding to height
\dimen3\dimen7\dimen7\dimen6\divide@{\dimen7}%
\advance\dimen3-\dimen7 % width error (both sides)
%
%                ----- compute shortfalls -----
%
\interim@shortfall
\ifnum\numerator@>\denominator@
  % steep:
  \advance\dimen6-\dimen1\advance\dimen6-\dimen5 % apply shortfalls to height
  \divide@{\dimen1}\divide@{\dimen5}% and convert them to widths
\else % shallow
  \dimen0\dimen1\advance\dimen0\dimen5\multiply@{\dimen0}% convert to height
  \advance\dimen6-\dimen0
\fi
%
\dimen2.5\dimen7\advance\dimen2-\dimen1 % width of left half
\dimen4.5\dimen7\advance\dimen4-\dimen5 % width of right half
%
\ifPositiveGradient
     \dimen0\dimen5 % use right margin to calculate top margin
     \advance\dimen1-\x@coord\DiagramCellWidth % stick out a lot on the left
     \advance\dimen1 \x@offset\DiagramCellWidth % relative to where?
     \setbox6=\llap{\unhbox6\kern.1\ht2}%
     \setbox7=\rlap{\kern.1\ht2\unhbox7}%
\else
     \dimen0\dimen1 % use left margin to calculate top margin
     \advance\dimen1-\x@offset\DiagramCellWidth % relative to where?
     \setbox7=\llap{\unhbox7\kern.1\ht2}%
     \setbox6=\rlap{\kern.1\ht2\unhbox6}%
\fi
%
\setbox6=\vbox{\box6\kern.1\wd2}\setbox7=\vtop{\kern.1\wd2\box7}%
%
\multiply@{\dimen0}% convert top margin from width to depth
\advance\dimen0-\axisheight\advance\dimen0-\y@offset\DiagramCellHeight
\dimen5-\dimen0 % height of upper tip
\advance\dimen0\dimen6 % depth of lower tip
%
\advance\dimen1.5\dimen3 % adjust left margin for width error
%
% middle disables through
\ifdim\wd3>\z@\ifdim\ht3>-\dp3\@cd@through@false\fi\fi
%
\dimen3\dimen2
\dimen7\dimen2\advance\dimen7\dimen4
\ifvoid3
\else
   \if@cd@through@
   \else
      % calculate x coordinate of intersection with top of middle
      \dimen8\ht3\advance\dimen8-\axisheight\divide@{\dimen8}%
      \at@most{\dimen8}{.5\wd3}% or choose intersection with edge
      %
      % calculate x coordinate of intersection with bottom of middle
      \dimen9\dp3\advance\dimen9\axisheight\divide@{\dimen9}%
      \at@most{\dimen9}{.5\wd3}% or choose intersection with edge
      %
      \ifPositiveGradient
           \advance\dimen2-\dimen9\advance\dimen4-\dimen8 % shorten fillers
      \else\advance\dimen4-\dimen9\advance\dimen2-\dimen8 % appropriately
   \fi\fi
   \advance\dimen3-.5\wd3
\fi
\dimen9=\y@coord\DiagramCellHeight\advance\dimen9-2\DiagramCellHeight
%
%
% make the fillers;
% re-use \dimen2 and \dimen4 as amounts to raise them (instead of their widths)
\if@cd@through@
   \advance\dimen2\dimen4
   \make@line{2}% width \dimen2 using \box2 to make \box2
   \dimen2-\dimen0\advance\dimen2\dp2 % amount to raise it
\else
   \make@line{2}% width \dimen2 using \box2 to make \box2
   \make@line{4}% width \dimen4 using \box4 to make \box4
   \ifPositiveGradient
        \dimen2-\dimen0\advance\dimen2\dp2 % amount to raise left
        \dimen4\dimen5\advance\dimen4-\ht4 % amount to raise right
   \else\dimen4-\dimen0\advance\dimen4\dp4 % amount to raise right
        \dimen2\dimen5\advance\dimen2-\ht2 % amount to raise left
\fi\fi
%
\setbox0=\hbox to\z@{%
% move to left edge
\kern\dimen1
%
% output the left tip
\ifvoid1
\else
   \ifPositiveGradient
        \advance\dimen0-\dp1
        \lower\dimen0
   \else\advance\dimen5-\ht1
        \raise\dimen5
   \fi\rlap{\unhbox1}%
\fi
%
% left filler
\raise\dimen2\rlap{\unhbox2}%
%
% output the middle
\ifvoid3 \else
   \lower.5\dimen9\rlap{\kern\dimen3\unhbox3}%
\fi
%
% labels
\kern.5\dimen7
\lower.5\dimen9\box6
\lower.5\dimen9\box7
\kern.5\dimen7
%
% right filler
\if@cd@through@\else
   \raise\dimen4\llap{\unhbox4}%
\fi
%
% right tip
\ifvoid5 \else
   \ifPositiveGradient
        \advance\dimen5-\ht5
        \raise\dimen5
   \else\advance\dimen0-\dp5
        \lower\dimen0
   \fi\llap{\unhbox5}%
\fi
%
\hss}%
\ht0=\axisheight\dp0=-\ht0\box0 }%
%
%\advance\dimen6.25\dimen8      % amount to raise upper label
%\advance\dimen7-.25\dimen8     % amount to raise lower label
%
%
%
%\setbox0=\hbox{\begin@maths\vcenter{%
%  \kern.9ex                            % space above
%  \hbox{%
%    \kern.4em                          % space on left
%    \count@=0
%    \mv-\ht1\box1                      % left tip
%    \loop % on bits
%    \ifnum\count@<\DiagonalLineSegments
%        \mv\count@\ht2\copy2           % filler
%        \advance\count@1
%    \repeat
%    \mv\count@\ht2\box5                        % right tip
%    \kern.4em                          % space on right
%  }%
%  \kern.9ex                            % space below
%}\end@maths}
%\dimen0=.5\wd0 \ht0\z@ \dp0\z@
% %\kern\dimen0
%\mv.5\wd2\hbox to\z@{\hss\box6\kern.5\ht2}% left label
%\kern-\dimen0
%\box0
%\kern-\dimen0
%\mv-.5\wd2\hbox to\z@{\kern.5\ht2\box7\hss}% right label
% %\kern\dimen0
%}
%
% Count clockwise from NW
% \ifPositiveGradient = \ifodd\diagonal@choice
% \ifClimbing = \ifnum\diagonal@choice<2
\def\NorthWest{\PositiveGradientfalse\Climbingtrue \DiagonalChoice0 }%
\def\NorthEast{\PositiveGradienttrue \Climbingtrue \DiagonalChoice1 }%
\def\SouthWest{\PositiveGradienttrue \Climbingfalse\DiagonalChoice3 }%
\def\SouthEast{\PositiveGradientfalse\Climbingfalse\DiagonalChoice2 }%
%
%
%
%=======================================================================%
%                                                                       %
%       (17) STRETCHABLE DIAGONALS                                      %
%                                                                       %
%=======================================================================%
%
% \missive at any point in the diagram text delivers the text to \cell@missive,
% which is called during \reformat@cell
%
% \hbox{(missive material)}
%
%\def\missive#1(#2,#3){\vadjust{\hbox{#1}\penalty#3\penalty#2\penalty2}}%
%\def\remissive#1(#2,#3)(#4,#5){\vadjust{%
%        \hbox{\hbox{#1}\penalty#3\penalty#2}%
%        \penalty#5\penalty#4\penalty103}}%
%\def\missivemap#1(#2,#3)(#4,#5){\vadjust{%
%        \hbox{\hbox{#1}\penalty#3\penalty#2}%
%        \penalty#5\penalty#4\penalty104}}%
\def\exec@missive{\vadjust{%
        \cd@num@a\cd@cell
        \advance\cd@num@a\ifPositiveGradient\else-\fi\x@offset\relax
        \cd@num@b\cd@row\advance\cd@num@b-\y@offset\relax
        \hbox{%
            \advance\cd@num@a\ifPositiveGradient-\fi\x@coord
            \advance\cd@num@b\y@coord
            \hbox{%
                \box6 % upper label
                \kern\crab@
                \kern\snake@
                \penalty1 % stops upper label being read as missing lower label
                \box7 % lower label
                \box\z@
            }%
            \penalty\cd@num@a
            \penalty\cd@num@b}%
        \penalty\cd@num@a\penalty\cd@num@b\penalty104}}%
%
\def\over@print#1{%
\relax % if case we're the first thing in a cell
%\ifmmode
    \vadjust{%
       \hbox@maths{#1}%
       \penalty\cd@cell
       \penalty\cd@row
       \penalty\tw@
    }%
%\else\cd@warning{mis-placed over-print ignored}% removed 15.4.95
%\fi
}%
%
% handle the missives
% \cd@penalty contains the code number, \box\z@ the missive material
% (note that we are currently in unrestricted horizontal mode,
% inside a paragraph in the main vertical list)
\def\cell@missive{%
%\expandafter\message{missive type \the\cd@penalty\space
%   received at (\the\cd@row,\the\cd@cell)\new@line}%
\ifcase \cd@penalty
        % 0: unused
\or     % 1: was used to mark an ordinal row of the matrix
\or     % 2: simple overprint
        %\message{overprint}%
        \output@cell{.5\wd0}{\box0}{.5\wd0}\z@%
\or     % 3: indirected overprint
        \unhbox\z@\setbox\z@\lastbox\output@cell{.5\wd0}{\box0}{.5\wd0}\z@
        \unpenalty\unpenalty\setbox\z@\lastbox
\or     % 4: draw diagonal
        \missive@diagonal
\else   % 100n+m: collect profiles of n more points and execute case m
        \advance\cd@penalty-100
        \ifnum\cd@penalty<\z@ \cd@shouldnt B\fi % unknown missive code
        \setbox\z@\hbox{%
                % save the profile of the current cell
                \kern\left@width
                \copy\object@profile
                \kern\right@width
                % and its coordinates
                \cd@num@a\cd@top\advance\cd@num@a-\cd@row\penalty\cd@num@a
                \cd@num@a\cd@cell\advance\cd@num@a-\cd@left\penalty\cd@num@a
                % at the front of the missive material
                \unhbox\z@
                % removing the coordinates of the next cell to visit
                \global\cd@num@g\lastpenalty\unpenalty% its row number
                \global\cd@num@h\lastpenalty\unpenalty}% its column number
        % send it there
        \cd@num@a-\cd@num@g\cd@num@b\cd@num@h
        \resend@missive
\fi}%
%
\def\missive@diagonal{%
%\global\@need@PS@lib@true % 12.7.94 deleted 6.10.2001
\unhbox\z@
\setbox\z@\lastbox
%
% get missive data
\cd@num@a\lastpenalty\unpenalty\advance\cd@num@a\cd@left@donat  % column no.
\cd@num@b\cd@top\advance\cd@num@b-\lastpenalty\unpenalty        % row no.
\dimen1\lastkern\unkern % right width
\setbox 3\lastbox % profile
\dimen0\lastkern\unkern % left width
%
\setbox0=\hbox to\z@{%
%
% get the arrow and the labels
\unhbox0\setbox0\lastbox
\setbox7\lastbox % lower label (\ifPositiveGradient right \else left)
\unpenalty
\snake@\lastkern\unkern
\crab@\lastkern\unkern
\setbox6\lastbox % upper label (\ifPositiveGradient left \else right)
%
% calculate \dimen7=unsigned width of diagonal map 14.7.94
\dimen7\column@placing\advance\dimen7-\wd\cd@num@a
\ifdim\dimen7<\z@
     \PositiveGradienttrue
     \multiply\dimen7\m@ne
     \let\mv\empty
\else\PositiveGradientfalse
     \def\mv{\raise\ht1}%
     \kern-\dimen7
\fi
%
% calculate \dimen6=height of diagonal map 10.7.94
\ifnum\cd@num@b>\cd@row
        \dimen6\completed@depth
        \advance\dimen6-\ht\cd@num@b
\else   \dimen6\z@
\fi
%
%\expandafter\message{(\the\dimen7,\the\dimen6)}%
% \dimen6=ht=\numerator@ \dimen7=dp=\denominator@ \dimen2=hypotenuse
\stretch@PS@diagonal
\rotate@box@z
%
% get these out of the way of \set@fraction
\setbox1\null\ht1\dimen6\wd1\dimen7
%
% denominator for sine/cosine is hypotenuse
\dimen7\dimen2
%
% cosine \cd@num@a/\cd@num@b
\dimen6\wd1 \set@fraction\cd@num@a\numerator@\cd@num@b\denominator@
%
% sine = \numerator@/\denominator@
\dimen6\ht1 \set@fraction
%
% use \box2 for position of middle
\setbox2\null
\divide\dimen2\tw@
\advance\dimen2\snake@ % snake to right
\multiply@@{\dimen2}\wd2\dimen2 % the width
%
\dimen0.5\dimen7
\advance\dimen0\ifPositiveGradient\else-\fi\snake@ %  snake up or down
\multiply@{\dimen0}%
\advance\dimen0-\axisheight % adjustment for maths axis
\ht2\dimen0
%
% crab adjustment (don't adjust for maths axis here)
\dimen0\crab@\multiply@@{\dimen0}\advance\dimen0\ht2\ht2\dimen0
\dimen0\ifPositiveGradient-\fi\crab@\multiply@{\dimen0}%
\advance\dimen0\wd2\wd2\dimen0
%
%
%
% use \box4 for amount by which to shift labels away from shaft
% this should agree with \baselikeskip in \label@horiz
% and the kerning of labels away from vertical arrows
\setbox4\null
\dimen0 .6\@em\multiply@@{\dimen0}\ht4\dimen0
\dimen0 .2\@em\multiply@{\dimen0}\wd4\dimen0
%
% local to this box:
%           positive gradient  |  negative gradient
% \box0     the horizontal arrow to be stretched
% \box1     vector between the centres of the cells which the arrow links
% \box2     position of middle
% \box3     profile
% \box4     amount by which to shift labels away from shaft
% \box6     upper left label   |  upper right label
% \box7     lower right label  |  lower left label
% \dimen0
% \dimen1
% \dimen2   hypotenuse
% \dimen3   unsigned width of arrow
% \dimen4   snake correction for length of label
% \dimen5   scratch
% \dimen6   height of arrow
% \dimen7   hypotenuse
%
% upper label
\dimen0\wd2
\ifvoid6\else
    \dimen1\ht4
    %\iftrue
    %   \advance\dimen1\axisheight % try locating by maths axis
    %   \ifdim\dimen1<\dp6\dimen1\dp6\fi % but at least depth
    %\fi % instead of base
    \advance\dimen1\ht2
    \correct@for@width 6+-%   \dimen4 = .5\wd6 * \dimen3 / \dimen7
    \raise\dimen1\rlap{%
    \ifPositiveGradient
         \advance\dimen0-\wd6\advance\dimen0-\wd4 % left
    \else\advance\dimen0\wd4 %right
    \fi
    \kern\dimen0\box6}%
\fi
%
% lower label
\dimen0\wd2
\ifvoid7\else
    \dimen1\ht4
    %\iftrue
    %    \advance\dimen1\axisheight % try locating by maths axis
    %    \ifdim\dimen1<\ht7\dimen1\ht7\fi % but at least height
    %\else
    %    \advance\dimen1\ht7 % instead of the top of the label box
    %\fi
    \advance\dimen1-\ht2
    \correct@for@width 7-+%   
    \lower\dimen1\rlap{%
    \ifPositiveGradient
         \advance\dimen0\wd4 %right
    \else\advance\dimen0-\wd7\advance\dimen0-\wd4 % left
    \fi
    \kern\dimen0\box7}%
\fi
%
% the arrow
\mv\box0\hss
}%
\ht0\z@\dp0\z@
%\output@cell{left width}{box}{right width}{raise}
\output@cell{\z@}{\box\z@}{\z@}{\axisheight}%
}%
%
\def\correct@for@width#1#2#3{% \dimen4 = .3\wd#1 * \dimen3 / \dimen7
    %
    % \dimen4 = effective half-width
    \dimen4.5\wd#1
    %\ifdim\dimen4<.5\@em\dimen4.5\@em\fi % unform correction for small labels
    \ifdim\dimen4>.25\dimen7\dimen4=.25\dimen7\fi % cut-off for big ones
    \ifdim\dimen4>\@em
        \dimen4.4\dimen4 % reduce the correction for biggish ones
        \advance\dimen4.6\@em % but make it continuous !
    \fi
    %
    % the projection onto the shaft of the effective half-width
    \multiply@@{\dimen4}%
    %
    % un-correct for the projection onto the shaft of the axis height
    \dimen5\axisheight\multiply@{\dimen5}\advance\dimen4-\dimen5
    %
    % horizontal adjustment: apply *another* cosine factor
    \dimen5\dimen4\multiply@@{\dimen5}%
    \advance\dimen0\ifPositiveGradient#2\else#3\fi\dimen5
    %
    % vertical adjustment: apply sine factor
    \multiply@{\dimen4}\advance\dimen1\dimen4
}
%
%
%=======================================================================%
%                                                                       %
%       (18) POSTSCRIPT AND TPIC ARROWS                                 %
%                                                                       %
%=======================================================================%
%
% from dvips.tex: (Rokicki)
%       \def\rotninety{\special{ps:currentpoint currentpoint translate 90
%          rotate neg exch neg exch translate}}%
%       \font\huge=cmbx10 at 14.4truept
%       \setbox0=\hbox to0pt{\huge A\hss}%
%       \vskip16truept
%       \centerline{%
%         \copy0
%         \special{ps:gsave}%
%         \rotninety\copy0
%         \rotninety\copy0
%         \rotninety\box0
%         \special{ps:grestore}}%
%       \vskip16truept
% prints something like
%       <A
%       V>
% except that all four characters are A from cmbx10.
%
% from rotate.tex: (Rokicki again)
%   These macros allow you to rotate or flip a \TeX\ box.  Very useful for
%   sideways tables or upsidedown answers.
%
%   To use, create a box containing the information you want to rotate.
%   (An hbox or vbox will do.)  Now call \@rotr\boxnum to rotate the
%   material and create a new box with the appropriate (flipped) dimensions.
%   \@rotr rotates right, \@rotl rotates left, \@rotu turns upside down, and
%   \@rotf flips.  These boxes may contain other rotated boxes.
%
%\newdimen\@rotdimen
%\newbox\@rotbox
%
% idea: circular arcs
% ask Rokicki about portability
% idea; collect PS definitions at top of diagram \vbox
%
%\def\@vspec#1{\special{ps:#1}}%  passes #1 verbatim to the output
%\def\@rotstart#1{\@vspec{gsave currentpoint currentpoint translate
% #1 neg exch neg exch translate}}% #1 can be any origin-fixing transformation
%\def\@rotfinish{\@vspec{currentpoint grestore moveto}}% gets back in synch
%
\def\expanded@ps@special#1{\expandafter\verbatim@ps@special{#1}}%
\cd@first@use\using@ps{output is PostScript dependent}%
%
\def\def@ps@turn{%\using@ps
  \verbatim@ps@special{%
    /bturn {%ascii                      % x y axisht on PS stack
        gsave                           % save graphics state
        currentpoint                    % push position
                        %#### 0 4 1 roll translate % fulcrum at axis height
        currentpoint translate          % move origin there
        4 2 roll neg exch atan rotate   % rotate baseline
                % dvips doesn't know we've changed the coordinate system, so
        neg exch neg exch translate     % move origin back
        } def
    /eturn {currentpoint grestore moveto} def}}%ascii
\def\do@eturn{\relax\if@pdf@\pdf@literal{Q}\else\verbatim@ps@special{eturn}\fi}
%
%\def\diagonal@box(#1,#2)#3{%ascii   COMPLETELY OBSOLETE - NO PDF VERSION
%  \global\@need@PS@lib@true     % define PS commands if necessary
%  {\dimen0=#1\relax
%   \dimen1=#2\relax
%               \dimen4=\axisheight
%                       \raise\dimen4 %#### would prefer PS to do this
%  \hbox{\expanded@ps@special{%
%       \dim@in@pts{\dimen0}\space % x (could use number of cells instead)
%       \dim@in@pts{\dimen1}\space % y
%                       %#### \dim@in@pts{\dimen4} \space % axis height
%       bturn}%
%               \Pythagorean@sum        %\dimen2:=sqrt((\dimen0)^2+(\dimen1)^2)
%                       \lower\dimen4 %#### would prefer PS to do this
%               \hbox to\dimen2{#3}%    % output the text
%       \do@eturn}%  \verbatim@ps@special{eturn}}%
%}}%
%
% *********** TPIC \special commands *************
%
%       see contrib/Vojta/xdvi/tpic.c aston/latex/contrib/eepic/eepic.sty
%
% pn <number>                 set pen size in thousandths of an inch (ugh!)
% fp                          flush path
% da <float>                  dashed line
% dt <float>                  dotted line
% pa <number> <number>        add a point to the current path
% ar <n> <n> <n> <n> <f> <f>  draw arc
% ia <n> <n> <n> <n> <f> <f>  draw invisible arc
% sp                          flush spline
% sh                          shade last box circle or ellipse
% wh                          whiten ditto
% bk                          blacken ditto
%
% xdvi doesn't honour the widths of TPIC diagonal lines; dvips does
%
% convert #1 accurately to thousands of an inch in \count@
\def\set@mil#1{\count@#1\relax
\multiply\count@7\advance\count@16577\divide\count@33154 }%
%
\def\expanded@tpic@special#1{\expandafter\special{#1}}
%
%\def\tpic@pen@size{\begingroup\set@mil\intended@breadth
%\expanded@tpic@special{pn \the\count@}\endgroup}%
%
\def\tpic@make@line#1{\setbox#1=\hbox{%
\dimen0\dimen#1\multiply@{\dimen0}\set@mil{\dimen0}% \dimen0=height
\setbox0=\null
\ifPositiveGradient
     \count@-\count@\ht0\dimen0
\else\dp0\dimen0
\fi
\box0 % strut
\cd@num@a\count@
\set@mil\intended@breadth\expanded@tpic@special{pn \the\count@}% set pen size
\expanded@tpic@special{pa 0 0}% start path here
\set@mil{\dimen#1}%
\expanded@tpic@special{pa \the\count@\space\the\cd@num@a}% path to here
\expanded@tpic@special{fp}% flush path
\kern\dimen#1}}%
% 
%
%=======================================================================%
%                                                                       %
%       (19) TRIGONOMETRY                                               %
%                                                                       %
%=======================================================================%
% diagonal of A3 paper is 1027pt
% y=\dimen6 and x=\dimen7 non-negative
% \dimen2=+sqrt(y^2+x^2) to within 0.2% (?)
%
\def\Pythagorean@sum{%
\set@fraction
\begingroup
%
% make y=\dimen2=\dimen7 the larger and x=\dimen6 the smaller
\ifdim  \dimen7<\dimen6
        \dimen2=\dimen6
        \dimen6=\dimen7
        \dimen7=\dimen2
        \count@\numerator@
        \numerator@\denominator@
        \denominator@\count@
\else
        \dimen2=\dimen7
\fi
%
% nothing to do if x=0
\ifdim\dimen6>.01\p@
   \@pyth@sum
   \global\cd@dim@g\dimen0
\else
   \global\cd@dim@g\dimen7
\fi
\endgroup
\dimen2\cd@dim@g
\make@division\num@@{\ifPositiveGradient\else-\fi\dimen6}%
\make@division\mnum@@{\ifPositiveGradient-\fi\dimen6}%
%\make@division\mdenom@@{\ifPositiveGradient-\fi\dimen7}%
\make@division\denom@@{\dimen7}%
}%
%
\def\@pyth@sum{%
\square@fraction% n/d = x^2/y^2
%
\ifdim  \dimen7>1.73\dimen6 % 1.73=sqrt(3)=sec(30deg)
%\then  % y>>x: use power series in u=x^2/2y^2: z=y'(4+4u-2u^2+2u^3) y'=y/4
        \divide\dimen2 4        % x'=\dimen2=y/4
        \multiply\denominator@ 2
\else
        % y~x:  use same series but in u=(x^2-y^2)/4y^2 with y'=y/(sqrt 8)
        \dimen2=0.353553\dimen2         % \dimen2=y'=y/(sqrt 8)
        \advance\numerator@-\denominator@
        \multiply\denominator@ 4
\fi
%
% now have
%       x'=\dimen2<341pt
% calculate
%       z=x'(4+4u-2u^2+2u^3-(5/2)u^4) in \dimen0 as accumulator
%
\dimen0=4\dimen2                % worst case:
 \monomial@  4%         <250pt
 \monomial@{-2}%                < 20pt
 \monomial@  2%         <  3.5pt        typically 0.2pt
 \monomial@{-2.5}%              <  0.66pt       drowned by rounding errors
%\monomial@{3.5}%               <  0.16pt
%\monomial@{-2.375}%    <  0.018pt      pixel at 1200dpi is 0.06pt
%\monomial@{2.0675}%    <  0.0025pt
}%
%
% \dimen0 is the angle using points for degrees
% \dimen1 the hypotenuse
% y=\dimen6 x=\dimen7 returned
%
\def\polar@to@rect{\begingroup
% reduce \dimen0 to between 0 and 45, and \count@ to number of octants
\count@\dimen0
\dimen2 45pt
\divide\count@\dimen2
\ifdim\dimen0<\z@\advance\count@\m@ne\fi
\ifodd\count@\advance\count@ 1\@cd@a@true\else\@cd@a@false\fi
\advance\dimen0-\count@\dimen2
\if@cd@a@\multiply\dimen0\m@ne\fi
\ifnum\count@<0 \multiply\count@-7 \fi
%
% save hypotenuse (the first term of cosine)
\dimen3\dimen1
\dimen6\dimen0
\dimen7 3754936sp
\ifdim\dimen0<6\p@\def\max@fraction{4000}\fi
\set@fraction % \numerator@/\denominator@ is angle in radians
%
% set first term of sine
\dimen2\dimen3\multiply@{\dimen2}%
%
% calculate multiplier: u=-x^2/6 where x is angle in radians
% not too good for cosines of angles between 1 and 4 degrees.
\square@fraction
\multiply\denominator@-6
%
% compute sin x = x-x^3/6+x^5/120 = x (1+u+(0.3)u^2)
\dimen0\dimen2
\monomial@ 1%
\monomial@{0.3}%
\dimen1\dimen0
%
% compute cos x = 1-x^2/2+x^4/24-x^6/720 = 1+3u+(1.5)u^2+(0.3)u^3
\dimen2\dimen3
\dimen0\dimen3
\monomial@ 3%
\monomial@{1.5}%
\monomial@{0.3}%
%
% swap sin/cos and change sign appropriately
\divide\count@2
\if@cd@a@\multiply\dimen1\m@ne\fi
\ifodd\count@\dimen2\dimen1\dimen1\dimen0\dimen0-\dimen2 \fi
\divide\count@2
\ifodd\count@\multiply\dimen0\m@ne\multiply\dimen1\m@ne\fi
%
% export
\global\cd@dim@g\dimen0\global\cd@dim@h\dimen1\endgroup
\dimen6\cd@dim@g\dimen7\cd@dim@h}%
%
% ****************** continued fraction approximation ********************
%
% set \numerator@/\denominator@ to nearest rational to \dimen6/\dimen7
% with both at most \max@fraction
\def\default@max@fraction{255}\let\max@fraction\default@max@fraction
\def\set@fraction{\begingroup
\ifdim\dimen7<\dimen6
  \dimen9\dimen7\dimen7\dimen6\dimen6\dimen9\@cd@a@true
\else
  \@cd@a@false
\fi
\dimen2\z@    \dimen3\one@sp            % b=0 b'=1 initialisation
\dimen4\one@sp\dimen0\z@                % c=1 c'=0
\dimen8=\max@fraction\one@sp            % d tolerance
\do@cont@frac
\global\cd@num@g\dimen\if@cd@a@ 0\else3\fi
\global\cd@num@h\dimen\if@cd@a@ 3\else0\fi
\endgroup
\numerator@\cd@num@g\denominator@\cd@num@h}%
%
\def\do@cont@frac{%
\count@\dimen6
\divide\count@\dimen7                   % u  := a/a'  new quotient
\advance\dimen6-\count@\dimen7          % a -:= ua'   reduced data
\dimen9\dimen4
\advance\dimen9\count@\dimen0           % c" := c+uc' trial denominator
%
\ifdim\dimen9>\dimen8                   % overflow
   \cont@frac@done
\else
   \cont@frac@swap      % b,b':=b',ub'+b; c,c':=c',c"
   \ifdim\dimen6>\z@    % if it's spot on return, else
       \dimen9\dimen6   % a,a':=a',a
       \dimen6\dimen7
       \dimen7\dimen9
       \expandafter\expandafter\expandafter
       \do@cont@frac    % carry on
\fi\fi}% result ends up as b'/c'
%
% When we've gone over the limit, but not twice, there's still a better
% approximation than the previous one, obtained by adjusting the quotient.
%
% Suppose b/c b'/c' and (b"=ub'+b)/(c"=uc'+c) are successive continued
% fraction approximants to r with c'<=d<c". Then any rational number p/q
% between b/c and b'/c' is at least as far away from r as p'/q where p'=vb'+b
% and q=vc'+c. We want v to be an integer such that q<=d. Is this closer
% than b/c (on the other side)? Yes if (p'/q) is less than twice as far from
% b/c as r is, which reduces to (a/a')<2v+(c/c'). This happens if u<2v.
% (It also happens if u=2v and a"c'<a'c, equivalently ac'<a'c", but we ignore
% this case.)
%
% If c'=0 d<c"<=2d then 1/d is the best approximant.
%
\def\cont@frac@done{%
\ifdim\dimen0=\z@          %
   \ifdim\dimen9<2\dimen8  % if c'=0 (so b'=1) and d<=c"<2d
      \dimen0\dimen8       %    choose d/1
   \fi
\else
   \advance\dimen8-\dimen4 
   \divide\dimen8\dimen0            % v := (d-c)/c' smaller quotient
   \ifdim\count@\one@sp<2\dimen8    % if u<2v there's a better approximation:
      \count@\dimen8
      \dimen9\dimen4
      \advance\dimen9\count@\dimen0 % c" := c+vc' recalculate denominator
      \cont@frac@swap               % and numerator, and swap
\fi\fi
}%
%
\def\cont@frac@swap{%
\dimen4\dimen0
\dimen0\dimen9
\advance\dimen2\count@\dimen3
\dimen9\dimen2
\dimen2\dimen3
\dimen3\dimen9
%\n\dimen3 \m\dimen0 \expandafter\message{\the\n/\the\m}%
}%
%
% \dimen2 *:= \numerator@/\denominator@
% \dimen0 +:= (#1)*(\dimen2)
\def\monomial@#1{%
\multiply@{\dimen2}%
\advance\dimen0 #1\dimen2
}%
%
\def\multiply@ #1{\divide#1\denominator@\multiply#1\numerator@}%
\def\multiply@@#1{\divide#1\cd@num@b\multiply#1\cd@num@a}%
\def\divide@   #1{\divide#1\numerator@  \multiply#1\denominator@}%
%
\def\square@fraction{%
   \dimen6\numerator@  \one@sp\multiply\dimen6\numerator@
   \dimen7\denominator@\one@sp\multiply\dimen7\denominator@
   \set@fraction}%
%
\def\make@division#1#2{%
   \begingroup
        \dimen@#2\relax
        \loop
           \ifdim\dimen2<.4\maxdimen
               \multiply\dimen2\tw@
               \multiply\dimen@\tw@
        \repeat
        \divide\dimen2\@cclvi
        \divide\dimen@\dimen2\relax
        \multiply\dimen@\@cclvi
        \expandafter\mk@@div\the\dimen@
   \endgroup
   %\expandafter\message{make@division=\div@@}%        
   \let#1\div@@}%
% %% this is a mega-hack for extracting as text the value of a \dimen in points
{\catcode`p=12 \catcode`0=12 \catcode`.=12 \catcode`t=12 
\gdef\mk@@div#1pt{\gdef\div@@{#1}}}%
%
%=======================================================================%
%                                                                       %
%       (20) PDFTEX SUPPORT                                             %
%                                                                       %
%=======================================================================%
%
% See /usr/share/doc/texmf/pdftex/base/example.tex
% or http://www.tug.org/applications/pdftex/
% or ftp://ftp.cstug.cz/pub/tex/local/cstug/thanh/pdftex-testing/latest
%
% \newdimen\d
% \newbox\b
% \def\avoidboxdimen#1{%
%     \setbox\b=\hbox{\box#1}%
%     \wd\b=0pt 
%     \ht\b=0pt
%     \dp\b=0pt
%     \box\b}
% 
% % rotation by `t' degrees counterclockwise is specified as 
% % `cos(t) sin(t) -sin(t) cos(t) 0 0'.
% \def\rotate@pdf{%
%     \vskip\wd0
%     \leftline{\hskip\ht0\hskip\dp0%
%     \pdf@literal{q 0 1 -1 0 0 0 cm}%
%     \avoidboxdimen0%
%     \pdf@literal{Q}}}
%
%=======================================================================%
%                                                                       %
%       (21) ERROR RECOVERY                                             %
%                                                                       %
%=======================================================================%
%
% Would be nice if we could get the error context to contain EXACTLY the
% information we want to show, in particular the inserted text as the next
% text to be input. [Could use \futurelet to show "to be read again"]
\ifx\errorcontextlines\undefined
\then   \let\no@error@context\relax
\else   \def\no@error@context{\errorcontextlines\m@ne}%
\fi
\ifnum\inputlineno<0
    % null input line strings if the info is not available
    \let\end@at@line\empty
    \let\at@line\empty
    \let\first@occur\relax
    \let\save@begin@at@line\relax
    \let\save@cell@at@line\relax
    \let\make@end@at@line\relax
    \message{! Why not upgrade to TeX version 3? (available since 1990)}%ascii
\else% input line number messages
    \def\at@line{ at line \number\inputlineno}%
    \def\first@occur{ - first occurred}%
    \def\save@begin@at@line{%
        \edef\begin@at@line{\the\inputlineno}%
        \global\let\cell@at@line\begin@at@line
        }%
    \def\begin@at@line{9999}%
    % changed \edef to \xdef 15.4.95
    \def\save@cell@at@line{%
       %\expandafter\message
        %{cell (\the\cd@row,\the\cd@cell) at \cell@at@line--\the\inputlineno}%
       \xdef\cell@at@line{\the\inputlineno}%
    }%
    \def\cell@at@line{\begin@at@line}%
    \def\make@end@at@line{%
      \ifnum\begin@at@line<\inputlineno
         \edef\end@at@line{\space at lines \begin@at@line--\the\inputlineno}%
      \else\edef\end@at@line{\at@line}%
      \fi}%
\fi
\let\end@at@line\empty
%
%
% first pass error (so can stop and give help)
\def\cd@error#1#2{\no@error@context
\errhelp=#2\expandafter\errmessage{\cd@name: #1}}%
%
% second pass error (too late to correct it)
\def\cd@refmt@error#1{\begingroup
    \expandafter\message{! \cd@name: #1\end@at@line}%ascii
    \ifnum\cd@top>\cd@row
    \ifnum\cd@bottom>\cd@row\else
    \ifnum\cd@left>\cd@cell\else
    \ifnum\cd@right>\cd@cell
       % these are ok 'cos we're in a \begingroup...\endgroup
       \advance\cd@top-\cd@row
       \advance\cd@cell-\cd@left
       \advance\cd@cell 1\relax
       \expandafter\message{! (error detected at row \the\cd@top, % ascii
       column \the\cd@cell, but probably caused elsewhere)}% ascii
    \fi\fi\fi\fi
\endgroup}%
%
% warning
\def\cd@warning#1{{%
   \expandafter\message{\cd@name\space Warning: #1\at@line}%
   }}%
%
\def\cd@obs@msg#1#2{\cd@warning{#1 \string#2 is obsolete\first@occur}}%
\def\cd@obs@dim#1{\cd@obs@msg{Dimension}{#1}%
 \glet#1\cd@obs@dimq\cd@obs@dimq}%
\def\cd@obs@dimq{\cd@dim@a=}%
\def\cd@obs@count#1{\cd@obs@msg{Count}{#1}\glet#1\@obs@countq\@obs@countq}%
\def\@obs@countq{\count@=}%
%
\def\HorizontalMapLength{\cd@obs@dim\HorizontalMapLength}%
\def\VerticalMapHeight{\cd@obs@dim\VerticalMapHeight}%
\def\VerticalMapDepth{\cd@obs@dim\VerticalMapDepth}%
\def\VerticalMapExtraHeight{\cd@obs@dim\VerticalMapExtraHeight}%
\def\VerticalMapExtraDepth{\cd@obs@dim\VerticalMapExtraDepth}%
\def\DiagonalLineSegments{\cd@obs@count\DiagonalLineSegments}%
%
%\def\spew#1{%
%\expandafter\message{#1}%
%\message{hbox0: remainder of line}\showbox0
%\message{vbox1: remainder of matrix}\showbox1
%\message{hbox2: donations from below}\showbox2
%\message{hbox3: completed verticals}\showbox3
%\message{hbox4: completed row}\showbox4
%\message{hbox5: donations upwards}\showbox5
%\message{hbox6: scratch}\showbox6
%\message{box7: donation from left}\showbox7
%\message{box8: donation from below}\showbox8
%\message{box9: scratch}\showbox9
%\message{current lists}\showlists
%}%
%
% check whether \font\tenln=line10 is really there
\ifx\tenln\nullfont
  \cd@first@use\no@tenln{\LaTeX@name\space diagonal line and arrow font
      not available}%
\else
  \let\no@tenln\relax
\fi
%
% #1=have, #2=need,
% #6=accumulator, #7=do if OK  (\cd@dim@a,\count@ scratch)
%
% #1=h,v,l,r; #2=have; #3=need; #4=message; #5=from row/col; #6=to row/col
\def\more@dim#1#2<#3:#4:#5#6{%
\begingroup
\cd@dim@b#3\relax\advance\cd@dim@b-#2\relax
\ifdim.1em<\cd@dim@b % ignore small amounts
    \cd@num@a#5\relax
    \cd@num@b#6\relax
    \ifnum\cd@num@a<\cd@num@b
        \count@\cd@num@b\advance\count@-\cd@num@a
       \cd@refmt@error{#4 by \the\cd@dim@b}%
        \if#1v%
                \let\next\vert@extra
                \edef\tmp{\the\cd@num@a--\the\cd@num@b,\the\cd@cell}%
        \else   % horizontal: correction for \across
                \advance\count@\count@
                \if#1l\advance\count@-\across@cells
                \else\if#1r\advance\count@\across@cells
                \fi\fi
                \advance\cd@dim@b\cd@dim@b
                \let\next\horiz@extra
                \edef\tmp{\the\cd@row,\the\cd@num@a--\the\cd@num@b}%
        \fi
%\cd@refmt@error
%{#4 by \the\cd@dim@b\space at (\tmp)-(\the\cd@top,\the\cd@left)}%
        \divide\cd@dim@b\count@
        \ifdim\next<\cd@dim@b\global\next\cd@dim@b\fi
\fi \fi
\endgroup             
}%
%
%
%================== erroneous occurences of \enddiagram ================
%
% \diagram\egroup\enddiagram (where \enddiagram may be inserted by \par)
% still causes trouble. same may also apply to \pile
%
% check no of lines since beginning of cell?
\new@if\if@end@diagram@ok@\@end@diagram@ok@true\@end@diagram@ok@false %global
\new@help\see@above{See the message above.}%
\new@help\par@not@allowed{Perhaps you've forgotten to end the diagram 
  before resuming the text, in\new@line which case some garbage may be added
  to the diagram, but we should be ok now.\new@line Alternatively you've
  left a blank line in the middle - TeX will now complain\new@line that the
  remaining \and@name s are misplaced - so please use comments for layout.}%
\new@help\fated@enddiagram{You have already closed too many brace pairs or
  environments; an \end@diagram@name\new@line command was (over)due.}%ascii
\new@help\pair@diagram@end{\diagram@name\space and \end@diagram@name\space
  commands must match.}%
%
%       (TeXbook p205) any runaway argument ended by \par is discarded
%       and replaced by \par alone;
%
% Blank line in the middle of a diagram.
% Ignore (with message) if interactive (\inputlineno=0)
\def\par@enddiagram{%
\ifnum  \inputlineno=0
%\then  \expandafter\interactive@par@endcd
\else   \expandafter\@par@enddiagram
\fi}%
%
\def\@par@enddiagram{%
\end@label              % terminate label
\enddiagram@endpile     % and \pile if necessary
\crcr                   % terminate row of matrix
\cd@error{missing \end@diagram@name\space inserted before \par@name -
type "h"}%ascii
\par@not@allowed
\enddiagram             % terminate diagram
\make@found@end@diagram\par@name
\par}%          % try again to end the paragraph, or whatever we wanted to do
%
% No point - can't seem to suppress the similar (vir)TeX message.
%\def\interactive@par@endcd{\expandafter\message
%{Please type a diagram command or say `\end@diagram@name'}}%
%
\def\make@found@end@diagram#1{%
\edef\enddiagram{\noexpand\found@end@diagram{#1\at@line}}}%
%
\def\found@end@diagram#1{%
\cd@error{\end@diagram@name\space (anticipated by #1) ignored}%ascii
\see@above\let\enddiagram\misplaced@enddiagram}%
%
\def\misplaced@enddiagram{%
\cd@error{misplaced \end@diagram@name\space ignored}\pair@diagram@end}%
%
\def\do@fated@enddiagram{%
\cd@error{missing \end@diagram@name\space inserted.}\fated@enddiagram
\make@found@end@diagram{closing group}}%
%
% Support for LaTeX2e \usepackage options.
% We don't use the official mechanism (\DeclareOption{name}{code}) because
% it deletes the code and does not handle our name=value construct.
% Instead we pick up everything using the LaTeX2e default option mechanism,
% which provides the user's options to us one by one as \CurrentOption.
% This doesn't pick up the \documentclass options.
% 
\ifx\DeclareOption\undefined\else\ifx\DeclareOption\@notprerr\else
   \DeclareOption*{%ascii
      \let\after@opt@arg\relax\let\next@opt@arg\relax
      \expandafter\@@getoptarg\CurrentOption,%
   }%
   %\AtEndOfPackage{%
       %\@was@pair@false
       %\ProcessOptions\relax
       %\if@was@pair@\bad@pair@opt\fi
   %}%
\fi\fi
%
%%======================================================================%
%%                                                                      %
%%      (22) AUXILLARY MACROS FOR ADJUSTMENT OF COMPONENTS              %
%%                                                                      %
%%======================================================================%

%% NOTE: The recommended way of defining arrow commands is now
%%      \newarrow{Name}{tail}{filler}{middle}{filler}{head}
%% which defines \rName, \lName, \dName and \uName using arrow parts which
%% have themselves previously been defined using the commands
%% \newarrowtail, \newarrowfiller, \newarrowmiddle and \newarrowhead.

%% The components \rhvee etc have been retained for the time being, as an
%% intermediate stage and to continue to support the old \HorizontalMap and
%% \VerticalMap commands, but you should not rely on the continued existence
%% of these macros.

%% The various components usually need some correction
%% - longitudinally, ie to prevent gaps and overprints with the shaft,
%% - transversally,  ie to prevent "steps" in the junction with the shaft.
%% The former can be done safely ad hoc, eg with \mkern1mu.
%% The latter are now done with the macros \scriptaxis, \boldscriptaxis,
%% \shifthook and \raisehook, which include pixel corrections.

%% Please note that these and the other auxillary macros which follow are
%% interim. When it becomes clear exactly what kinds of adjustments are
%% needed for characters, this job will be done by a suitable extension
%% to the language of \newarrowhead, etc. If you have any other ideas for
%% transformations of general use please tell me.

%% By all means experiment with other characters for arrowheads, but
%% please, in your own interests, do not rely on macros like \rhvee,
%% send me a copy of your definitions for distribution to other users
%% in this file, and keep track of where your efforts get copied so
%% that they can be replaced with the "official" version when it is
%% incorporated.

%% ***** DONT use macros with mangled names like \Cd@gH. *****

\catcode`\$=3 %% make sure that $ means maths-shift
\def\vboxtoz{\vbox to\z@}%% \z@ is in plain TeX and means 0pt
%\def\ulapm#1{\vboxtoz{\vss\hbox{$#1$}\kern\z@}%
%\def\dlapm#1{\vboxtoz{\kern\z@\hbox{$#1$}\vss\kern\z@}%

%% print #1 in \scriptstyle, adjusting for the maths axis height
\def\scriptaxis#1{\@scriptaxis{$\scriptstyle#1$}}%%
\def\ssaxis#1{\@ssaxis{$\scriptscriptstyle#1$}}%%
\def\@scriptaxis#1{%
\dimen0\axisheight\advance\dimen0-\ss@axisheight%
\raise\dimen0\hbox{#1}}%
\def\@ssaxis#1{%
\dimen0\axisheight\advance\dimen0-\ss@axisheight%
\raise\dimen0\hbox{#1}}%

%% Some of the characters would look better in bold since they're
%% taken from sub/superscript fonts; we use LaTeX's \boldmath to
%% do this, defining this to do nothing if it doesn't exist.
%% With the old LaTeX font selection at other than 10pt you may still
%% get nothing happenning.  Also, PK fonts may be missing.
%% If you have problems, DONT use boldhook or boldlittlevee.
\ifx\boldmath\undefined%%
     \let\boldscriptaxis\scriptaxis%%
     \def\boldscript#1{\hbox{$\scriptstyle#1$}}%%
     \def\boldscriptscript#1{\hbox{$\scriptscriptstyle#1$}}%%
\else\def\boldscriptaxis#1{\@scriptaxis{\boldmath$\scriptstyle#1$}}%%
     \def\boldscript#1{\hbox{\boldmath$\scriptstyle#1$}}%%
     \def\boldscriptscript#1{\hbox{\boldmath$\scriptscriptstyle#1$}}%%
\fi

%%  #1= {} or \boldmath; #2= + or -; #3=\subset or \supset
\def\raisehook#1#2#3{\hbox{%
\setbox3=\hbox{#1$\scriptscriptstyle#3$}%% the character to use
\dimen0\ss@axisheight%% \scriptscriptstyle axis height
\dimen1\axisheight\advance\dimen1-\dimen0%% difference in axis heights
\dimen2\ht3\advance\dimen2-\dimen0%%  height of char above axis (half spread)
\advance\dimen2-0.021em% \raisehookfudge used in THM 9.4.2 of my book
%\advance\dimen2-.5\rounded@breadth% (dont) need to adjust for rule thickness
\advance\dimen1 #2\dimen2%% shift = axis_difference +/- half_spread
%\expandafter\message{\the\dimen1}%
\raise\dimen1\box3}}%% print the character
%
%\expandafter\message{\new@line\new@line raisehook fudged by \the\raisehookfudge\new@line\new@line}%
%
%% Mark Dawson suggested using the width
% see sym.mf for MetaFont definitions of \cup and \cap (12u wide)
% subtract 2u from its width to remove the MF-encoded margin 
% also subtract \rounded@breadth to match up the shaft
% except that 2\rounded@breadth seems to work better (9.7.98)
% ptbook+boldmath+box0 gave a strut, so changed to \box1 (9.7.98)
\def\shifthook#1#2#3{% #1= {} or \boldmath; #2= + or -   #3= \cup or \cap
\setbox1=\hbox{#1$\scriptscriptstyle#3$}% the character
\dimen0\wd1\divide\dimen0 12\pixel@round{\dimen0}%%  "u"
\dimen1\wd1\advance\dimen1-2\dimen0
%\advance\dimen1-2\intended@breadth
\advance\dimen1-2\rounded@breadth
\pixel@round{\dimen1}%
\kern#2\dimen1\box1}%% print

%% use the extension font (cmex) for double vertical arrows
% and braces
\def\@cmex{\mathchar"03}%%ascii double quote

%%      ************* P U L L B A C K S ************

%% These will probably be replaced by something less ad hoc
%% in a future version.

\def\make@pbk#1{\setbox\tw@\hbox to\z@{#1}\ht\tw@\z@\dp\tw@\z@\box\tw@}%
\def\overprint@pbk#1{\overprint{\hbox to\z@{#1}}}%
\def\pbk@sh{\kern0.11em}\def\pbk@osh{\kern0.35em}%

%% This is a hack for my book ``Practical Foundations of Mathematics''
%% and WILL NOT BE SUPPORTED --- DO NOT USE IT!
\def\dblvert{\def\pbk@shsh{\kern .5\PileSpacing}}\def\pbk@shsh{}%

\def\SEpbk{\make@pbk{%
\pbk@sh\pbk@shsh
\vrule depth 2.87ex height -2.75ex width 0.95em
\vrule height -0.66ex depth 2.87ex width 0.05em
\hss
}}

\def\SWpbk{\make@pbk{%
\hss
\vrule height -0.66ex depth 2.87ex width 0.05em
\vrule depth 2.87ex height -2.75ex width 0.95em
\pbk@sh\pbk@shsh
}}

\def\NEpbk{\make@pbk{%
\pbk@sh\pbk@shsh
\vrule depth -3.81ex height 4.00ex width 0.95em
\vrule height 4.00ex depth -1.72ex width 0.05em
\hss
}}

\def\NWpbk{\make@pbk{%
\hss
\vrule height 4.00ex depth -1.72ex width 0.05em
\vrule depth -3.81ex height 4.00ex width 0.95em
\pbk@sh\pbk@shsh
}}

%%  Freyd & Scedrov puncture symbol for non-commuting polygon
\def\puncture{{\setbox0\hbox{A}%
  \vrule height.53\ht0 depth-.47\ht0 width.35\ht0
  \kern .12\ht0
  \vrule height\ht0 depth-.65\ht0 width.06\ht0
  \kern-.06\ht0
  \vrule height.35\ht0 depth0pt width.06\ht0
  \kern .12\ht0
  \vrule height.53\ht0 depth-.47\ht0 width.35\ht0
}}%


%% 2-cells: (24.11.95)
%% \NEclck puts a clockwise (ie southeast) arrow to the northwest of cell etc
\def\NEclck{\overprint{\raise2.5ex\rlap{ \pbk@shsh$\scriptstyle\searrow$}}}%%
\def\NEanti{\overprint{\raise2.5ex\rlap{ \pbk@shsh$\scriptstyle\nwarrow$}}}%%
\def\NWclck{\overprint{\raise2.5ex\llap{$\scriptstyle\nearrow$ \pbk@shsh}}}%%
\def\NWanti{\overprint{\raise2.5ex\llap{$\scriptstyle\swarrow$ \pbk@shsh}}}%%
\def\SEclck{\overprint{\lower1ex\rlap{ \pbk@shsh$\scriptstyle\swarrow$}}}%%
\def\SEanti{\overprint{\lower1ex\rlap{ \pbk@shsh$\scriptstyle\nearrow$}}}%%
\def\SWclck{\overprint{\lower1ex\llap{$\scriptstyle\nwarrow$ \pbk@shsh}}}%%
\def\SWanti{\overprint{\lower1ex\llap{$\scriptstyle\searrow$ \pbk@shsh}}}

%%======================================================================%
%%                                                                      %
%%      (23) BITS OF ARROWS                                             %
%%                                                                      %
%%======================================================================%

%%       **********  H E A D S ***********

%% \diagramstyle[heads=xxx] defines {>} as {xxx} where xxx
%% has been defined by \newarrowhead{xxx} and \newarrowtail{xxx}

%% vee head
\def\rhvee{\mkern-10mu\greaterthan}%%
\def\lhvee{\lessthan\mkern-10mu}%%
\def\dhvee{\vboxtoz{\vss\hbox{$\vee$}\kern0pt}}%%
\def\uhvee{\vboxtoz{\hbox{$\wedge$}\vss}}%%
\newarrowhead{vee}\rhvee\lhvee\dhvee\uhvee

%% little vee head
\def\dhlvee{\vboxtoz{\vss\hbox{$\scriptstyle\vee$}\kern0pt}}%%
\def\uhlvee{\vboxtoz{\hbox{$\scriptstyle\wedge$}\vss}}%%
\newarrowhead{littlevee}{\mkern1mu\scriptaxis\rhvee}%
   {\scriptaxis\lhvee}\dhlvee\uhlvee
\ifx\boldmath\undefined%%
   \newarrowhead{boldlittlevee}{\mkern1mu\scriptaxis\rhvee}%
   {\scriptaxis\lhvee}\dhlvee\uhlvee
\else%%
   \def\dhblvee{\vboxtoz{\vss\boldscript\vee\kern0pt}}%%
   \def\uhblvee{\vboxtoz{\boldscript\wedge\vss}}%%
   \newarrowhead{boldlittlevee}{\mkern1mu\boldscriptaxis\rhvee}%
   {\boldscriptaxis\lhvee}\dhblvee\uhblvee%%
\fi

%% curly vee head (uses AMS symbols fonts)
\def\rhcvee{\mkern-10mu\succ}%%
\def\lhcvee{\prec\mkern-10mu}%%
\def\dhcvee{\vboxtoz{\vss\hbox{$\curlyvee$}\kern0pt}}%%
\def\uhcvee{\vboxtoz{\hbox{$\curlywedge$}\vss}}%%
\newarrowhead{curlyvee}\rhcvee\lhcvee\dhcvee\uhcvee

%% double vee head %% will probably be withdrawn later
\def\rhvvee{\mkern-13mu\gg}%% 24.8.92 changed 10mu to 13mu
\def\lhvvee{\ll\mkern-13mu}%% to make rule go through
\def\dhvvee{\vboxtoz{\vss\hbox{$\vee$}\kern-.6ex\hbox{$\vee$}\kern0pt}}%%
\def\uhvvee{\vboxtoz{\hbox{$\wedge$}\kern-.6ex
\hbox{$\wedge$}\vss}}%%
\newarrowhead{doublevee}\rhvvee\lhvvee\dhvvee\uhvvee

%% open and closed triangles (uses AMS symbols fonts)
\def\triangleup{{\scriptscriptstyle\bigtriangleup}}%%
\def\littletriangledown{{\scriptscriptstyle\triangledown}}%% AMS
\def\rhtriangle{\triangleright\mkern1.2mu}%% 29.1.93
\def\lhtriangle{\triangleleft\mkern.8mu}%%
\def\uhtriangle{\vbox{%
   \kern-.2ex % 15.1.93 from -.05ex
   \hbox{$\scriptscriptstyle\bigtriangleup$}%
   \kern-.25ex}}%%
%% Changed \scriptstyle\triangledown to \scriptscriptstyle\bigtriangledown
%% at the suggestion of Martin Hofmann (25.11.92) to avoid using AMS symbols
%% and also for compatibility with upward arrow.
\def\dhtriangle{\vbox{%
     \kern-.28ex % 15.1.93 from -.25
     \hbox{$\scriptscriptstyle\bigtriangledown$}%
     \kern-.1ex}}%% 15.1.93 from -.25ex
\def\dhblack{\vbox{\kern-.25ex\nointerlineskip
     \hbox{$\blacktriangledown$}}}%% AMS
\def\uhblack{\vbox{\kern-.25ex\nointerlineskip
     \hbox{$\blacktriangle$}}}%% AMS
\def\dhlblack{\vbox{\kern-.25ex\nointerlineskip
     \hbox{$\scriptstyle\blacktriangledown$}}}%% AMS
\def\uhlblack{\vbox{\kern-.25ex\nointerlineskip
     \hbox{$\scriptstyle\blacktriangle$}}}%% AMS
\newarrowhead{triangle}\rhtriangle\lhtriangle\dhtriangle\uhtriangle
\newarrowhead{blacktriangle}{\mkern-1mu\blacktriangleright\mkern.4mu}% 29.1.93
     {\blacktriangleleft}\dhblack\uhblack
\newarrowhead{littleblack}{\mkern-1mu\scriptaxis\blacktriangleright}%
     {\scriptaxis\blacktriangleleft\mkern-2mu}\dhlblack\uhlblack

%% LaTeX arrowheads
\def\rhla{\hbox{\setbox0=\lnchar55\dimen0=\wd0%
\kern-.6\dimen0\ht0\z@ % 15.1.93 from -.5; also smashed height
\raise\axisheight\box0\kern.1\dimen0}}%%
\def\lhla{\hbox{\setbox0=\lnchar33\dimen0=\wd0%
\kern.05\dimen0\ht0\z@ % 15.1.93 from -.1; also smashed height
\raise\axisheight\box0\kern-.5\dimen0}}%%
\def\dhla{\vboxtoz{\vss\rlap{\lnchar77}}}%%
\def\uhla{\vboxtoz{\setbox0=\lnchar66 \wd0\z@\kern-.15\ht0\box0\vss}}%% 1/93
\newarrowhead{LaTeX}\rhla\lhla\dhla\uhla

%% double LaTeX arrowheads %% will probably be withdrawn later
\def\lhlala{\lhla\kern.3em\lhla}%%
\def\rhlala{\rhla\kern.3em\rhla}%%
\def\uhlala{\hbox{\uhla\raise-.6ex\uhla}}%%
\def\dhlala{\hbox{\dhla\lower-.6ex\dhla}}%%
\newarrowhead{doubleLaTeX}\rhlala\lhlala\dhlala\uhlala

%% circles % \rho is a Greek letter!
\def\hhO{\scriptaxis\bigcirc\mkern.4mu}
\def\hho{{\circ}\mkern1.2mu}%
\newarrowhead{o}\hho\hho\circ\circ%%
\newarrowhead{O}\hhO\hhO{\scriptstyle\bigcirc}{\scriptstyle\bigcirc}%%

%% crosses
\def\rhtimes{\mkern-5mu{\times}\mkern-.8mu}%
\def\lhtimes{\mkern-.8mu{\times}\mkern-5mu}%
\def\uhtimes{\setbox0=\hbox{$\times$}\ht0\axisheight\dp0-\ht0\lower\ht0\box0 }%
\def\dhtimes{\setbox0=\hbox{$\times$}\ht0\axisheight\box0 }%
\newarrowhead{X}\rhtimes\lhtimes\dhtimes\uhtimes
\newarrowhead+++++%ascii

%% empty head {} is also available

%% Y from stmaryrd (vertical ones still need large adjustment)
% \Yup and \Ydown swapped 26.2.2007
\newarrowhead{Y}{\mkern-3mu\Yright}{\Yleft\mkern-3mu}\Ydown\Yup

%%       **********  H E A D S  with  S H A F T S  ***********

%% little arrow with shaft
\newarrowhead{->}\rightarrow\leftarrow\downarrow\uparrow

%% arrow with double shaft
%%\newarrowhead{=>}\Rightarrow\Leftarrow\Downarrow\Uparrow
\newarrowhead{=>}\Rightarrow\Leftarrow{\@cmex7F}{\@cmex7E}% 16.1.93

%% harpoon with shaft (trailing up/left can be changed to down/right)
% shift verticals to balance! ######## (uses AMS symbols fonts)
\newarrowhead{harpoon}\rightharpoonup\leftharpoonup\downharpoonleft
\upharpoonleft

%% little double-headed arrow with shaft (uses AMS symbols fonts)
\def\twoheaddownarrow{\rlap{$\downarrow$}\raise-.5ex\hbox{$\downarrow$}}%%
\def\twoheaduparrow{\rlap{$\uparrow$}\raise.5ex\hbox{$\uparrow$}}%%
\newarrowhead{->>}\twoheadrightarrow\twoheadleftarrow\twoheaddownarrow
\twoheaduparrow

%%       **********  T A I L S ***********

%% vee tail
\def\rtvee{\greaterthan}%%
\def\ltvee{\mkern-1mu{\lessthan}\mkern.4mu}%% \mkern added 15.1.93
%\def\dtvee{\vboxtoz{\vss\hbox{$\vee$}\kern0pt}}%%
%\def\utvee{\vboxtoz{\hbox{$\wedge$}\vss}}%%
\def\dtvee{\vee}%%
\def\utvee{\wedge}%%
\newarrowtail{vee}\greaterthan\ltvee\vee\wedge

%% little vee tail
\newarrowtail{littlevee}{\scriptaxis\greaterthan}%
   {\mkern-1mu\scriptaxis\lessthan}%
   {\scriptstyle\vee}{\scriptstyle\wedge}%
\ifx\boldmath\undefined
   \newarrowtail{boldlittlevee}{\scriptaxis\greaterthan}%
   {\mkern-1mu\scriptaxis\lessthan}%
   {\scriptstyle\vee}{\scriptstyle\wedge}%
\else
   \newarrowtail{boldlittlevee}{\boldscriptaxis\greaterthan}%
   {\mkern-1mu\boldscriptaxis\lessthan}%
   {\boldscript\vee}{\boldscript\wedge}%
\fi

%% curly vee tail (uses AMS symbols fonts)
\newarrowtail{curlyvee}\succ{\mkern-1mu{\prec}\mkern.4mu}\curlyvee\curlywedge

%% open and closed triangle tails (uses AMS symbols fonts)
\def\rttriangle{\mkern1.2mu\triangleright}%% 29.1.93
\newarrowtail{triangle}\rttriangle\lhtriangle\dhtriangle
\uhtriangle
\newarrowtail{blacktriangle}\blacktriangleright
     {\mkern-1mu\blacktriangleleft\mkern.4mu}%
\dhblack\uhblack
\newarrowtail{littleblack}{\scriptaxis\blacktriangleright\mkern-2mu}%
     {\mkern-1mu\scriptaxis\blacktriangleleft}\dhlblack\uhlblack

%% LaTeX tails
\def\rtla{\hbox{\setbox0=\lnchar55\dimen0=\wd0%
\kern-.5\dimen0\ht0\z@% 19.1.93 smashed height
\raise\axisheight\box0\kern-.2\dimen0}}%%
\def\ltla{\hbox{\setbox0=\lnchar33\dimen0=\wd0\kern-.15\dimen0\ht0\z@
\raise\axisheight\box0\kern-.5\dimen0}}%%
\def\dtla{\vbox{\setbox0=\rlap{\lnchar77}%
\dimen0=\ht0\kern-.7\dimen0\box0\kern-.1\dimen0}}%% 15.1.93 from -.6
\def\utla{\vbox{\setbox0=\rlap{\lnchar66}%
\dimen0=\ht0\kern-.1\dimen0\box0\kern-.6\dimen0}}%%
\newarrowtail{LaTeX}\rtla\ltla\dtla\utla

%% double vee tail %% will probably be withdrawn later
\def\rtvvee{\gg\mkern-3mu}%%
\def\ltvvee{\mkern-3mu\ll}%%
\def\dtvvee{\vbox{\hbox{$\vee$}\kern-.6ex
\hbox{$\vee$}\vss}}%%
\def\utvvee{\vbox{\vss\hbox{$\wedge$}\kern-.6ex
\hbox{$\wedge$}\kern\z@}}%%
\newarrowtail{doublevee}\rtvvee\ltvvee\dtvvee\utvvee

%% double LaTeX tails %% will probably be withdrawn later
\def\ltlala{\ltla\kern.3em\ltla}%%
\def\rtlala{\rtla\kern.3em\rtla}%%
\def\utlala{\hbox{\utla\raise-.6ex\utla}}%%
\def\dtlala{\hbox{\dtla\lower-.6ex\dtla}}%%
\newarrowtail{doubleLaTeX}\rtlala\ltlala\dtlala\utlala

% single dotted line tail (eh?)
%\def\htdot{\mkern3.15mu\cdot\mkern3.15mu}%%
%\def\vtdot{\vbox to 1.46ex{\vss\hbox{$\cdot$}}}

%% bar (as in \mapsto)
\def\utbar{\vrule height 0.093ex depth0pt width 0.4em}%%
\let\dtbar\utbar%%
\def\rtbar{\mkern1.5mu\vrule height 1.1ex depth.06ex width .04em\mkern1.5mu}%%
\let\ltbar\rtbar%%
\newarrowtail{mapsto}\rtbar\ltbar\dtbar\utbar%%
\newarrowtail{|}\rtbar\ltbar\dtbar\utbar%%ascii vertical bar (|)

%% hooks (as in \into): choice of after/above and before/below

\def\rthooka{\raisehook{}+\subset\mkern-1mu}%%
\def\lthooka{\mkern-1mu\raisehook{}+\supset}%%
\def\rthookb{\raisehook{}-\subset\mkern-2mu}%%
\def\lthookb{\mkern-1mu\raisehook{}-\supset}%%

\def\dthooka{\shifthook{}+\cap}%%
\def\dthookb{\shifthook{}-\cap}%%
\def\uthooka{\shifthook{}+\cup}%%
\def\uthookb{\shifthook{}-\cup}%%

\newarrowtail{hooka}\rthooka\lthooka\dthooka\uthooka
\newarrowtail{hookb}\rthookb\lthookb\dthookb\uthookb

\ifx\boldmath\undefined
  \newarrowtail{boldhooka}\rthooka\lthooka\dthooka\uthooka
  \newarrowtail{boldhookb}\rthookb\lthookb\dthookb\uthookb
  \newarrowtail{boldhook}\rthooka\lthooka\dthookb\uthooka
\else
  \def\rtbhooka{\raisehook\boldmath+\subset\mkern-1mu}%%
  \def\ltbhooka{\mkern-1mu\raisehook\boldmath+\supset}%%
  \def\rtbhookb{\raisehook\boldmath-\subset\mkern-2mu}%%
  \def\ltbhookb{\mkern-1mu\raisehook\boldmath-\supset}%%
  \def\dtbhooka{\shifthook\boldmath+\cap}%%
  \def\dtbhookb{\shifthook\boldmath-\cap}%%
  \def\utbhooka{\shifthook\boldmath+\cup}%%
  \def\utbhookb{\shifthook\boldmath-\cup}%%
  \newarrowtail{boldhooka}\rtbhooka\ltbhooka\dtbhooka\utbhooka
  \newarrowtail{boldhookb}\rtbhookb\ltbhookb\dtbhookb\utbhookb
  \newarrowtail{boldhook}\rtbhooka\ltbhooka\dtbhooka\utbhooka
\fi

%% square-ended hooks (used for closed subsets in ``lifting and gluing'')
\def\dtsqhooka{\shifthook{}+\sqcap}%%
\def\dtsqhookb{\shifthook{}-\sqcap}%%
\def\ltsqhooka{\mkern-1mu\raisehook{}+\sqsupset}%%
\def\ltsqhookb{\mkern-1mu\raisehook{}-\sqsupset}%%
\def\rtsqhooka{\raisehook{}+\sqsubset\mkern-1mu}%%
\def\rtsqhookb{\raisehook{}-\sqsubset\mkern-2mu}%%
\def\utsqhooka{\shifthook{}+\sqcup}%%
\def\utsqhookb{\shifthook{}-\sqcup}%%
\newarrowtail{sqhook}\rtsqhooka\ltsqhooka\dtsqhooka\utsqhooka

%% the following seem the better choices at 10pt & 300dpi
\newarrowtail{hook}\rthooka\lthookb\dthooka\uthooka
\newarrowtail{C}\rthooka\lthookb\dthooka\uthooka

%% circles
\newarrowtail{o}\hho\hho\circ\circ%%
\newarrowtail{O}\hhO\hhO{\scriptstyle\bigcirc}{\scriptstyle\bigcirc}%%

%% crosses
\newarrowtail{X}\lhtimes\rhtimes\uhtimes\dhtimes
\newarrowtail+++++%ascii

%% empty tail {} is also available

%% Y from stmaryrd (vertical ones still need adjustment)
\newarrowtail{Y}\Yright\Yleft\Ydown\Yup

%% harpoon with shaft (trailing up/left can be changed to down/right)
% shift verticals to balance! ######## (uses AMS symbols fonts)
\newarrowtail{harpoon}\leftharpoondown\rightharpoondown\upharpoonright
\downharpoonright

%% arrow with double shaft
% 12.8.2009 suggested by Bostjan Gabrovsek
%%\newarrowtail{<=}\Leftarrow\Rightarrow\Uparrow\Downarrow
\newarrowtail{<=}\Leftarrow\Rightarrow{\@cmex7E}{\@cmex7F}% 

%%      **********  F I L L E R S ***********

%% shortening is up to 0.15em=2.7mu horiz and 0.35ex vertically at each end.

%% dot {.}, single rule {-} and empty {} fillers are also available

%% double and triple lines
%%\newarrowfiller{=}==\Vert\Vert%%
\newarrowfiller{=}=={\@cmex77}{\@cmex77}%% 16.1.93
\def\vfthree{\mid\!\!\!\mid\!\!\!\mid}%%ascii
\newarrowfiller{3}\equiv\equiv\vfthree\vfthree

% use the extension font: double vertical="305 or "37F

%% dashed line
\def\vfdashstrut{\vrule width0pt height1.3ex depth0.7ex}%%
\def\vfthedash{\vrule width\intended@breadth height0.6ex depth 0pt}%%
\def\hfthedash{\set@axis\vrule\horizhtdp width 0.26em}%%
\def\hfdash{\mkern5.5mu\hfthedash\mkern5.5mu}%%
\def\vfdash{\vfdashstrut\vfthedash}%%
\newarrowfiller{dash}\hfdash\hfdash\vfdash\vfdash

%%      ************* M I D D L E S ************

% corners for bent lines
%\def\dmcornervert{\vrule width\intended@breadth height\intended@breadth}%%
%\def\rdmcorner{\kern.4em\dmcornervert\vrule width .4em \horizhtdp}%%
%\def\ldmcorner{\vrule width .4em \horizhtdp\dmcornervert\kern.4em}%%
%\def\rumcorner{\kern.4em\vrule width .4em \horizhtdp}%%
%\def\lumcorner{\vrule width .4em \horizhtdp\kern.4em}%%
%\def\urmcorner{\mkern-4.2mu}%%
%\let\drmcorner\urmcorner\let\dlmcorner\urmcorner\let\ulmcorner\urmcorner

%% plus
\newarrowmiddle+++++%ascii

%%      ************* D I A G O N A L S ************

%% simple arrow heads
%%\def\nwhTO{\nwarrow\mkern-1mu}%%
%%\def\nehTO{\mkern-.1mu\nearrow}%%
%%\def\sehTO{\searrow\mkern-.02mu}%%
%%\def\swhTO{\mkern-.8mu\swarrow}%%


%%======================================================================%
%%                                                                      %
%%      (24) ARROW COMMANDS                                             %
%%                                                                      %
%%======================================================================%

%% change to \iftrue to get mixed heads
\iffalse%%
\newarrow{To}----{vee}%%
\newarrow{Arr}----{LaTeX}%%
\newarrow{Dotsto}....{vee}%%
\newarrow{Dotsarr}....{LaTeX}%%
\newarrow{Dashto}{}{dash}{}{dash}{vee}%%
\newarrow{Dasharr}{}{dash}{}{dash}{LaTeX}%%
\newarrow{Mapsto}{mapsto}---{vee}%%
\newarrow{Mapsarr}{mapsto}---{LaTeX}%%
\newarrow{IntoA}{hooka}---{vee}%%
\newarrow{IntoB}{hookb}---{vee}%%
\newarrow{Embed}{vee}---{vee}%%
\newarrow{Emarr}{LaTeX}---{LaTeX}%%
\newarrow{Onto}----{doublevee}%%
\newarrow{Dotsonarr}....{doubleLaTeX}%%
\newarrow{Dotsonto}....{doublevee}%%
\newarrow{Dotsonarr}....{doubleLaTeX}%%
\else%%
\newarrow{To}---->%%
\newarrow{Arr}---->%%
\newarrow{Dotsto}....>%%
\newarrow{Dotsarr}....>%%
\newarrow{Dashto}{}{dash}{}{dash}>%%
\newarrow{Dasharr}{}{dash}{}{dash}>%%
\newarrow{Mapsto}{mapsto}--->%%
\newarrow{Mapsarr}{mapsto}--->%%
\newarrow{IntoA}{hooka}--->%%
\newarrow{IntoB}{hookb}--->%%
\newarrow{Embed}>--->%%
\newarrow{Emarr}>--->%%
\newarrow{Onto}----{>>}%%
\newarrow{Dotsonarr}....{>>}%%
\newarrow{Dotsonto}....{>>}%%
\newarrow{Dotsonarr}....{>>}%%
\fi%%

\newarrow{Implies}===={=>}%% minimum cell height 9.5pt
\newarrow{Project}----{triangle}%%
\newarrow{Pto}----{harpoon}%% partial function
\newarrow{Relto}{harpoon}---{harpoon}%% binary relation

\newarrow{Eq}=====%%
\newarrow{Line}-----%%
\newarrow{Dots}.....%%
\newarrow{Dashes}{}{dash}{}{dash}{}%%

%% square hooked arrow (used in my ``gluing and lifting'' paper)
\newarrow{SquareInto}{sqhook}--->

%% braces and parentheses
%% \newarrow gives inappropriate directions, so we change the names
%% the vertical filler is too far to the right; horizontal too high
%% the vertical middles are too low with midvshaft
%% maybe we'll add square brackets and the integral sign one day
\newarrowhead{cmexbra}{\@cmex7B}{\@cmex7C}{\@cmex3B}{\@cmex38}%%
\newarrowtail{cmexbra}{\@cmex7A}{\@cmex7D}{\@cmex39}{\@cmex3A}%%
\newarrowmiddle{cmexbra}{\braceru\bracelu}{\bracerd\braceld}%
{\vcenter{\hbox@maths{\@cmex3D\mkern-2mu}}}%% right
{\vcenter{\hbox@maths{\mkern 2mu\@cmex3C}}}%% left
\newarrow{@brace}{cmexbra}-{cmexbra}-{cmexbra}%% braces
\newarrow{@parenth}{cmexbra}---{cmexbra}%% straight parentheses
\def\rightBrace{\d@brace[thick,cmex]}%%ASCII square brackets []
\def\leftBrace {\u@brace[thick,cmex]}%%ASCII square brackets []
\def\upperBrace{\r@brace[thick,cmex]}%%ASCII square brackets []
\def\lowerBrace{\l@brace[thick,cmex]}%%ASCII square brackets []
\def\rightParenth{\d@parenth[thick,cmex]}%%ASCII square brackets []
\def\leftParenth {\u@parenth[thick,cmex]}%%ASCII square brackets []
\def\upperParenth{\r@parenth[thick,cmex]}%%ASCII square brackets []
\def\lowerParenth{\l@parenth[thick,cmex]}%%ASCII square brackets []

%% synonyms for reverse compatibility

\let\uFrom\uTo%%
\let\lFrom\lTo%%
\let\uDotsfrom\uDotsto%%
\let\lDotsfrom\lDotsto%%
\let\uDashfrom\uDashto%%
\let\lDashfrom\lDashto%%
\let\uImpliedby\uImplies%%
\let\lImpliedby\lImplies%%
\let\uMapsfrom\uMapsto%%
\let\lMapsfrom\lMapsto%%
\let\lOnfrom\lOnto%%
\let\uOnfrom\uOnto%%
\let\lPfrom\lPto%%
\let\uPfrom\uPto%%

\let\uInfromA\uIntoA%%
\let\uInfromB\uIntoB%%
\let\lInfromA\lIntoA%%
\let\lInfromB\lIntoB%%
\let\rInto\rIntoA%%
\let\lInto\lIntoA%%
\let\dInto\dIntoB%%
\let\uInto\uIntoA%%
\let\ruInto\ruIntoA%%
\let\luInto\luIntoA%%
\let\rdInto\rdIntoA%%
\let\ldInto\ldIntoA%%
%%
\let\hEq\rEq%%
\let\vEq\uEq%%
\let\hLine\rLine%%
\let\vLine\uLine%%
\let\hDots\rDots%%
\let\vDots\uDots%%
\let\hDashes\rDashes%%
\let\vDashes\uDashes%%

%%=========================================================================%
%% The following are included for reverse compatibility only.
% \NW   plain arrows (like \vector in LaTeX)
% \NWd  dotted lines with LaTeX arrowheads
% \NWl  lines without arrowheads
% \NWld dotted lines without heads
% \NWe  "embed" tails
% \NWo  "onto" ie double LaTeX arrowheads (which Henk Barendregt wanted)
% \NWod double heads and dotted lines (ditto)
%%=========================================================================%
\let\NW\luTo\let\NE\ruTo\let\SW\ldTo\let\SE\rdTo
\def\nNW{\luTo(2,3)}\def\nNE{\ruTo(2,3)}%%ascii
\def\sSW{\ldTo(2,3)}\def\sSE{\rdTo(2,3)}%%ascii
\def\wNW{\luTo(3,2)}\def\eNE{\ruTo(3,2)}%%ascii
\def\wSW{\ldTo(3,2)}\def\eSE{\rdTo(3,2)}%%ascii
\def\NNW{\luTo(2,4)}\def\NNE{\ruTo(2,4)}%%ascii
\def\SSW{\ldTo(2,4)}\def\SSE{\rdTo(2,4)}%%ascii
\def\WNW{\luTo(4,2)}\def\ENE{\ruTo(4,2)}%%ascii
\def\WSW{\ldTo(4,2)}\def\ESE{\rdTo(4,2)}%%ascii
\def\NNNW{\luTo(2,6)}\def\NNNE{\ruTo(2,6)}%%ascii
\def\SSSW{\ldTo(2,6)}\def\SSSE{\rdTo(2,6)}%%ascii
\def\WWNW{\luTo(6,2)}\def\EENE{\ruTo(6,2)}%%ascii
\def\WWSW{\ldTo(6,2)}\def\EESE{\rdTo(6,2)}%%ascii

\let\NWd\luDotsto\let\NEd\ruDotsto\let\SWd\ldDotsto\let\SEd\rdDotsto
\def\nNWd{\luDotsto(2,3)}\def\nNEd{\ruDotsto(2,3)}%%ascii
\def\sSWd{\ldDotsto(2,3)}\def\sSEd{\rdDotsto(2,3)}%%ascii
\def\wNWd{\luDotsto(3,2)}\def\eNEd{\ruDotsto(3,2)}%%ascii
\def\wSWd{\ldDotsto(3,2)}\def\eSEd{\rdDotsto(3,2)}%%ascii
\def\NNWd{\luDotsto(2,4)}\def\NNEd{\ruDotsto(2,4)}%%ascii
\def\SSWd{\ldDotsto(2,4)}\def\SSEd{\rdDotsto(2,4)}%%ascii
\def\WNWd{\luDotsto(4,2)}\def\ENEd{\ruDotsto(4,2)}%%ascii
\def\WSWd{\ldDotsto(4,2)}\def\ESEd{\rdDotsto(4,2)}%%ascii
\def\NNNWd{\luDotsto(2,6)}\def\NNNEd{\ruDotsto(2,6)}%%ascii
\def\SSSWd{\ldDotsto(2,6)}\def\SSSEd{\rdDotsto(2,6)}%%ascii
\def\WWNWd{\luDotsto(6,2)}\def\EENEd{\ruDotsto(6,2)}%%ascii
\def\WWSWd{\ldDotsto(6,2)}\def\EESEd{\rdDotsto(6,2)}%%ascii

\let\NWl\luLine\let\NEl\ruLine\let\SWl\ldLine\let\SEl\rdLine
\def\nNWl{\luLine(2,3)}\def\nNEl{\ruLine(2,3)}%%ascii
\def\sSWl{\ldLine(2,3)}\def\sSEl{\rdLine(2,3)}%%ascii
\def\wNWl{\luLine(3,2)}\def\eNEl{\ruLine(3,2)}%%ascii
\def\wSWl{\ldLine(3,2)}\def\eSEl{\rdLine(3,2)}%%ascii
\def\NNWl{\luLine(2,4)}\def\NNEl{\ruLine(2,4)}%%ascii
\def\SSWl{\ldLine(2,4)}\def\SSEl{\rdLine(2,4)}%%ascii
\def\WNWl{\luLine(4,2)}\def\ENEl{\ruLine(4,2)}%%ascii
\def\WSWl{\ldLine(4,2)}\def\ESEl{\rdLine(4,2)}%%ascii
\def\NNNWl{\luLine(2,6)}\def\NNNEl{\ruLine(2,6)}%%ascii
\def\SSSWl{\ldLine(2,6)}\def\SSSEl{\rdLine(2,6)}%%ascii
\def\WWNWl{\luLine(6,2)}\def\EENEl{\ruLine(6,2)}%%ascii
\def\WWSWl{\ldLine(6,2)}\def\EESEl{\rdLine(6,2)}%%ascii

\let\NWld\luDots\let\NEld\ruDots\let\SWld\ldDots\let\SEld\rdDots
\def\nNWld{\luDots(2,3)}\def\nNEld{\ruDots(2,3)}%%ascii
\def\sSWld{\ldDots(2,3)}\def\sSEld{\rdDots(2,3)}%%ascii
\def\wNWld{\luDots(3,2)}\def\eNEld{\ruDots(3,2)}%%ascii
\def\wSWld{\ldDots(3,2)}\def\eSEld{\rdDots(3,2)}%%ascii
\def\NNWld{\luDots(2,4)}\def\NNEld{\ruDots(2,4)}%%ascii
\def\SSWld{\ldDots(2,4)}\def\SSEld{\rdDots(2,4)}%%ascii
\def\WNWld{\luDots(4,2)}\def\ENEld{\ruDots(4,2)}%%ascii
\def\WSWld{\ldDots(4,2)}\def\ESEld{\rdDots(4,2)}%%ascii
\def\NNNWld{\luDots(2,6)}\def\NNNEld{\ruDots(2,6)}%%ascii
\def\SSSWld{\ldDots(2,6)}\def\SSSEld{\rdDots(2,6)}%%ascii
\def\WWNWld{\luDots(6,2)}\def\EENEld{\ruDots(6,2)}%%ascii
\def\WWSWld{\ldDots(6,2)}\def\EESEld{\rdDots(6,2)}%%ascii

\let\NWe\luEmbed\let\NEe\ruEmbed\let\SWe\ldEmbed\let\SEe\rdEmbed
\def\nNWe{\luEmbed(2,3)}\def\nNEe{\ruEmbed(2,3)}%%ascii
\def\sSWe{\ldEmbed(2,3)}\def\sSEe{\rdEmbed(2,3)}%%ascii
\def\wNWe{\luEmbed(3,2)}\def\eNEe{\ruEmbed(3,2)}%%ascii
\def\wSWe{\ldEmbed(3,2)}\def\eSEe{\rdEmbed(3,2)}%%ascii
\def\NNWe{\luEmbed(2,4)}\def\NNEe{\ruEmbed(2,4)}%%ascii
\def\SSWe{\ldEmbed(2,4)}\def\SSEe{\rdEmbed(2,4)}%%ascii
\def\WNWe{\luEmbed(4,2)}\def\ENEe{\ruEmbed(4,2)}%%ascii
\def\WSWe{\ldEmbed(4,2)}\def\ESEe{\rdEmbed(4,2)}%%ascii
\def\NNNWe{\luEmbed(2,6)}\def\NNNEe{\ruEmbed(2,6)}%%ascii
\def\SSSWe{\ldEmbed(2,6)}\def\SSSEe{\rdEmbed(2,6)}%%ascii
\def\WWNWe{\luEmbed(6,2)}\def\EENEe{\ruEmbed(6,2)}%%ascii
\def\WWSWe{\ldEmbed(6,2)}\def\EESEe{\rdEmbed(6,2)}%%ascii

\let\NWo\luOnto\let\NEo\ruOnto\let\SWo\ldOnto\let\SEo\rdOnto
\def\nNWo{\luOnto(2,3)}\def\nNEo{\ruOnto(2,3)}%%ascii
\def\sSWo{\ldOnto(2,3)}\def\sSEo{\rdOnto(2,3)}%%ascii
\def\wNWo{\luOnto(3,2)}\def\eNEo{\ruOnto(3,2)}%%ascii
\def\wSWo{\ldOnto(3,2)}\def\eSEo{\rdOnto(3,2)}%%ascii
\def\NNWo{\luOnto(2,4)}\def\NNEo{\ruOnto(2,4)}%%ascii
\def\SSWo{\ldOnto(2,4)}\def\SSEo{\rdOnto(2,4)}%%ascii
\def\WNWo{\luOnto(4,2)}\def\ENEo{\ruOnto(4,2)}%%ascii
\def\WSWo{\ldOnto(4,2)}\def\ESEo{\rdOnto(4,2)}%%ascii
\def\NNNWo{\luOnto(2,6)}\def\NNNEo{\ruOnto(2,6)}%%ascii
\def\SSSWo{\ldOnto(2,6)}\def\SSSEo{\rdOnto(2,6)}%%ascii
\def\WWNWo{\luOnto(6,2)}\def\EENEo{\ruOnto(6,2)}%%ascii
\def\WWSWo{\ldOnto(6,2)}\def\EESEo{\rdOnto(6,2)}%%ascii

\let\NWod\luDotsonto\let\NEod\ruDotsonto\let\SWod\ldDotsonto
\let\SEod\rdDotsonto
\def\nNWod{\luDotsonto(2,3)}\def\nNEod{\ruDotsonto(2,3)}%%ascii
\def\sSWod{\ldDotsonto(2,3)}\def\sSEod{\rdDotsonto(2,3)}%%ascii
\def\wNWod{\luDotsonto(3,2)}\def\eNEod{\ruDotsonto(3,2)}%%ascii
\def\wSWod{\ldDotsonto(3,2)}\def\eSEod{\rdDotsonto(3,2)}%%ascii
\def\NNWod{\luDotsonto(2,4)}\def\NNEod{\ruDotsonto(2,4)}%%ascii
\def\SSWod{\ldDotsonto(2,4)}\def\SSEod{\rdDotsonto(2,4)}%%ascii
\def\WNWod{\luDotsonto(4,2)}\def\ENEod{\ruDotsonto(4,2)}%%ascii
\def\WSWod{\ldDotsonto(4,2)}\def\ESEod{\rdDotsonto(4,2)}%%ascii
\def\NNNWod{\luDotsonto(2,6)}\def\NNNEod{\ruDotsonto(2,6)}%%ascii
\def\SSSWod{\ldDotsonto(2,6)}\def\SSSEod{\rdDotsonto(2,6)}%%ascii
\def\WWNWod{\luDotsonto(6,2)}\def\EENEod{\ruDotsonto(6,2)}%%ascii
\def\WWSWod{\ldDotsonto(6,2)}\def\EESEod{\rdDotsonto(6,2)}%%ascii

%%======================================================================%
%%                                                                      %
%%      (25) MISCELLANEOUS                                              %
%%                                                                      %
%%======================================================================%

\def\labelstyle{%%
   \ifincommdiag%%
      \textstyle%%
   \else%%
      \scriptstyle%%
   \fi}%%
\let\objectstyle\displaystyle

\newdiagramgrid{pentagon}%
   {0.618034,0.618034,1,1,1,1,0.618034,0.618034}%
   {1.17557,1.17557,1.902113,1.902113}

\newdiagramgrid{perspective}%
   {0.75,0.75,1.1,1.1,0.9,0.9,0.95,0.95,0.75,0.75}%
   {0.75,0.75,1.1,1.1,0.9,0.9}%

\diagramstyle[%%ascii open square bracket
dpi=300,%%              office laserwriters are usually 300 dots per inch
vmiddle,nobalance,%%    vertical and horizontal positioning
loose,%%                allow rows and columns to stretch
thin,%%                 line10 arrows; default rule thickness (TeXbook p447)
pilespacing=10pt,%%     parallel vertical separation (horizontals: half this)
shortfall=4pt,%%        distance between arrowheads and their targets
%% The following are defaulted on entry to the diagram itself.
%% l>=2em               minimum length of horizontal arrow shafts in text
%% l>=1em               ditto in diagrams
%% size=3em             cell size
%% heads=LaTeX          arrowheads
]%%ascii close square bracket

%% process options to LaTeX2e's \usepackage[options]{diagrams}
%\tracingmacros1 \tracingcommands1 \tracingonline1
\ifx\ProcessOptions\undefined\else
   \@was@pair@false\ProcessOptions\relax\if@was@pair@\bad@pair@opt\fi
\fi

%%============================== THE END ====================================
\if@cd@use@PS@
\if@pdf@
\message{| running in pdf mode -- diagonal arrows will work automatically |}%
\else
\message{| >>>>>>>> POSTSCRIPT MODE (DVIPS) IS NOW THE DEFAULT <<<<<<<<<<<<|}%
\message{|(DVI mode has not been supported since 1992 and produces inferior|}%
\message{|results which are completely unsuitable for publication. However,|}%
\message{|if you really still need it, you can still get it by loading the |}%
\message{|package using ``\string
                          \usepackage[UglyObsolete]{diagrams}'' instead. ) |}%
\fi\else
\message{| >>>>>>>> USING UGLY OBSOLETE DVI CODE - PLEASE STOP <<<<<<<<<<<<|}%
\message{|(DVI mode has not been supported since 1992 and produces inferior|}%
\message{|results which are completely unsuitable for publication - Please |}%
\message{|use the PostScript or PDF mode instead, for much better results.)|}%
\fi
\cdrestoreat %% restore old category code for @ etc
\message{===================================================================}%
%% This is the end of Paul Taylor's commutative diagrams package.