Subject: STY.NUMLINE

From: [email-masked]
Date: Sun, 11 Apr 1993 21:06:38 CDT

%%% ====================================================================
%%%  @LaTeX-style-file{
%%%     author          = "Michal Jaegermann and James Fortune",
%%%     version         = "1.2",
%%%     date            = "03 April 1993",
%%%     time            = "17:00:30 MST",
%%%     filename        = "numline.sty",
%%%     address         = "10923 36Av, Edmonton,
%%%                        Alberta, CANADA T6J 0B7",
%%%     telephone       = "403 438 7012",
%%%     checksum        = "08448 304 1358 11653",
%%%     email           = "[email-masked] and
%%%                        [email-masked] (Internet)",
%%%     codetable       = "ISO/ASCII",
%%%     keywords        = "line numbers",
%%%     supported       = "yes (sort of)",
%%%     abstract        = "LaTeX style file for putting line numbers on
%%%                        margins of at least some documents which will
%%%                        survive such treatment.  It works modifying
%%%                        LaTeX output routine, so do not expect that
%%%                        this will work on anything but simple text!
%%%                        If it does then you are very lucky person.
%%%
%%%                        In some situations you should be able to
%%%                        adjust it for special needs but do not expect
%%%                        miracles.  For plain TeX try EDMAC by Dominik
%%%                        Wujastyk.
%%%
%%%                        This style provides:
%%%                          - continuous line numbering for the whole
%%%                            document or, if \lnumpagetrue, restarted
%%%                            on every page
%%%                          - numbers on alternate margins when 'twoside'
%%%                            document option is in force
%%%                          - ajustable interval between line numbers
%%%                            given by a value of \lineCountInterval counter
%%%                          - settable ranges of numbered lines
%%%                            with \nlinesBoundary macro
%%%                          - changing line witdth together with indent.sty
%%%                        See comments and examples below.",
%%%     docstring       = "The checksum field above contains a CRC-16
%%%                        checksum as the first value, followed by the
%%%                        equivalent of the standard UNIX wc (word
%%%                        count) utility output of lines, words, and
%%%                        characters.  This is produced by Robert
%%%                        Solovay's checksum utility.",
%%%  }
%%% ====================================================================
%
% HISTORY:
%
% Based upon the TUGboat article ``Output Routines: Examples and Techniques.''
% by David Salomon that appeared in Volume 11 (1990), Nos. 1, 3 and 4.
%
% Started by James Fortune as altnline.sty with some help and advice
% from MJ which later hacked it for quite a while.
%
% Changes to version 1.0
%
% * Protect internal macros by including '@' in their names.
% * Split countlines and duplicate operations from a single loop
%   (does not work that way).
%
% Changes to version 1.1 (mj)
%
% * Added logic to print line numbers only every \lineCountInterval
% * Added a way to set up ONE range of numbered lines; use \nlinesBoundary
%   to do that. (It is possible to sprinkle your text with \nlinesBoundary
%   commands and they may even do the right thing if you will put them
%   in right places - but this is a hack.)
% * Miscellaneous cleanup
%
% Changes to 1.2 (mj)
% * Prevent 'Output routine didn't use all of \box255' messages
% * Add code to handle, in a fashion, indentation generated by indent.sty
% * Add switch to restart numbering on every page
% * Make switching enumeration margins dependent on 'twoside' option

% USER INTERFACE:
%
% In your document you have an access to:
%   * a conditional \lnumpage which can be set with \lnumpagetrue
%     or \lnumpagefalse (default); when true line numbers are reset
%     on every page;
%   * a counter \lineCountInterval (default 5) to set interval between
%     line numbers
%   * a command \nlinesBoundary to set boundaries for line numbering;
%     example of use:
%          \nlinesBoundary{12}, or \nlinesBoundary[50]{12}
%     with \nlinesBoundary[<optional upper limit>]<lower limit>
% Any negative number for an upper limit means number to the very end.
% This is a default!

