/usr/share/lifelines/tree.tex is in lifelines-reports 3.0.61-2.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 | % Tree -- a macro to make aligned (horizontal) trees in TeX
%
% Input is of the form
% \tree
% item
% \subtree
% \leaf{item}
% .
% .
% .
% \endsubtree
% \subtree
% .
% .
% .
% \endsubtree
% \endsubtree
% \endtree
%
% Nesting is to any level. \leaf is defined as a subtree of one item:
% \def\leaf#1{\subtree#1\endsubtree}.
%
% A structure:
% \subtree
% item_part1
% item_part2
% .
% .
% .
%
% will print item_part2 directly below item_part1 as a single item
% as if they were in a \box.
%
% The macro is a 3-pass macro. On the first pass it sets up a data
% structure from the \subtree ... \endsubtree definitions. On the second pass
% it recursively calculates the width of each level of the tree. On the third
% pass it sets up the boxes, glue and rules.
%
% By David Eppstein, TUGboat, vol. 6 (1985), no. 1, pp. 31--35.
% Transcribed by Margaret Kromer (peg), Feb., 1986.
%
% Permission to add to Source Forge repository granted by David Eppstein
% (eppstein@ics.uci.edu) on 14 Nov 2000. In his email, he said:
%
% Sure. The original TeX source for the article is online, at
% http://www.ics.uci.edu/~eppstein/pubs/p-ttree.tex.Z, if that helps.
%
%
% Pass 1
% At the end of pass 1, the tree is coded as a nested collection of \hboxes
% and \vboxes.
\newbox\treebox\newcount\treeboxcnt
\def\tree{\message{Begin tree}\treeboxcnt=1\global\setbox\treebox=\boxtree}
\def\subtree{\ettext \advance\treeboxcnt by 1 \boxtree}
\def\leaf#1{\subtree#1\endsubtree}
\def\endsubtree{\ettext \egroup \advance\treeboxcnt-1{}%
\ifnum\treeboxcnt=-1 \treeerrora\fi}
\def\endtree{\endsubtree \ifnum\treeboxcnt>0 \treeerrorb\fi%
\settreesizes \typesettree \message{-- end tree}}
% Error messages for unbalanced tree
\def\treeerrora{\errhelp=\treeerrorahelp%
\errmessage{Unbalanced tree -- too many endsubtrees}}
\newhelp\treeerrorahelp{There are more subtrees closed than opened}
\def\treeerrorb{\errhelp=\treeerrorbhelp%
\errmessage{Unbalanced tree -- not enough endsubtrees}}
\newhelp\treeerrorbhelp{Not all the subtrees of the tree are closed.
If you continue, you'll get some mysterious secondary errors.}
% Set up \vbox containing root of tree
\newif\iftreetext\treetextfalse % Whether still aligning text
\def\boxtree{\hbox\bgroup % Start outer box of tree or subtree
\baselineskip 2.5ex % Narrow line spacing slightly
\tabskip 0pt % No spurious glue in alignment
\vbox\bgroup % Start inner text \vbox
\treetexttrue % Remember for \ettext
\let\par\crcr \obeylines % New line breaks without explicit \cr
\halign\bgroup##\hfil\cr} % Start alignment with simple template
\def\ettext{\iftreetext % Are we still in inner text \vbox?
\crcr\egroup \egroup \fi} % Yes, end alignment and box
% Pass 2
% Recursively calculate widths of tree with \setsizes; keep results in
% \treesizes; \treewidth contains total width calculated so far. \treeworkbox
% is workspace containing subtree being sized.
\newbox\treeworkbox
\def\cons#1#2{\edef#2{\xmark #1#2}} % Add something to start of list
\def\car#1{\expandafter\docar#1\docar} % Take first element of list
\def\docar\xmark#1\xmark#2\docar{#1} % ..by ignoring rest in expansion
\def\cdr#1{\expandafter\docdr#1\docdr#1}% Similarly, drop first element
\def\docdr\xmark#1\xmark#2\docdr#3{\def#3{\xmark #2}}
\def\xmark{\noexpand\xmark} % List separator expands to self
\def\nil{\xmark} % Empty list is just separator
\def\settreesizes{\setbox\treeworkbox=\copy\treebox%
\global\let\treesizes\nil \setsizes}
\newdimen\treewidth % Width of this part of the tree
\def\setsizes{\setbox\treeworkbox=\hbox\bgroup% Get a horiz list as a workspace
\unhbox\treeworkbox\unskip % Take tree, unpack it into horiz list
\inittreewidth % Get old width at this level
\sizesubtrees % Recurse through all subtrees
\sizelevel % Now set width from remaining \vbox
\egroup} % All done, finish our \hbox
\def\inittreewidth{\ifx\treesizes\nil % If this is the first at this level
\treewidth=0pt % ..then we have no previous max width
\else \treewidth=\car\treesizes % Otherwise take old max level width
\global\cdr\treesizes % ..and advance level width storage
\fi} % ..in preparation for next level.
\def\sizesubtrees{\loop % For each box in horiz list (subtree)
\setbox\treeworkbox=\lastbox \unskip % ..pull it off list and flush glue
\ifhbox\treeworkbox \setsizes % If hbox, it's a subtree - recurse
\repeat} % ..and loop; end loop on tree text
\def\sizelevel{%
\ifdim\treewidth<\wd\treeworkbox % If greater than previous maximum
\treewidth=\wd\treeworkbox \fi % Then set max to new high
\global\cons{\the\treewidth}\treesizes}% In either case, put back on list
% Pass 3
% Recursively typeset tree with \maketree by adding an \hbox containing
% a subtree (in \treebox) to the horizontal list.
\newdimen\treeheight % Height of this part of the tree
\newif\ifleaf % Tree has no subtrees (is a leaf)
\newif\ifbotsub % Bottom subtree of parent
\newif\iftopsub % Top subtree of parent
\def\typesettree{\medskip\maketree\medskip} % Make whole tree
\def\maketree{\hbox{\treewidth=\car\treesizes % Get width at this level
\cdr\treesizes % Set up width list for recursion
\makesubtreebox\unskip % Set \treebox to text, make subtrees
\ifleaf \makeleaf % No subtrees, add glue
\else \makeparent \fi}} % Have subtrees, stick them at right
{\catcode`@=11 % Be able to use \voidb@x
\gdef\makesubtreebox{\unhbox\treebox % Open up tree or subtree
\unskip\global\setbox\treebox\lastbox % Pick up very last box
\ifvbox\treebox % If we're already at the \vbox
\global\leaftrue \let\next\relax % ..then this is a leaf
\else \botsubtrue % Otherwise, we have subtrees
\setbox\treeworkbox\box\voidb@x % Init stack of processed subs
\botsubtrue \let\next\makesubtree % ..and call \maketree on them
\fi \next}} % Finish up for whichever it was
\def\makesubtree{\setbox1\maketree % Call \maketree on this subtree
\unskip\global\setbox\treebox\lastbox % Pick up box before it
\treeheight=\ht1 % Get height of subtree we made
\advance\treeheight 2ex % Add some room around the edges
\ifhbox\treebox \topsubfalse % If picked up box is a \vbox,
\else \topsubtrue \fi % ..this is the top, otherwise not
\addsubtreebox % Stack subtree with the rest
\iftopsub \global\leaffalse % If top, remember not a leaf
\let\next\relax \else % ..(after recursion), set return
\botsubfalse \let\next\makesubtree % Otherwise, we have more subtrees
\fi \next} % Do tail recursion or return
\def\addsubtreebox{\setbox\treeworkbox=\vbox{\subtreebox\unvbox\treeworkbox}}
\def\subtreebox{\hbox\bgroup % Start \hbox of tree and lines
\vbox to \treeheight\bgroup % Start \vbox for vertical rules
\ifbotsub \iftopsub \vfil % If both bottom and top subtree
\hrule width 0.4pt % ..vertical rule is just a dot
\else \treehalfrule \fi \vfil % Bottom gets half-height rule
\else \iftopsub \vfil \treehalfrule % Top gets half-height the other way
\else \hrule width 0.4pt height \treeheight \fi\fi % Middle, full height
\egroup % Finish vertical rule \vbox
\treectrbox{\hrule width 1em}\hskip 0.2em\treectrbox{\box1}\egroup}
\def\treectrbox#1{\vbox to \treeheight{\vfil #1\vfil}}
\def\treehalfrule{\dimen\treeworkbox=\treeheight % Get total height
\divide\dimen\treeworkbox 2%
\advance\dimen\treeworkbox 0.2pt % Divide by two, add half horiz height
\hrule width 0.4pt height \dimen\treeworkbox}% Make a vertical rule that high
\def\makeleaf{\box\treebox} % Add leaf box to horiz list
\def\makeparent{\ifdim\ht\treebox>%
\ht\treeworkbox % If text is higher than subtrees
\treeheight=\ht\treebox % ..use that height
\else \treeheight=\ht\treeworkbox \fi % Otherwise use height of subtrees
\advance\treewidth-\wd\treebox % Take remainder of level width
\advance\treewidth 1em % ..after accounting for text and glue
\treectrbox{\box\treebox}\hskip 0.2em % Add text, space before connection
\treectrbox{\hrule width \treewidth}%
\treectrbox{\box\treeworkbox}} % Add \hrule, subs
% No idea what \spouse is supposed to do... wasn't included
\def\spouse{\bf}
|