# Dirtree pagebreak issue

I have a (rather long-ish) hierarchical structure, typeset with the dirtree package. However, I have some issues when breaking the tree over to a new page -- the line may protrude up to the very top of the sheet writeable area, extending into the headings area.

Note that I used the headings here only to better illustrate the issue, they are not necessary to exemplify the problem. But I do have a similar page setup, and it looks particularly unpleasant with the horizontal rule being intersected by the tree lines.

Here's an example:

\documentclass{article}
\usepackage{lipsum}
\usepackage{dirtree}
\usepackage{fancyhdr}

\fancyhf{}
\fancyfoot[C]{\thepage}
\renewcommand{\footrulewidth}{0.4pt}
\pagestyle{fancy}
\renewcommand{\sectionmark}[1]{\markright{#1}}
\renewcommand{\subsectionmark}[1]{\markright{#1}}

\begin{document}
\lipsum[1-4]
\dirtree{%
.1 spam.
.2 eggs.
.2 ham.
.3 circus.
.3 parrot.
.4 knights.
.3 spamalot.
.4 ni.
.5 brian.
.5 vikings.
.2 meaning.
}
\end{document}


Now, the package documentation says that a command \DTsplittree is in the To-Do list, that will allow splitting the tree over several pages. Any ideas for a dirty hack or a workaround that I might be able to use in the meantime?

I've used some other tricks from the book, like reducing the line spacing and playing with font size, and I guess I could split it in two a few smaller parts (which I will have to fit again between pages!) if I can't find another way of doing it. But I'm more interested in a TeXnical solution.

Update Let's see if this will get answered if some 100 bonus rep is thrown at it.

-

The dirtree package is neat! Below is a slight modification of the package to page break sanely. It requires LaTeX and the zref package, so I don't claim it's the right solution, but it does seem to work (at least with extremely limited testing). As this modification uses references, it takes multiple runs of LaTeX to see the new page breaking behavior.

% This file was dirtree.tex. It was modified by TH. to support
% splitting the tree at pagebreaks sanely. It has been renamed to
% durtree.sty. It will now only work with LaTeX. It is meant as a
% quick hack to solve the problem at hand. Any bugs in it are my own,
% please don't blame M. Charpentier for them!
%
%%
%% This is file dirtree.tex',
%% generated with the docstrip utility.
%%
%% The original source files were:
%%
%% dirtree.dtx  (with options: tex')
%%
%% IMPORTANT NOTICE:
%%
%% For the copyright see the source file.
%%
%% Any modified versions of this file must be renamed
%% with new filenames distinct from dirtree.tex.
%%
%% For distribution of the original source see the terms
%% for copying and modification in the file dirtree.dtx.
%%
%% This generated file may be distributed as long as the
%% original source files, as listed above, are part of the
%% same distribution. (The sources need not necessarily be
%% in the same archive or directory.)
%%
%% Package dirtree.dtx'
%% -----------------------------------------------
%% Copyright (C) 2004-2006 Jean-C\^ome Charpentier
%% -----------------------------------------------
%%
%% This work may be distributed and/or modified under the
%% conditions of the LaTeX Project Public License, either version 1.3
%% of this license or (at your option) any later version.
%%   http://www.latex-project.org/lppl.txt
%% and version 1.3 or later is part of all distributions of LaTeX
%% version 2003/12/01 or later.
%%
%% See CTAN archives in directory macros/latex/base/lppl.txt.
%%
%% CONTENTS:
%%   This work consists of the files dirtree.ins and dirtree.dtx.
%%   Derived files are dirtree.tex and dirtree.sty.
%%
%% DESCRIPTION:
%%   dirtree is a package displaying directory trees.
%%
\def\fileversion{0.1}
\def\filedate{2010/12/04}
\NeedsTeXFormat{LaTeX2e}[1995/06/01]
\ProvidesPackage{durtree}[\filedate\space v\fileversion]
\RequirePackage{zref-abspage}
\long\def\LOOP#1\REPEAT{%
\def\ITERATE{#1\relax\expandafter\ITERATE\fi}%
\ITERATE
\let\ITERATE\relax
}
\let\REPEAT=\fi
\def\@nameedef#1{\expandafter\edef\csname #1\endcsname}
\newdimen\DT@offset \DT@offset=0.2em
\newdimen\DT@width \DT@width=1em
\newdimen\DT@sep \DT@sep=0.2em
\newdimen\DT@all
\DT@all=\DT@offset
\newdimen\DT@rulewidth \DT@rulewidth=0.4pt
\newdimen\DT@dotwidth \DT@dotwidth=1.6pt
\newdimen\DTbaselineskip \DTbaselineskip=\baselineskip
\newcount\DT@counti
\newcount\DT@countii
\newcount\DT@countiii
\newcount\DT@countiv
\newcount\DT@treenum \DT@treenum=0
\newif\ifDT@split
\def\DTsetlength#1#2#3#4#5{%
\DT@offset=#1\relax
\DT@width=#2\relax
\DT@sep=#3\relax
\DT@all=\DT@offset
\DT@rulewidth=#4\relax
\DT@dotwidth=#5\relax
}
\def\DTstyle{\ttfamily}
\def\DTstylecomment{\rmfamily}
\def\DTcomment#1{%
\kern\parindent\dotfill
{\DTstylecomment{#1}}%
}
\def\dirtree#1{%
\let\DT@indent=\parindent
\parindent=\z@
\let\DT@parskip=\parskip
\parskip=\z@
\let\DT@baselineskip=\baselineskip
\baselineskip=\DTbaselineskip
\let\DT@strut=\strut
\def\strut{\vrule width\z@ height0.7\baselineskip depth0.3\baselineskip}%
\DT@counti=\z@
\next#1\@nil
\dimen@=\hsize
\setbox\z@=\hbox to\dimen@{%
\hsize=\dimen@
\vbox{\@nameuse{DT@body@1}}%
}%
\dimen@=\ht\z@
\ht\z@=0.7\baselineskip
\dp\z@=\dimen@
\par\leavevmode
\kern\DT@offset
\kern\DT@width
\box\z@
\endgraf
\DT@countii=\@ne
\DT@countiii=\z@
\dimen3=\dimen@
\@namedef{DT@lastlevel@1}{-0.7\baselineskip}%
\loop
\ifnum\DT@countii<\DT@counti
\dimen@=\@nameuse{DT@level@\the\DT@countii}\DT@all
\leavevmode
\kern\dimen@
\DT@countiv=\DT@countii
\count@=\z@
\DT@splitfalse
\LOOP
\ifnum\@nameuse{DT@level@\the\DT@countiv} >
\@nameuse{DT@level@\the\DT@countii}\relax
\else
\count@=\@ne
\fi
\ifnum0\zref@extract{DT\the\DT@treenum.\the\DT@countiv}{abspage} =
0\zref@extract{DT\the\DT@treenum.\the\DT@countii}{abspage}\relax
\else
\count@=\@ne
\DT@splittrue
\fi
\ifnum\count@=\z@
\REPEAT
\edef\DT@hsize{\the\hsize}%
\count@=\@nameuse{DT@level@\the\DT@countii}\relax
\dimen@=\count@\DT@all
\setbox\z@=\vbox{\@nameuse{DT@body@\the\DT@countii}}%
\hsize=\DT@hsize
\dimen@=\ht\z@
\ht\z@=0.7\baselineskip
\dp\z@=\dimen@
\@nameedef{DT@lastlevel@\the\DT@countii}{\the\dimen3}%
\dimen@=\@nameuse{DT@lastlevel@\the\DT@countii}\relax
\ifnum\@nameuse{DT@level@\the\DT@countiv} <
\@nameuse{DT@level@\the\DT@countii}\relax
\fi
\ifDT@split
\fi
\kern-0.5\DT@rulewidth
\hbox{\vbox to\z@{\vss\hrule width\DT@rulewidth height\dimen@}}%
\kern-0.5\DT@rulewidth
\kern-0.5\DT@dotwidth
\vrule width\DT@dotwidth height0.5\DT@dotwidth depth0.5\DT@dotwidth
\kern-0.5\DT@dotwidth
\vrule width\DT@width height0.5\DT@rulewidth depth0.5\DT@rulewidth
\kern\DT@sep
\box\z@
\endgraf
\repeat
\parindent=\DT@indent
\parskip=\DT@parskip
\DT@baselineskip=\baselineskip
\let\strut\DT@strut
}
\@namedef{DT@level@\the\DT@counti}{#1}%
\edef\DT@label{DT\the\DT@treenum.\the\DT@counti}%
\expandafter\def\csname DT@body@\the\DT@counti\expandafter\endcsname
\expandafter{\expandafter\strut\expandafter\zref@label\expandafter{%
\DT@label}%
{\DTstyle{#2}\strut}%
}
\ifx\relax#3\relax
\let\next\@gobble
\fi
\next#3\@nil
}
\endinput
%%
%% End of file durtree.sty'.


It might be instructive to diff this file with dirtree.tex to see what I changed in detail. Basically, I added an absolute page ref after the first \strut that gets added around each entry. Then, when typesetting, it checks if the page number of the current entry matches the previous entry at that level. If they match, nothing different happens (\ifDT@split is false). Otherwise, it only draws the vertical rule to the top of the first entry on the current page.

I also changed the \dimen\z@ and \dimen0 to \dimen@. I guess this is technically slightly faster, but mostly it was annoying me.

-
@TH Barring a couple of pixels short on top left, the revised code works very well. You certainly deserve the bounty on top of which I would like to add another 100 - if there is a way to do it. If there is would you please post how on meta? –  Yiannis Lazarides Dec 4 '10 at 16:01
@Yiannis: I'm not sure I know what you mean by a couple of pixels short on the top left. If there's a bug, I can try to fix it. –  TH. Dec 4 '10 at 21:31
Оutstanding! I kinda lost hope for this to get answered, but I was pleasantly surprised by your answer. I can't spend much time right now studying the diff between the versions, but in the few quick tests I ran it works exactly the way I want it to. Thanks a lot! You deserve definitely all the rep I can throw your way for this answer. BTW, have you considered conntacting the package author to see whether he'll include some of your code in a future version of dirtree? –  Martin Tapankov Dec 5 '10 at 17:59
@Martin: I hadn't really thought about it. dirtree works with both plain TeX and LaTeX. My solution works only with LaTeX. It wouldn't be too hard to implement a generic solution, but that'd basically be duplicating the reference mechanism which seems like the wrong solution. The tricky part is that TeX can construct more than a page of material before deciding that it is going to break the page so I'm not actually sure what the right way to handle this is. –  TH. Dec 5 '10 at 23:49