% INDENTING:
% Any changes in line width caused by indent.sty have the same effect.
% So \begin{indentation}{2em}{2em} and \begin{indentation}{4em}{0pt}
% are equivalent.  Positioning of indented lines can be only performed
% by modifications in a definition of \@duplicate.  Check examples
% below.

%
% various counters
%
\newcount\lineCountInterval % used to determine how often lin@Count is printed
\lineCountInterval=5
%
\newcount\lin@CountInit     % used to establish lineCount of first line on page
\lin@CountInit=\z@
\newcount\lin@CountStart    % don't print line numbers below this value
\lin@CountStart=\@ne
\newcount\lin@CountFinish   % don't print line numbers higher than this
\lin@CountFinish=\m@ne
%
\newcount\lin@sSoFar
% remainder from division of \lin@sSoFar by \lineCountInterval
\newcount\total@Rem
% current value of remainder used to produce line numbers
\newcount\lin@rem

%
% A command to set boundaries for line numbering.
%
\def\nlinesBoundary{\@ifnextchar[{\nlin@sBoundary}{\nlin@sBoundary[\m@ne]}}
\edef\nlin@sBoundary[#1]#2{%
  \global\lin@CountFinish=#1\relax
  \global\lin@CountStart=#2\relax}

%
% if's
%
\newif\iflnumpage % if true restart line numbers on every page
%
\newif\ifa@@lnum  % do we really want to print that line number?

%
% make page easier to break into lines
%
\def\zero@ToSp{\parskip=\@ne sp plus\@ne pt
  \def\vfil{\vskip1sp plus1fil}
  \def\vfill{\vskip1sp plus1fill}
  \abovedisplayshortskip=\@ne sp plus3pt
  \postdisplaypenalty=\@ne
  \interlinepenalty=\@ne}

\zero@ToSp

% It is possible to change a "look" of numbering by modifications
% of this macro; in particular calculations below allow to start
% with \lin@CountInit different from 0

\def\resetlin@sSoFar{%
  \global\lin@sSoFar=\lin@CountInit
  \total@Rem=\lin@CountInit
  \divide\total@Rem by\lineCountInterval
  \multiply\total@Rem by-\lineCountInterval
  \global\advance\total@Rem by\lin@CountInit}

\resetlin@sSoFar

\newcount\lin@Count
\newif\ifAnyleft \newcount\pen
\def\count@lines{%
  \global\lin@Count=\lin@sSoFar
  \loop \Anyleftfalse
    \ifdim\lastskip=\z@ \ifdim\lastkern=\z@ \ifnum\lastpenalty=\z@
      \setbox\z@=\lastbox
    \ifvoid\z@
    \else \Anylefttrue \global\advance\lin@Count by\@ne
		       \global\advance\total@Rem by\@ne
                       \ifnum\total@Rem=\lineCountInterval
                          \global\total@Rem=\z@
                       \fi\fi
    \else \Anylefttrue \unpenalty \fi
    \else \Anylefttrue \unkern \fi
    \else \Anylefttrue \unskip \fi
  \ifAnyleft \repeat}

\def\@duplicate{%
  \loop \Anyleftfalse
    \ifdim\lastskip=\z@ \ifdim\lastkern=\z@ \ifnum\lastpenalty=\z@
      \global\setbox\z@=\lastbox \ifvoid\z@ % end of breakup loop
    \else \Anylefttrue                  % box present
      \ifnum\lin@rem=\z@                % if remainder non-zero we do not care
        \lin@rem=\lineCountInterval
        \ifnum\lin@Count<\lin@CountStart
          \a@@lnumfalse
        \else
          \ifnum\lin@CountFinish<\z@    % no upper bound
            \a@@lnumtrue                % print it
          \else
            \ifnum\lin@Count>\lin@CountFinish
              \a@@lnumfalse
            \else
              \a@@lnumtrue              % this is the ticket
            \fi
          \fi
        \fi
      \else
         \a@@lnumfalse
      \fi
% Position shorter lines to keep indentation.  Only a line length
% is important
% This prints indented lines flush right margin
      \setbox\z@=\vbox{\hbox to\textwidth{\hfil\box\z@}}
% This for centered lines
%     \setbox\z@=\vbox{\hbox to\textwidth{\hfil\box\z@\hfil\relax}}
% For other variants you are on your own!!
      \ifa@@lnum
         \append@line
      \else
         \global\setbox\@ne=\vbox{\box\z@\unvbox\@ne}
      \fi
      \advance\lin@Count\m@ne
      \advance\lin@rem by\m@ne\fi
    \else \Anylefttrue                  % penalty present
      \pen=\lastpenalty
      \global\setbox\@ne=\vbox{\penalty\pen\unvbox\@ne}\unpenalty\fi
    \else \Anylefttrue                  % kern present
      \dimen\z@=\lastkern
      \global\setbox\@ne=\vbox{\kern\dimen\z@\unvbox\@ne}\unkern \fi
    \else \Anylefttrue                  % skip present
      \skip\z@=\lastskip
      \global\setbox\@ne=\vbox{\vskip\skip\z@\unvbox\@ne}\unskip \fi
    \ifAnyleft \repeat}

\def\append@line{%  attach line number
  \setbox2=\vbox to \z@{\smash{\footnotesize\the\lin@Count}}
  \wd2=25pt                           % that much of space for a line number
  \if@twoside			      % we are printing twoside
    \ifodd\count\z@                   % on the right margin for odd pages
       \setbox\z@=\hbox{\box\z@\rlap{\rule{\wd2}{\z@}\box2}}
    \else			      % and on the left for even
       \setbox\z@=\hbox{\llap{\box2}\box\z@}
    \fi
  \else                               % one sided printing
    \setbox\z@=\hbox{\llap{\box2}\box\z@} % left margin only
  \fi
  \global\setbox\@ne=\vbox{\box\z@\unvbox\@ne}}% add this to a reconstructed
					       % page

% Rainer showed me how to save the previous \output.  Thanks Rainer. (jaf)
\newtoks\LaTeX@output
\LaTeX@output = \expandafter{\the\output}

\newbox\brk

\output={\ifnum\outputpenalty <-\@M
    \output={\LaTeX@output}   % Use old output definition if page
                              % is not to be output
  \else
    \lin@Count=\lin@sSoFar
    \setbox\brk=\vbox{\unvcopy\@cclv\count@lines}
             \global\setbox\@ne=\vbox{}
             \lin@rem=\total@Rem
    \iflnumpage
      \resetlin@sSoFar
    \else
      \global\lin@sSoFar=\lin@Count
    \fi
    \setbox\brk=\vbox{\unvcopy\@cclv\@duplicate}
    \ifdim\ht\brk>\z@\message{Incomplete breakup}\fi
    \ht\@ne=\z@\dp\@ne=\z@
    \global\setbox\@cclv=\vbox to\vsize{\unvbox\@ne}% attempt to get glues back
    \@makecol\@opcol
  \fi
\setbox\brk=\box\@cclv
\deadcycles=\z@
}

\endinput

% Sample input - add more of the same to really see effects.

\documentstyle[numline%
,indent%    Comment out this line if you do not have indent.sty
%      %    but do not use indentation environment in such case
%,twoside%  Uncomment this line for 'switchin sides' numbers
]{article}

%\lnumpagetrue % Uncomment this to restart lines numbers at every page
\begin{document}

This is the test.  This is the test.  This is the test.  This is the
test.  This is the test.  This is the test.  This is the test.  This
is the test.  This is the test.  This is the test.  This is the test.

% This gives only a length of indented line - not a position.
% See comments in numline.sty
\begin{indentation}{3em}{0cm}

This is the test.  This is the test.  This is the test.  This is the
test.  This is the test.  This is the test.  This is the test.  This
is the test.  This is the test.  This is the test.  This is the test.
This is the test.  This is the test.  This is the test.  This is the
test.  This is the test.  This is the test.  This is the test.

\end{indentation}

This is the test.  This is the test.  This is the test.  This is the
test.  This is the test.  This is the test.  This is the test.  This
is the test.  This is the test.  This is the test.  This is the test.
This is the test.  This is the test.  This is the test.

\end{document}