% \begin{meta-comment}
%
% poetry.dtx
%
% Sophisticated typesetting of poetry
%
% (c) 1996 Mark Wooding
%
% \end{meta-comment}
%
% \begin{meta-comment} <general public licence>
%%
%% poetry package -- sophisticated typesetting of poetry
%% Copyright (c) 1996 Mark Wooding
%%
%% This package is not finished, let alone properly tested.  It is being
%% released in the hope that others can contribute ideas and suggestions
%% that the author (who is not an expert on poetry) may have missed.
%%
%% I hope that someone finds this package useful.  However, if it goes
%% wrong, that's your problem.  I may try and fix it, although the author
%% does not guarantee that this is the case.
%%
%% This pre-release version may be distributed under the terms of the GNU
%% General Public Licence, as published by the Free Software Foundation;
%% either version 2 of the Licence, or (at your option) any later version.
%% However, since this is not finished, and I'd like others to benefit
%% from the finished version, the author BEGS and PLEADS you not to spread
%% this pre-release too much.
%%
% \end{meta-comment}
%
% \begin{meta-comment} <Package preambles>
%<+package>\NeedsTeXFormat{LaTeX2e}
%<+package>\ProvidesPackage{poetry}
%<+package>                [1996/05/28 1.00 Poetry typesetting]
% \end{meta-comment}
%
% ^^A \CheckSum{579}
%% \CharacterTable
%%  {Upper-case    \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z
%%   Lower-case    \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z
%%   Digits        \0\1\2\3\4\5\6\7\8\9
%%   Exclamation   \!     Double quote  \"     Hash (number) \#
%%   Dollar        \$     Percent       \%     Ampersand     \&
%%   Acute accent  \'     Left paren    \(     Right paren   \)
%%   Asterisk      \*     Plus          \+     Comma         \,
%%   Minus         \-     Point         \.     Solidus       \/
%%   Colon         \:     Semicolon     \;     Less than     \<
%%   Equals        \=     Greater than  \>     Question mark \?
%%   Commercial at \@     Left bracket  \[     Backslash     \\
%%   Right bracket \]     Circumflex    \^     Underscore    \_
%%   Grave accent  \`     Left brace    \{     Vertical bar  \|
%%   Right brace   \}     Tilde         \~}
%%
%
% \begin{meta-comment}
%
%<*driver>
\input{mdwtools}
\describespackage{poetry}
\def\todo#1{%
  \par\bigskip\noindent%
  \fbox{\dimen0\hsize\advance\dimen0-2\fboxsep%
        \parbox{\dimen0}%
               {\vskip5pt\centerline{\bfseries TO DO}\vskip 12pt#1}}%
  \par\bigskip}%
\mdwdoc
%</driver>
%
% \end{meta-comment}
%
% \section{User guide}
%
% The \package{poem} package is designed to provide appropriate typesetting
% for all manner of `sensible' poems, by which I mean not to exclude the
% works of such great poets as Spike Milligan, but more those who lay out
% their words to form pretty patterns: such works must be dealt with on
% an individual basis, I'm afraid.
%
% An overview of the features provided wouldn't go amiss, I think.
% \begin{itemize}
%
% \item Poems are normally centred on the page based on the length of
%       the longest line.  This package handles this requirement, but
%       allows poems to be left or right aligned if desired.
%
% \item Lines of poems are numbered, and may be labelled and referenced
%       using the normal |\label| and |\ref| commands of \LaTeX.  Numbers
%       are by default printed every 5 lines, on the right hand side, but
%       this is fully configurable, as is the style of the numbers.
%
% \item Stanzas can be numbered, titled, either, neither or both.  Stanza
%       numbers can be labelled and referenced.
%
% \end{itemize}
%
%
% \subsection{Typesetting simple poems}
%
% \DescribeEnv{poem}
% You can typeset a poem using the \env{poem} environment.  The lines of
% the poem are separated by |\\| commands as usual.  Use the |\stanza*|
% command to start new stanzas.  Something like this would do the job:
%
% \todo{There should be a demo here}
%
% Lines of a poem will be broken if they get too long.  However, a
% `logical' line of a poem will never be broken between pages.\footnote{
%   This is an artifact of the way I've implemented the poems.  I don't
%   think it's a terribly nasty restriction.}
% Continued lines are indented from the left margin by a fair distance,
% so that they don't get confused with the starts of new lines.
%
% \DescribeMacro{\poemline}
% You've probably noticed that the poem lines are numbered down the right
% hand side.  This happens automatically, although you can turn it off if
% it's inappropriate.  All the line numbers are generated by the command
% |\poemline|, which you can define however you like.  Saying
% \begin{listing}
%\renewcommand{\poemline}{}
% \end{listing}
% will cause nothing to be printed for the line numbers, turning them off.
%
% \todo{A command to disable numbering?}
%
% \DescribeMacro{\title}
% You can use the |\title| command to typeset a title for your poem.  The
% title is inserted right there and then, so watch out.  It's conventional
% to put the title at the top of the poem, although this is art we're talking
% about, so who knows?  Just say \syntax{"\title{"<title>"}"}.
%
% \DescribeMacro{\author}
% Similarly, the author of a poem can be credited with the |\author| command.
% Just put the author's name in the argument.  Authors usually go at the
% bottom of poems.
%
% \DescribeMacro{\poemtitle} \DescribeMacro{\poemauthor}
% The |\title| and |\author| commands are implemented internally by the
% commands |\poemtitle| and |\poemauthor|, which you can redefine if you
% like.  You should probably have a look at the default definitions before
% you do this: they use some little features which haven't been described
% yet.  Don't be intimidated, though: I'll get to them later!
%
%
% \subsection{Playing with stanzas}
%
% \DescribeMacro{\stanza}
% The |\stanza| command is actually fairly complicated.  It always starts
% a new stanza, leaving a gap if necessary after the previous line.
% Also, the stanza will be numbered, unless you use the |\stanza*| command.
% You can also give the stanza a title by saying
% \syntax{"\\stanza["<title>"]"} (or |\stanza*|\dots\ if you don't want the
% number).  The title and number are printed above the new stanza.
%
% \DescribeMacro{\labelstanza}
% The stanza numbers are typeset by the command |\labelstanza| which you
% can define however you like.  To disable them entirely, say
% \begin{listing}
%\renewcommand{\labelstanza}{}
% \end{listing}
%
% There are a collection of other style parameters for stanza titles.  These
% are described below (if you're not interested in this sort of thing, skip
% to the next section).
%
% \begin{description} \def\makelabel#1{\hskip\labelsep\cmd{#1}\hfil}
% \item [stanza] is a \LaTeX\ counter which contains the current stanza
%       number.
% \item [\thestanza] typesets the value of the |stanza| counter in normal
%       text.
% \item [\labelstanza] typesets the value of the |stanza| counter specially
%       for use as a stanza title.  (The default style uses small caps here,
%       which is generally inappropriate in running text.)
% \item [\stanzaname] is a command with one argument which typesets a stanza
%       title string, as passed to the |\stanza| command (not including the
%       number).
% \item [\stanzacombine] is given two arguments: a title (built by
%       |\labelstanza|) and a title (formatted by |\stanzaname|).  It
%       should format and space these two arguments.  It \emph{can't}
%       change the font of this text -- it's too late for that now.
%       This command is only used when both a number and a stanza title
%       are given.
% \item [\stanzaspace] is called with no arguments.  It should somehow
%       separate the previous stanza (if any) from the new one.  Look at the
%	counter value to find out whether this is the first stanza, if it
%	matters (e.g., you're drawing little rows of stars or something).
% \item [\stanzatitle] is given one argument: a `combined' title.  It should
%       typeset the title as a line in LR mode.  Again, it's too late to
%       play with fonts now.
% \end{description}
%
% All of the commands described above are given fairly simple definitions
% by default: you should be able to customise these without difficulty.
%
%
% \subsection{Starting new lines}
%
% \DescribeMacro{\\}
% New lines within a stanza are started with the |\\| command.  This always
% starts a new line.  The |\\*| command (which forbids a following page
% break) and the optional argument (which adds vertical space) are
% fully supported.
%
% \DescribeMacro{\nl}
% However, there's also a command |\nl| which works like |\\| (it has a
% $*$-version and so on) except that it won't start a new line unless
% there's something already on the current one.  This is useful in commands
% like |\poemauthor| which want to typeset their text on a new line without
% possibly leaving an ugly looking gap.
%
% For example, the definition of |\poemauthor| is:
% \begin{listing}
%\providecommand{\poemauthor}[1]{%
%  \nl*[\smallskipamount]%
%  \nonumber%
%  \hfill\normalfont\itshape#1%
%  \\%
%}
% \end{listing}
% The important part to us is that |\nl*[\smallskipamount]| at the
% beginning.  This starts a new line, making sure that there's no page
% break between it and the previous line, and adds a little extra space
% before the author's name.  The |\nonumber| command just prevents this line
% from being numbered, since it's not actually part of the poem itself:
% numbering is dealt with in detail in the next section.
%
%
% \subsection{Line numbering}
%
% \DescribeMacro{\poemline}
% I skimmed over line numbering earlier, because it's a bit complex.  I'll
% start with the default definition of the |\poemline| command, which will
% give me something specific to talk about.  The command is used to generate
% the line number for the line which has \emph{just finished}.
%
% \begin{listing}
%\providecommand{\poemline}{%
%  \ifmultipleof{5}{\value{poemline}}%
%    {\poemlineposition[r]{\scriptsize\thepoemline}}%
%    {}%
%  \refstepcounter{poemline}%
%}
% \end{listing}
%
% \DescribeMacro{\ifmultipleof}
% The |\ifmultipleof{5}{\value{poemline}}|\dots\ construction restricts the
% printed numbers to every fifth line (|\value{poemline}| is the value of
% the |poemline| counter).  Saying
% \syntax{"\\ifmultipleof{"$n$"}{"$x$"}{"<true>"}{"<false>"}"} will do
% \<true> if~$x$ is a multiple of~$n$; otherwise it does \<false>.
%
% \DescribeMacro{\poemlineposition}
% The |\poemlineposition| command positions its text to the right or
% left of the poem, according to whether its optional argument is \lit{l}
% or \lit{r}.
%
% So, the code up there just prints the poem line in small numbers on the
% right hand side of every fifth line of the poem.  (Phew!)  It then steps
% the counter so it'll be all right for cross-references in the next line
% down.  Got that?
%
% \DescribeMacro{\nonumber}
% Something a little simpler now: saying |\nonumber| in a line of poetry will
% suppress the line number on that line.  The counter won't be stepped, and
% no number is printed.  This is mainly useful in titles and other
% adornments in poems.
%
%
% \subsection{Other little extras}
%
% \DescribeEnv{xpoem}
% The \env{poem} environment doesn't actually do a lot by itself.  If you
% look at its definition, you'll see that it just starts a standard \LaTeX\
% \env{verse} environment and then calls the \env{xpoem} environment to
% do the actual work.  The idea is that you can then redefine \env{poem}
% to do whatever setting up you want and then use \env{xpoem} to do
% its typesetting magic.  For example, the definitions
% \begin{listing}
%\newcommand{\poemend}{}
%\renewenvironment{poem}[2]{%
%  \begin{verse}%
%  \renewcommand{\poemend}{\author{#2}}%
%  \begin{xpoem}%
%  \title{#1}%
%}{%
%  \poemend%
%  \end{xpoem}%
%  \end{verse}%
%}
% \end{listing}
% modifies the environment so that it takes two arguments, the title and
% the author, and sets them at the beginning and end of the poem
% respectively.
%
% \TeX\ hackers who know about such things could make a \env{poem}
% environment which `obeys' line breaks in the input file by making active
% newlines do an |\nl| command.  The possibilities are endless.
%
% \DescribeMacro{\splitline}
% The |\splitline| command should be used at the start of a new line (it
% starts a new line all by itself otherwise).  It shunts all the text of
% the line to the right so that it starts where the previous line finished.
%
% \todo{Come up with an example for this}
%
%
% \implementation
%
% \section{Implementation}
%
% \subsection{Various allocations}
%
% I need a shocking number of allocations for this package to work.  I'll
% start with the counters, because they're probably the most reasonable.
%
% |poem@count| keeps track of which poem this is, so I can look up the
% width in my magic list (I'll describe width handling later in detail).
% |poemline| is a user-level counter which keeps track of the current line
% number.  |stanza| keeps track of the current stanza number.
%
% The |\poemchunksize| counter (which is also faked as a \LaTeX\ counter)
% tells me how big a chunk should be.  The final counter, |\poem@linesleft|
% tells me how many more lines I can do in this chunk.
%
% All the counters are assigned globally, or at least they should be.
%
%    \begin{macrocode}
\newcounter{poem@count}
\newcounter{poemline}
\newcount\poemchunksize
\let\c@poemchunksize\poemchunksize
\newcount\poem@linesleft
\poemchunksize=30
%    \end{macrocode}
%
% Now for some length registers.  |\poem@width| contains the width of the
% poem as read from the |.aux| file; |\poem@thiswidth| contains the width
% of the longest line read so far.  Both of these are updated as I go through
% the poem.  The final value of |\poem@thiswidth| is written back to the
% list when all's finished.
%
% |\poem@lastwidth| contains the width of the last line -- it's used in
% handling |\splitline|s.  |\poem@prevdepth| is used to fiddle |\prevdepth|
% when handling long lines.
%
% All of these length parameters should be modified globally at all times.
%
%    \begin{macrocode}
\newdimen\poem@width
\newdimen\poem@thiswidth
\newdimen\poem@lastwidth
\newdimen\poem@prevdepth
%    \end{macrocode}
%
% The switch |\ifpoem@long| is used to decide whether we need to save the
% poem width in the aux file.
%
%    \begin{macrocode}
\newif\ifpoem@long
%    \end{macrocode}
%
% Lastly, a skip register.  This is the glue on the left hand side of a 
% poem.  It should be |\@centering| to center the poem horizontally, or
% something rigid and nonzero to left-align.
%
%    \begin{macrocode}
\newskip\poemleftskip
\poemleftskip\@centering
%    \end{macrocode}
%
%
% \subsection{Handling poem widths}
%
% Poems are horizontally centred, based on the width of their longest line.
% This can be done without too many problems using an |\halign|.  However,
% this would require \TeX\ to read in the whole poem before being able to lay
% out the first line; this is clearly impractical for something like
% \emph{The Rime of the Ancient Mariner}.
%
% The solution is fairly similar to that used by the \package{longtable}
% package.  I'll divide a poem up into chunks, centring each chunk
% horizontally.  I'll also keep track of the longest line so far, and make
% sure that it affects each chunk, so as to prevent the chunks looking odd.
% When all's finished, I'll write a list containing the widths of all the
% poems to the |.aux| file so that next time everything will look nice.
%
% The list is held in just one macro, which contains entries of the form
% \syntax{"["<poem-number>"]{"<width>"}"}.  I build the new updated
% list in another macro as I go -- this version will be written to the
% |.aux| file at the very end, to ensure that inserted or removed poems
% don't mess anything up permanently.  It also avoids problems to do with
% poem widths decreasing, which gives \package{longtable} a bit of a
% headache.
%
% These two macros are always assigned globally.
%
%    \begin{macrocode}
\def\poem@widths{}
\def\poem@savedwidths{}
%    \end{macrocode}
%
% \begin{macro}{\poem@getwidth}
%
% The width of the current poem can be read using this macro.  It assigns
% the width to the |\poem@width| register; it gets the value 0\,pt if no
% value for this poem actually exists.
%
%    \begin{macrocode}
\def\poem@getwidth#1{%
  \def\@tempa##1[#1]##2##3\@@{##2}%
  \global\poem@width\expandafter\@tempa\poem@savedwidths[#1]\z@\@@%
  \relax%
}
%    \end{macrocode}
%
% \end{macro}
%
% \begin{macro}{\poem@setwidth}
%
% I can also write the width of the current poem using this macro.  It
% updates the new improved list with the value of |\poem@thiswidth|.
%
%    \begin{macrocode}
\def\poem@setwidth#1{%
  \def\@tempb##1[#1]\z@{##1}%
  \def\@tempa##1[#1]##2##3\@@{%
    \xdef\poem@widths{%
      ##1%
      [#1]{\the\poem@thiswidth}%
      \ifdim##2=\z@\else\expandafter\@tempb\fi##3%
    }%
  }%
  \expandafter\@tempa\poem@widths[#1]\z@\@@%
}
%    \end{macrocode}
%
% \end{macro}
%
% At the very end of the document, I want to write the poem widths to the
% |.aux| file.  The following code will do the job nicely.
%
%    \begin{macrocode}
\AtEndDocument{%
  \if@filesw%
    \immediate\write\@auxout%
      {\gdef\noexpand\poem@savedwidths{\poem@widths}}%
  \fi%
}
%    \end{macrocode}
%
%
% \subsection{Some little details}
%
% \begin{macro}{\@maybe@unskip}
%
% This macro solves a little problem.  In an alignment (and in other places)
% it's desirable to suppress trailing space.  The usual method, to say
% |\unskip|, is a little hamfisted, because it removes perfectly reasonable
% aligning spaces like |\hfil|s.  While as a package writer I can deal with
% this sort of thing by saying |\kern\z@| in appropriate places, it can
% annoy users who are trying to use |\hfill| to override alignment in funny
% places.
%
% My current solution seems to be acceptable.  I'll remove the natural width
% of the last glue item, so that it can still stretch and shrink if
% necessary.  The implementation makes use of the fact that multiplying
% a \<skip> by a \<number> kills off the stretch.
%
%    \begin{macrocode}
\def\@maybe@unskip{\hskip-\@ne\lastskip\relax}
%    \end{macrocode}
%
% \end{macro}
%
%
% \subsection{Line numbering}
%
% Poem lines are numbered in a fairly sensible and normal way.  However, it's
% not normal to number every single line.  The macro |\poemline| below will
% decide whether and how to number a line.
%
% \begin{macro}{\ifmultipleof}
%
% This macro is called as
% \syntax{"\\ifmultipleof{"$n$"}{"$x$"}{"<true>"}{"<false>"}"}.  If the
% number~$x$ is a multiple of~$n$, then the whole lot expands to \<true>;
% otherwise it expands to \<false>.  The test here relies on \TeX\ doing
% integer division (which it does).
%
%    \begin{macrocode}
\def\ifmultipleof#1#2{%
  \count@#2%
  \divide\count@#1%
  \multiply\count@#1%
  \relax%
  \ifnum#2=\count@%
    \expandafter\@firstoftwo%
  \else%
    \expandafter\@secondoftwo%
  \fi%
}
%    \end{macrocode}
%
% \end{macro}
%
% \begin{macro}{\poemlineposition}
%
% This macro typesets its argument relative to the poem in some neat way.
% It's called as \syntax{"\\poemlineposition["<posn>"]{"<text>"}"}.  The
% \<posn> may be \lit{l} or \lit{r}, where `l' and `r' mean left and right
% respectively.
%
% This command only produces at all sensible results when typesetting poem
% line numbers.
%
%    \begin{macrocode}
\def\poemlineposition{\@ifnextchar[\poem@lp@i{\poem@lp@i[l]}}
%    \end{macrocode}
%
% Now there's some sorting out to do.  If the number is to go on the
% right, then there's no problem: it can just be typeset as it is.
% Positioning on the left isn't too hard either -- I just need to shift the
% number to the left by |\linewidth| plus a bit for niceness.
%
%    \begin{macrocode}
\def\poem@lp@i[#1]#2{%
  \if#1r%
    \hfil\kern8\p@#2%
  \else\if#1l%
    \llap{#2\kern8\p@\kern\linewidth}%
  \fi\fi%
}
%    \end{macrocode}
%
% \end{macro}
%
% \begin{macro}{\poemline}
%
% The default definition of |\poemline| will put a line number in script
% size (so as not to appear too obvious) on every fifth line.
%
%    \begin{macrocode}
\providecommand{\poemline}{%
  \ifmultipleof{5}{\value{poemline}}%
    {\poemlineposition[r]{\scriptsize\thepoemline}}%
    {}%
  \refstepcounter{poemline}%
}
%    \end{macrocode}
%
% \end{macro}
%
%
% \subsection{The main environment}
%
% \begin{environment}{xpoem}
%
% The \env{xpoem} environment is where the nastiness really starts. 
% Actually, the early bit is simple enough.
%
% This environment has a funny name, so that users and style designers can
% define a usable `poem' environment the way they want.  Typically this
% will involve playing with some parameters, maybe setting up some active
% characters in a funny way, and probably adding a list environment to
% provide appropriate indentation on the left and right sides.
%
%    \begin{macrocode}
\def\xpoem{%
%    \end{macrocode}
%
% The first thing to do is to reset the line number counter.
%
%    \begin{macrocode}
  \global\c@poemline\z@%
%    \end{macrocode}
%
% Now for some hookery -- the internal |\poem@printline| command will do
% the job of deciding whether to print a line number or not on the current
% line.  Unless otherwise disabled, this will be equal to |\poemline|.
%
%    \begin{macrocode}
  \global\let\poem@printline\poemline%
%    \end{macrocode}
%
% The |\nonumber| command, which is also used by \env{eqnarray},\footnote{^^A
%   Just a plug: check out the improved \env{eqnarray} environment in the
%   \package{mathenv} package!}
% suppresses numbering of the current line by changing |\poem@printline|.
% It will be reset by the next line end, so it only applies to a single line.
%
%    \begin{macrocode}
  \def\nonumber{\global\let\poem@printline\@empty}%
%    \end{macrocode}
%
% The |\title| and |\author| commands need redefining.  I'll set these
% equal to some user-configurable commands below.
%
%    \begin{macrocode}
  \let\title\poemtitle%
  \let\author\poemauthor%
%    \end{macrocode}
%
% Do some nasty things to make lists work properly.
%
%    \begin{macrocode}
  \global\@inlabelfalse%
  \global\@newlistfalse%
%    \end{macrocode}
%
% Now it's time to start the alignment.  I'll clear the |\everycr| tokens,
% and set up the |\\| command.  I'll make |\par| expand to nothing exciting,
% so that blank lines in poems won't mess anything up, and set up the
% `outside' meaning of |\nl|.
%
%    \begin{macrocode}
  \everycr{}%
  \let\\\poem@cr%
  \def\nl{\poem@nl}%
  \global\let\poem@nl\poem@donl%
  \let\par\@empty%
%    \end{macrocode}
%
% Now to set the widths of the poem.  |\poem@width| is read from the |.aux|
% file from the \emph{last} time the poem was typeset, and is used to set
% the width \emph{this} time, while |\poem@thiswidth| is initially zero,
% and is set up as we go through \emph{this} time, and will be used to
% set the actual poem width \emph{next} time.  Is that clear?  No?  Oh, well.
%
%    \begin{macrocode}
  \expandafter\poem@getwidth\expandafter{\the\c@poem@count}%
  \global\poem@thiswidth\z@%
  \global\poem@longfalse
%    \end{macrocode}
%
% Now some hacking to position the poem horizontally.  I need to inspect the
% current list margins, so as to make it look right.  I'll set |\dimen@| to
% be the size of the right hand margin.
%
%    \begin{macrocode}
  \dimen@\hsize%
  \advance\dimen@-\@totalleftmargin%
  \advance\dimen@-\linewidth%
%    \end{macrocode}
%
% Now for some silly little things before I really get going.  Leave some
% vertical space, and step the counter ready for the first line.
%
%    \begin{macrocode}
  \bigskip%
  \stepcounter{poemline}%
  \def\@currentlabel{\p@poemline\thepoemline}%
%    \end{macrocode}
%
% Other things may want to add their declarations here.  I'll provide a hook.
%
%    \begin{macrocode}
  \poem@hook%
%    \end{macrocode}
%
% Now start the first poem chunk and give control to the user.
%
%    \begin{macrocode}
  \poem@startchunk%
}
%    \end{macrocode}
%
% That's the start of the environment done; what happens at the end?  Well,
% some fairly simple things, actually.
%
%    \begin{macrocode}
\def\endxpoem{%
%    \end{macrocode}
%
% First of all, I forcibly truncate this chunk of poem.
%
%    \begin{macrocode}
  \nl%
  \poem@endchunk%
%    \end{macrocode}
%
% Now, if the poem is longer than the chunk size, I'll add it to the new
% width list.  If it's shorter than the chunk size, there's no need to do
% this, since \TeX\ will always work out the correct width `in time'.
%
%    \begin{macrocode}
  \ifnum\c@poemline>\poemchunksize\poem@longtrue\fi%
  \ifpoem@long%
    \expandafter\poem@setwidth\expandafter{\the\c@poem@count}%
  \fi%
%    \end{macrocode}
%
% Now I'll step the poem counter, leave a little gap, and end the
% environment.
%
%    \begin{macrocode}
  \global\advance\c@poem@count\@ne%
  \bigskip%
}
%    \end{macrocode}
%
% \end{environment}
%
% \begin{macro}{\poem@hook}
%
% The hook used above in |\poem| starts off empty.  Macro packages can add
% to it later.
%
%    \begin{macrocode}
\def\poem@hook{}
%    \end{macrocode}
%
% \end{macro}
%
% \begin{macro}{\poem@addtohook}
%
% Packages add to that hook by saying
% \syntax{"\\poem@addtohook{"<declarations>"}"}.  This is truly trivial.
%
%    \begin{macrocode}
\def\poem@addtohook#1{%
  \expandafter\def\expandafter\poem@hook\expandafter{\poem@hook#1}%
}
%    \end{macrocode}
%
% \end{macro}
%
% I'll take a break from the deep hacking for a while, and implement some
% style things.  These commands should be redefined to alter the style of
% the poems.  (I've tried hard to make them as simple as possible.)
%
% \begin{macro}{\poemtitle}
%
% Poem titles are large, bold, and centred.  The |\nl| command starts a new
% row if necessary.  I want to avoid a page break after the title, for
% obvious reasons.
%
%    \begin{macrocode}
\providecommand{\poemtitle}[1]{%
  \nl%
  \nonumber%
  \hfill\normalfont\large\bfseries#1\hfill%
  \\*[\bigskipamount]%
}
%    \end{macrocode}
%
% \end{macro}
%
% \begin{macro}{\poemauthor}
%
% Authors are typeset in italics, right aligned.
%
%    \begin{macrocode}
\providecommand{\poemauthor}[1]{%
  \nl*[\smallskipamount]%
  \nonumber%
  \hfill\normalfont\itshape#1%
  \\%
}
%    \end{macrocode}
%
% \end{macro}
%
%
% \subsection{Poem chunk handling}
%
% Poems are divided into chunks to save \TeX's memory.  Chunks are started
% like this:
%
% \begin{macro}{\poem@startchunk}
%
%    \begin{macrocode}
\def\poem@startchunk{%
%    \end{macrocode}
%
% Reset the `lines left' counter.  When this hits zero, I end the chunk and
% start another one.
%
%    \begin{macrocode}
  \global\poem@linesleft\poemchunksize%
%    \end{macrocode}
%
% Now for the alignment itself.  The poem is centred by tabskip glue around
% its first column.  There are an infinite number of zero-width columns off
% to the right, in which the line numbers are typeset (this avoids problems
% if users accidentally tab over to the next column).
%
% The `main' column is a bit odd.  It reads the text into a box, which is
% global to preserve save stack space, and then calls a macro |\poem@doline|
% to typeset the text in the box correctly.
%
%    \begin{macrocode}
  \skip@\@totalleftmargin%
  \advance\skip@\poemleftskip%
  \tabskip\skip@%
  \halign to\hsize\bgroup%
    \global\let\poem@nl\poem@cr%
    \global\setbox\@ne\hbox{{\ignorespaces##\@maybe@unskip}}\poem@doline%
    \tabskip\@centering&&%
    \poem@rightcolumn\hbox{{##}}\tabskip\dimen@\cr%
}
%    \end{macrocode}
%
% \end{macro}
%
% \begin{macro}{\poem@endchunk}
%
% This is really easy.  I end the line, in case it hasn't been ended already
% (although it should have been), and end the alignment.
%
%    \begin{macrocode}
\def\poem@endchunk{%
  \crcr%
  \noalign{\global\dimen@i\prevdepth\nointerlineskip}%
  \omit\hb@xt@\poem@width{}\cr%
  \egroup%
  \prevdepth\dimen@i%
}
%    \end{macrocode}
%
% \end{macro}
%
%
% \subsection{Typesetting poem lines}
%
% \begin{macro}{\poem@doline}
%
% This is where most of the real mess lies.  Given a line of doggerel in
% box~1, I must typeset it beautifully.
%
%    \begin{macrocode}
\def\poem@doline{%
%    \end{macrocode}
%
% In order to know whether I need to split the line, I must know how wide
% the line number is.  (Judging from the books I've seen, lines are allowed
% to encroach on the space allocated to line numbers, as long as there isn't
% a number on this line.  Maybe as a future extension, I could decide whether
% it might be better to suppress this line, and maybe force a number for
% the next one since it won't fit here.)
%
% Anyway, I'll do this the easy way.  I'll work out the width of the line
% number, and subtract it from the basic line width.
%
%    \begin{macrocode}
  \dimen@\linewidth%
  \global\setbox\@labels\hbox{\poem@printline}%
  \advance\dimen@-\wd\@labels%
%    \end{macrocode}
%
% If the width of the doggerel is wider than |\dimen@|, I must split the
% text over more than one line, or at least I must try to.  (\TeX\ may
% be able to squeeze the text onto one line by shrinking the glue, so I've
% got to watch out for this possibility.)
%
%    \begin{macrocode}
  \ifdim\wd\@ne>\dimen@%
%    \end{macrocode}
%
% I'll now put the text in a vbox, so I can play with it.  The parshape
% is set up so that the first line misses the line number (if there is
% one), while subsequent lines are indented, but take up the full available
% width of the page.  The text is not indented (just to make sure).
%
% The messing with |\leftskip| and the initial kern provides the indentation,
% and saves a little arithmetic.  There is a more plausible historical reason
% for it too.
%
%    \begin{macrocode}
    \global\setbox\@ne\vtop{%
      \parshape\tw@ \z@\dimen@ \z@\linewidth%
      \leftskip3em%
      \noindent%
      \kern-3em%
      \unhbox\@ne%
      \@@par%
    }%
%    \end{macrocode}
%
% Since table cells are set in LR mode, the baselineskip glue will be set
% all wrong underneath this line.  I also need to set |\poem@lastwidth|
% correctly.  I'll copy the box to another box, and pick off the bottom line
% so I can peek inside.
%
% I'll set |\poem@prevdepth| from the depth of the box (this will be set
% properly at the end of the line).  I'll also rip that box apart, remove
% the |\parfillskip| glue, and rebox it in an attempt to calculate
% |\poem@lastwidth|.  This isn't perfect, since the line might actually be
% shrinking instead of stretching.  This is unlikely, though.
%
%    \begin{macrocode}
    \global\setbox\thr@@\vbox{%
      \unvcopy\@ne%
      \global\setbox\thr@@\lastbox%
      \global\poem@prevdepth\dp\thr@@%
      \global\setbox\thr@@\hbox{\unhbox\thr@@\unskip}%
      \global\poem@lastwidth\wd\thr@@%
    }%
%    \end{macrocode}
%
% Now that's done, I can output the box.  I'll clear box~3, which I
% vandalised above.  I also know that the line was too long, so I can
% set the poem widths to |\linewidth| with impunity.
%
%    \begin{macrocode}
    \box\@ne%
    \global\setbox\thr@@\box\voidb@x%
    \global\poem@width\linewidth%
    \global\poem@thiswidth\linewidth%
  \else%
%    \end{macrocode}
%
% If it fits, I can update the widths if necessary, set |\poem@lastwidth|,
% and spew out the text.  Finally, I'll set |\poem@prevdepth| to a sentinel
% value meaning `don't change'.
%
%    \begin{macrocode}
    \ifdim\wd\@ne>\poem@width\global\poem@width\wd\@ne\fi%
    \ifdim\wd\@ne>\poem@thiswidth\global\poem@thiswidth\wd\@ne\fi%
    \global\poem@lastwidth\wd\@ne%
    \unhbox\@ne\hfil%
    \global\poem@prevdepth\maxdimen%
  \fi%
}
%    \end{macrocode}
%
% \end{macro}
%
%
% \subsection{Starting a new line}
%
% There are two different routes to starting new lines.  The |\\| command
% always starts a new line.  The command |\nl| will work out if
% the current line hasn't been started yet, and behaves appropriately.
%
% \begin{macro}{\poem@cr}
%
% The |\poem@cr| macro implements the |\\| command and the |\nl|
% command once a new line has been started.
%
% First, I need to pick out the optional arguments.  All the standard hacking
% for doing newlines in alignments appears here.  If you want detailed
% commentary, look somewhere else -- this is humdrum stuff now.
%
%    \begin{macrocode}
\def\poem@cr{%
  \relax%
  \global\let\poem@nl\poem@donl%
  \iffalse{\fi\ifnum0=`}\fi%
  \@ifstar{\poem@cr@i\@M}{\poem@cr@i\z@}%
}
\def\poem@cr@i#1{\@ifnextchar[{\poem@cr@ii{#1}}{\poem@cr@ii{#1}[\z@]}}
%    \end{macrocode}
%
% That's the standard hacking over.  Here's the tricky bit.
%
%    \begin{macrocode}
\def\poem@cr@ii#1[#2]{%
  \ifnum0=`{}\fi%
%    \end{macrocode}
%
% First of all, I must clear the command which raises an error in the right
% hand column.  Then I'll enter the column and insert the line number (which
% was stored in |\@labels| for safekeeping).
%
%    \begin{macrocode}
  \global\let\poem@rightcolumn\relax%
  &\relax%
  \llap{\unhbox\@labels}%
%    \end{macrocode}
%
% Now I'll reset the various hooks and things ready for the next like.
%
%    \begin{macrocode}
  \global\let\poem@printline\poemline%
  \global\let\poem@rightcolumn\poem@@rightcolumn%
%    \end{macrocode}
%
% Now to decide whether to start a new chunk.  I'll decrement the counter,
% and if it reaches zero, I'll end that chunk and start a new one.
%
%    \begin{macrocode}
  \global\advance\poem@linesleft\m@ne%
  \ifnum\poem@linesleft=\z@%
    \poem@endchunk%
    \expandafter\poem@startchunk%
  \else%
    \expandafter\cr%
  \fi%
%    \end{macrocode}
%
% Finally, if I had a split line, I must change the |\prevdepth| setting to
% keep everyone happy.
%
%    \begin{macrocode}
  \noalign{%
    \addpenalty{#1}%
    \vskip#2%
    \ifdim\poem@prevdepth=\maxdimen\else\prevdepth\poem@prevdepth\fi%
  }%
}
%    \end{macrocode}
%
% \end{macro}
%
% \begin{macro}{\poem@donl}
%
% The |\poem@nl| macro implements |\nl| during those `in-between' times
% outside of a line of doggerel.  This is actually spectacularly easy.
%
%    \begin{macrocode}
\def\poem@donl{%
  \noalign{\ifnum0=`}\fi%
  \@ifstar{\poem@donl@i{\addpenalty\@M}}{\poem@donl@i{}}%
}
\def\poem@donl@i#1{%
  \@ifnextchar[{\poem@donl@ii{#1}}{\poem@donl@ii{#1}[\z@]}%
}
\def\poem@donl@ii#1[#2]{%
  #1%
  \addvspace{#2}%
  \ifnum0=`{\fi}%
}
%    \end{macrocode}
%
% \end{macro}
%
%
% \subsection{Other things}
%
% Well, that's all that I actually need to supply; everything else can be
% added over the top.
%
% \begin{macro}{\splitline}
%
% Some books appear to split lines, starting the second where the first
% ends.  This is easy to handle with the |\splitline| command.
%
%    \begin{macrocode}
\def\splitline{\nl\nonumber\kern\poem@lastwidth\ }
%    \end{macrocode}
%
% \end{macro}
%
% \begin{macro}{\stanza}
%
% New stanzas are started using the |\stanza| command, oddly enough.  There's
% a problem, though: to number, or not to number?  Following the example of
% \LaTeX's sectioning commands, I'll not number if there's a following $*$.
% I don't really think that this is the right thing to do, since unnumbered
% stanzas are much more common than numbered ones.  This is actually a real
% pain.
%
% Anyway, if I'm going to handle numbered stanzas, I'll need a counter.
%
%    \begin{macrocode}
\newcounter{stanza}
%    \end{macrocode}
%
% Whatever happens, I'll start by adding in some vertical space above the
% stanza.  Then I'll see if there's a following $*$.  If so, step the counter
% and typeset the number; otherwise do nothing.  However, there's a snaglet
% here: |\@ifstar| will do assignments and things, and start the next row of
% the alignment prematurely.  I'll do the work in a |\noalign| to avoid
% problems.  (Yuk.)
%
%    \begin{macrocode}
\def\stanza{%
  \nl%
  \noalign{\ifnum0=`}\fi%
  \@ifstar{%
    \stanza@i{}%
  }{%
    \stanza@i{\global\advance\c@stanza\@ne\labelstanza}%
  }%
}
%    \end{macrocode}
%
% OK\@.  Now I have to see if there's an optional argument.  I'm still safely
% inside that |\noalign|, remember.
%
%    \begin{macrocode}
\def\stanza@i#1{\@ifnextchar[{\stanza@ii{#1}}{\stanza@ii{#1}[]}}
%    \end{macrocode}
%
% I can now read the argument, and decide what actually needs to be done.
%
%    \begin{macrocode}
\def\stanza@ii#1[#2]{%
%    \end{macrocode}
%
% I want to be able to allow |\label|s inside the optional argument.
% However, I also want to be able to see whether the number and/or title
% is `empty', bearing in mind that the title may contain just a |\label|,
% which shouldn't alter the spacing; which means really that I ought to put
% them into boxes and measure them.  But this stops |\refstepcounter|'s
% setting of |\@currentlabel| (in the `number' box) being noticed by the
% possible |\label| command in the other box.  I \emph{could} say something
% like
% \begin{listing}
%\refstepcounter{stanza}
%\addtocounter{stanza}{-1}
% \end{listing}
% which will do what I want, but defining |\@currentlabel| by hand is
% considerably easier, and more efficient.
%
%    \begin{macrocode}
  \def\@currentlabel{\p@stanza\thestanza}%
  \sbox\z@{#1}%
  \sbox\tw@{\stanzaname{#2}}%
%    \end{macrocode}
%
% There are essentially four possibilities:
% \begin{itemize}
% \item There's nothing to typeset at all.  This is easy: don't typeset
%       anything.
% \item There's a number, but no title.
% \item There's a title, but no number.
% \item There's both a title \emph{and} a number.
% \end{itemize}
% The tricky bit is the last possibility, since I don't know how the two
% will be separated.  Oh, well: I'll just have to use a load of user macros.
%
% As a first attempt, I'll put the thing to typeset into box~0.  This is
% fairly simple.  If there's a title, then I check if there's a number too:
% if so, I'll combine them both into box~0; otherwise I can just copy the
% box over.  If there's anything to typeset at this point, it'll be in
% box~0.  However, I'm currently in a |\noalign|, and that introduces a
% level of grouping.  So I'll then move the box into box~1, which is global.
%
%    \begin{macrocode}
  \ifdim\wd\tw@>\z@%
    \ifdim\wd\z@>\z@%
      \global\setbox\@ne\hbox{\stanzacombine{\unhbox\z@}{\unhbox\tw@}}%
    \else%
      \global\setbox\@ne\box\tw@%
    \fi%
  \else%
    \global\setbox\@ne\hbox{\unhbox\z@\unhbox\tw@}%
  \fi%
%    \end{macrocode}
%
% That's all the messy processing done.  Now I can just typeset the
% title.
%
%    \begin{macrocode}
  \ifnum0=`{\fi}%
  \stanzaspace%
  \ifdim\wd\@ne>\z@%
    \nonumber%
    \stanzatitle{\unhbox\@ne}%
  \else
  \fi%
%    \end{macrocode}
%
% That's it!  I'm done.
%
%    \begin{macrocode}
}
%    \end{macrocode}
%
% \end{macro}
%
% The |stanza| counter must be reset at the beginning of the poem.
%
%    \begin{macrocode}
\poem@addtohook{\global\c@stanza\z@}
%    \end{macrocode}
%
% Now for some formatting defaults.  This is easy stuff.
%
%
% \begin{macro}{\thestanza}
%
% Obviously, this is the default way to typeset a stanza number.
%
%    \begin{macrocode}
\renewcommand{\thestanza}{\Roman{stanza}}
%    \end{macrocode}
%
% \end{macro}
%
% \begin{macro}{\labelstanza}
%
% This macro is responsible for giving the stanza number to be typeset in
% the title line.
%
%    \begin{macrocode}
\providecommand{\labelstanza}{\textsc{\roman{stanza}}}
%    \end{macrocode}
%
% \end{macro}
%
% \begin{macro}{\stanzaname}
%
% This is responsible for typesetting the stanza's name.  This is easy.
%
%    \begin{macrocode}
\providecommand{\stanzaname}[1]{\textsc{#1}}
%    \end{macrocode}
%
% \end{macro}
%
% \begin{macro}{\stanzacombine}
%
% This is how to combine stanza numbers and names.  I'll just leave a space.
%
%    \begin{macrocode}
\providecommand{\stanzacombine}[2]{#1\quad#2}
%    \end{macrocode}
%
% \end{macro}
%
% \begin{macro}{\stanzaspace}
%
% Separate the previous stanza from a new one.  This isn't done in
% |\stanzatitle| because there may not be a title.
%
%    \begin{macrocode}
\providecommand{\stanzaspace}{\nl[\medskipamount]}
%    \end{macrocode}
%
% \end{macro}
%
% \begin{macro}{\stanzatitle}
%
% Finally, this is the typesetting of the stanza title in its entirety.
%
%    \begin{macrocode}
\providecommand{\stanzatitle}[1]{%
  \hfill#1\hfill\\%
}
%    \end{macrocode}
%
% \end{macro}
%
%
% \hfill Mark Wooding, \today
%
% \Finale
%
\endinput
