summaryrefslogtreecommitdiff
path: root/macros/latex209/contrib/chbars/chbars.sty
diff options
context:
space:
mode:
Diffstat (limited to 'macros/latex209/contrib/chbars/chbars.sty')
-rw-r--r--macros/latex209/contrib/chbars/chbars.sty1000
1 files changed, 1000 insertions, 0 deletions
diff --git a/macros/latex209/contrib/chbars/chbars.sty b/macros/latex209/contrib/chbars/chbars.sty
new file mode 100644
index 0000000000..245f9e5459
--- /dev/null
+++ b/macros/latex209/contrib/chbars/chbars.sty
@@ -0,0 +1,1000 @@
+% This is CHBARS.STY as of Aug '92
+% -*-LaTeX-*-
+%---------------------------------------------------------
+% (c) 1989 by J.Schrod. copy conditions see below.
+
+%
+% Macro package for creating changebars in LaTeX.
+% MAKEPROG will ``weave'' this file into documentation that can be LaTeX'ed.
+%
+% documented in LaTeX (for Anne and Chris)
+
+%
+% VERSION HISTORY (MSCF -- most significant change first)
+%
+% DATE PERSON REMARK
+% 92-08-15 -rlb Use change bars in this document to mark major changes;
+% so now you can see for yourself what they are.
+% 92-07-28 -rlb Run through a spelling checker before distributing.
+% 92-01-15 -rlb 1) Keep \maxdeadcycles the same; just
+% don't count calls to output for change processing.
+% 2) Allow setting the change bar width.
+% 3) Some typos and rewording of some of the comments.
+% 4) Allow setting change bar width. Interface copied
+% from changebars.sty
+% 5) Allow changebars to be on the left as well as
+% the right.
+% 6) localize some variables global definitions now
+% start with cb_.
+% 7) Chain onto existing \output routine rather than assume
+% \plainoutput.
+% And miscellaneous minor hacks.
+% 89-10-09 -js converted to LaTeX (progltx)
+% 89-09-25 -js repaired \mark processing in horizontal mode
+% 89-08 -js first version (for EuroTeX89 in Karlsruhe)
+%
+
+% author's current address:
+%
+% Detig$\,\cdot\,$Schrod \TeX{}sys
+% Joachim Schrod
+% Kranichweg 1
+%
+% D-6074 R\"odermark-Urberach
+% FR Germany
+%
+% Tel. (+6074) 1617
+% Bitnet: XITIJSCH@DDATHD21
+
+
+
+% should be progtex...
+%%%%
+%%%%
+%%%% These TeX macros were documented with the documentation system
+%%%% MAKEPROG and automatically converted to the current form.
+%%%% If you have MAKEPROG available you may transform it back to
+%%%% the original input: Remove every occurence of three percents
+%%%% and one optional blank from the beginning of a line and remove
+%%%% every line which starts with four percents. The following lex
+%%%% program will do this:
+%%%%
+%%%% %%
+%%%%
+%%%% ^%%%\ ? ;
+%%%% ^%%%%.*\n ;
+%%%%
+%%%% MAKEPROG may be obtained over the net from the Bitnet-Listserver
+%%%% LISTSERV@DHDURZ1 (filelist WEBWARE), from tuglib@science.utah.edu,
+%%%% or via ftp from june.cs.washington.edu.
+%%%%
+%%%%
+%%% \documentstyle[progltx,chbars,a4-9]{article}
+
+
+%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%% %
+%%% % local macros
+%%% %
+
+%%% \let\mc=\small % for names like GNU
+
+%%% \def\PS{{\sc PostScript}}
+%%% \def\DVI{{\tt DVI}}
+%%% \def\GNU{{\mc GNU}}
+
+%%% \chardef\bs=`\\
+
+%%% %
+%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+
+
+%%% \begin{document}
+%%% \tableofcontents
+
+%%% \title{Changebars without {\tt \bs{}special}'s}
+%%% \author{\sc Joachim Schrod}
+
+%%% \newcommand{\changedate}{Aug 15, 1992}
+%%% \date{Revised last on \changedate\footnote{by {\tt rocky@watson.ibm.com}}\\
+%%% Formatted on \today}
+%%% \maketitle
+
+
+
+%%% \begin{abstract}
+%%% It is common practice to use vertical bars in the margins of a
+%%% document to mark pieces of text which have changed since the last
+%%% version(s) of this document. Such vertical bars are usually
+%%% called {\em changebars}. It has often been said that it is
+%%% impossible to produce changebars with \TeX{} without the usage of
+%%% |\special| commands (driver directives), which extend the
+%%% primitives of \TeX{}. This paper presents a \TeX{} macro file
+%%% which implements changebars without such a usage. The macro file
+%%% is written for the usage with {\sc Plain}~\TeX{} but the implementation
+%%% strategy can be used with \LaTeX{}, too with minor changes.
+
+%%% \end{abstract}
+
+
+
+%%% \chap Introduction.
+
+%%% Changebars are used to mark modified parts in existing documents. For
+%%% the usage in \TeX{} documents, there exist only solutions that use
+%%% driver/printer features by the way of inserting |\special| commands in
+%%% the \TeX{} source, e.g.\ for \PS{} drivers. This results in documents
+%%% that are no longer as freely interchangeable as the \DVI{} concept would
+%%% allow---device dependency is problematic especially for this application
+%%% that is useful for multi-authoring or standards development.
+
+%%% This macro package offers a pure \TeX{} solution. Nevertheless, it has
+%%% its restrictions, too. The page break will no longer be optimal,
+%%% because there is no strechability or shrinkability of a page
+%%% on top of the last
+%%% region of change marked. But this seems to be acceptable,
+%%% especially as the change bar feature often will be used for proof
+%%% reading and not in the final document. This restriction is the reason
+%%% why no change marks can be used on title pages or on similar
+%%% constructions. Changes in floating insertions (footnotes, figures) are
+%%% not handled. Multi-column formats such as a two-column layout
+%%% will not work. There is currently no support for nested changes.
+
+%%% The method for writing a change bar consists of three
+%%% parts: First, the output routine is signalled when the beginning
+%%% or end of a change bar setting command is encountered.
+%%% Next, the position of the changed area is found out
+%%% and fixed; the end-of-change command adds the last change bar
+%%% position, length and width to a list of all such positions,
+%%% lengths and widths of change bars that is accumulated for the current
+%%% page. Finally, when
+%%% the output routine is triggered (either asynchronously in trying
+%%% to ship out the page or synchronously when discovering that the
+%%% end of a change bar lies off the page), this list of change
+%%% bars information is used create vertical rules which are added to the page.
+%%% If the change bar is not complete, a ``virtual'' end change is
+%%% inserted, and a ``virtual'' begin change is inserted at the
+%%% beginning of the next page.
+
+%%% \beginchange
+%%% The demonstrated solution was originally written in {\sc Plain}
+%%% \TeX{}, because it was
+%%% easier and could be presented better at the Euro\TeX89 conference in
+%%% Karlsruhe. An adaptation to \LaTeX{} has been done too which
+%%% requires minor modifications to the \LaTeX's output routine.
+%%% \endchange
+
+%%% Some history. The routines were initially written by Joachim
+%%% Schrod. Around Jan.\ 1992, R.\ Bernstein added some of the features
+%%% coded in |changebars.sty| to combine the best features
+%%% of the two (and added a couple of his own). For example, the
+%%% ability to specify change bar widths, put the change bars either on the
+%%% right or left margin, specifiy the distance from the margin to the
+%%% change bar, and chain to on top of a pre-existing modified
+%%% output routine.
+%%% \beginchange
+%%% Initially, both the {\TeX} and the {\LaTeX}
+%%% versions were put into one file. However, due problems in
+%%% dealing with conditional definition of code, in particular
+%%% problems with an extra or omitted |\fi| in defining or not
+%%% |\ifr@ggedbottom|, the code was split into two.
+%%% \endchange
+%%%
+%%% The |changebars.sty| package
+%%% was written by Michael Fine and revised by Johannes Braams
+%%% and Neil Winton. One or two ideas from Thomas J.~Reid have been
+%%% used.
+
+%%% \chap GNU General Public License.
+
+%%% This program is free software; you can redistribute it and/or
+%%% modify it under the terms of the \GNU{} General Public License as
+%%% published by the Free Software Foundation; either version~2, or (at your
+%%% option) any later version.
+
+%%% This program is distributed in the hope that it will be useful, but
+%%% {\bf without any warranty\/}; without even the implied warranty of
+%%% {\bf merchantability\/} or {\bf fitness for a particular purpose}. See
+%%% the \GNU{} General Public License for more details.
+
+%%% You should have received a copy of the \GNU{} General Public License
+%%% along with this program; if not, write to the Free Software Foundation,
+%%% Inc., 675~Mass Ave, Cambridge, MA~02139, USA.
+
+
+%%% \chap User Interface.
+
+%%% \begin{newsloppy}
+%%% A changed area is described by two marks, |\beginchange| and
+%%% |\endchange|. The |\beginchange| can take an optional argument,
+%%% the bar thickness, enclosed in brackets. That is, either of the
+%%% something like |\beginchange[0.4pt]|, or |\beginchange| is valid.
+%%% In the latter case where no thickness dimension is specified, the value
+%%% of |\changebarwidth| is used. Therefore, by setting this you can
+%%% change the bar thickness used when none is given. Changing the bar
+%%% thickness might be useful in identifying different classes of changes.
+
+%%% Another pair of global values that can be set are the
+%%% logical variables
+%%% {\tt \bs chbar\-Right\-true} and {\tt \bs chbar\-Right\-false}.
+%%% These specify whether
+%%% changebars should be on the right or left. Say, if one wanted to
+%%% have the changebars always appear on the outside margin, one could
+%%% change these accordingly on each page.
+%%% \end{newsloppy}
+
+%%% Finally |\BarDistance| is the amount of place between the text margin
+%%% and the change bars. This value should normally be positive. For
+%%% change bars on the right this value is added to |\hsize|, while
+%%% for change bars on the left this value is {\em subtracted\/} from
+%%% |\hoffset|.
+
+%%% \beginprog
+\newdimen\changebarwidth \changebarwidth=1pt\relax
+\newif\ifchbarRight \chbarRightfalse
+\newdimen\BarDistance \BarDistance=2cc
+
+%%% \endprog
+
+%%% \chap Utility Routines and Programming Conventions.
+
+%%% Before we get into the nitty gritty details, we give some common
+%%% macros.
+%%%
+%%% First, we declare some shorthands for category codes. By
+%%% declaring the at sign~(`|@|') as well as the underscore~`(|_|)' as
+%%% letters we can use them in our macros. (I agree with D.~Knuth that
+%%% |\identifier_several_words_long| is more readable than
+%%% |\IdentifierSeveralWordsLong| and in every case better than |\p@@@s|.)
+%%% \beginchange
+%%% By defining the at sign to be in the letter class,
+%%% we can access {\sc Plain} \TeX's ``private''macros. By defining the
+%%% underscore to be in the letter class, we make our own private macros more
+%%% readable. But since have to
+%%% restore these category codes at the end of this macro file, we store
+%%% \endchange
+%%% their former values in the control sequences |\atcode| and |\uscode|.
+%%% This method is better than to use a group because not all macros have to
+%%% be defined global this way.
+%%%
+%%% All {\em global\/} definitions of the package are prefixed by
+%%% |cb_|. In this way, they can be easily determined. If other
+%%% packages do likewise, it is less likely that definition
+%%% names will clash between packages. (Unless the other package uses the
+%%% |cb_| prefix too, in which case there is a good chance that many
+%%% variable names will clash.)
+%%%
+%%% The {\TeX}book recommends the 255 registers be used for scratch
+%%% space, so routines use this value when a spare register is
+%%% needed. (See for example |\cb_write_bar|.)
+%%%
+
+%%% \beginprog
+\chardef\letter=11
+
+\chardef\atcode=\catcode`\@
+\chardef\uscode=\catcode`\_
+
+\catcode`\@=\letter
+\catcode`\_=\letter
+
+%%% \endprog
+
+%%% \sect Now we are ready to code the top-level routine for indicating the
+%%% beginning of a change. But first we display the banner and
+%%% version number associated with this package. If this package has
+%%% been loaded already we terminate.
+%%%
+%%% Although one can specify a bar
+%%% thickness on the |\beginchange| macro, it is at the |\endchange|
+%%% where this thickness is recorded and put on a current list of
+%%% change bar entries for the current page. It seems more natural to
+%%% specify the thickness at the beginning of the change rather than
+%%% the end. Therefore at the
+%%% |\beginchange| we merely save the value given or save the value of
+%%% |\changebarwidth| if no thickness was given.
+%%% |\cb_changebarwidth| is this saved value. Auxiliary routine
+%%% |\cb_xstart| is used to parse off the optional enclosing
+%%% brackets. (This weird name was taken from one used in |changebars.sty|.)
+
+%%% default value, that is the value when a width is not specified
+%%% is |\changebarwidth|.
+
+%%% \beginprog
+
+\@ifundefined{cb_xstart}{}{\endinput}
+\typeout{Style option `change bars' -- version 1.1a}
+
+\newdimen\cb_changebarwidth
+
+\def\beginchange{\@ifnextchar [
+ {\cb_xstart}
+ {\beginchange_\changebarwidth}}
+\def\cb_xstart[#1]{\beginchange_{#1}}
+
+%%% \endprog
+
+%%% \chap Triggering the Output Routine.
+
+%%% \beginchange
+%%% When a change bar is started or completed, we signal the output
+%%% routine in the ``usual'' way described below. Why bother the
+%%% output routine? The output routine is supposed to be thought of
+%%% as an asynchronous process which has access to the page via the
+%%% contents of box register 255. In theory, if we did not perform
+%%% actions in the output routine, it might get triggered inadvertantly,
+%%% and the output routine might modify this box register on us in the
+%%% midst of our work. The information that needs to be recorded
+%%% is the position of the beginning and end of the lines containing a
+%%% marked change region.
+
+%%% \begin{newsloppy}
+%%% The macros |\beginchange| and |\endchange| signal the output
+%%% routine. Rather than merely calling the output routine directly,
+%%% these routines signal the output routine by setting a low page penalty, i.e.,
+%%% one which tells {\TeX} that this is a really good place to break
+%%% the page. Of course, we will modify the output routine so that it
+%%% doesn't really split the page when it has been called in this fashion.
+%%% Again, the reason we signal the output routine in what seems at
+%%% first a pretty odd way, is that this is the way it is supposed to
+%%% be done. If a low penalty were not set, some
+%%% other action (if we weren't careful) might cause a penalty to be
+%%% set and thus call the output routine (recursively).
+
+%%% So that we can distinguish our calls from others, |\beginchange|
+%%% and |\endchange| reserve a range of
+%%% penalty values; he actual value is stored in |\cb_break_penalty|.
+%%% This range of values is below
+%%% $-10\,000$, the nominal value for indicating that a page should
+%%% occur now. The penalty will be in the range $|\cb_penalty_group|
+%%% \cdot 100 - 99 \ldots |\cb_penalty_group| \cdot 100$.
+%%% The output routine then decides whether it has been called
+%%% to start or end a change bar or neither. This is done with the values
+%%% |\cb_penalty_begin| and |\cb_penalty_end| that are used as the
+%%% second-to-last digit of the change penalty.
+%%% \end{newsloppy}
+
+%%% The output routine also needs to determine whether
+%%% the beginning of change bar starts in horizontal or vertical mode
+%%% so it can figure out the exact placement for the beginning of the
+%%% bar line. In horizontal mode, the change bar does
+%%% not begin at the baseline of the actual text position, but on top of the
+%%% actual line. This is marked in the last digit, an odd digit will be
+%%% used in horizontal mode.
+
+%%% Note that the values mentioned above are used as digits here that can be
+%%% concatenated. If they are not followed by an other digit they should be
+%%% terminated by |\space| to stop {\TeX}'s look-ahead scanning for
+%%% digits when reading a number.
+%%% \endchange
+
+%%% \beginprog
+\def\cb_penalty_group{-101} \def\cb_penalty_begin{0}
+\def\cb_penalty_end{1}
+
+%%% \endprog
+
+
+%%% \sect The calls to start or end a change bar, set an encoded page-break
+%%% penalty which includes an
+%%% indication of begin or end of a change bar. The variable
+%%% |\cb_break_penalty| is used to create such as special value.
+%%% The rest (|\cb_trigger_output|) is the same action
+%%% for both. The region just before the end of the changed region can be
+%%% in horizontal mode and preceded by
+%%% glue that could cause a line break, thus including the following line to
+%%% the change area as well. To avoid this unwanted behavior, the space is
+%%% saved in |\save_lastskip|, discarded in front of the mark and restored
+%%% afterwards.
+
+%%% \beginprog
+\newcount\cb_break_penalty
+
+\def\beginchange_#1{%
+ \cb_changebarwidth=#1
+ \cb_break_penalty=\cb_penalty_group\cb_penalty_begin0
+ \cb_trigger_output
+ }
+\def\endchange{{%
+ \skipdef\save_lastskip=255%
+ \ifhmode \save_lastskip=\lastskip \unskip \fi%
+ \cb_break_penalty=\cb_penalty_group\cb_penalty_end0%
+ \cb_trigger_output%
+ \ifhmode \hskip\save_lastskip \fi%
+ }}%\endchange
+%%% \endprog
+
+
+%%% \sect The next routine, |\cb_trigger_output|,
+%%% triggers calls to the output routine by setting the page-break
+%%% penalty, |\penalty|. {\TeX} may discard an |\output| invocation at
+%%% the beginning of a page. So we trigger the output routine twice, first
+%%% with a special penalty value that is 2~less than the correct value
+%%% (including the code for horizontal or vertical mode). After the first
+%%% page break, it is asserted that the current list is empty. The output
+%%% routine has to save the former page contents if necessary.
+
+%%% Next we set the penalty to the correct value. The second page break does
+%%% the real work, restores the page contents and handles the split
+%%% insertions (footnotes, figures,~\dots).
+
+%%% In horizontal mode |\spacefactor| must not be destroyed, so it is
+%%% saved and restored via local count register |\save_spacefactor|.
+
+%%% \beginprog
+
+\def\cb_trigger_output{%
+ \ifinner \errmessage{Change cannot be marked inside a box}%
+ \else{%
+ \countdef\save_spacefactor=255%
+ \ifvmode
+ \let\do_in_vmode=\relax
+ \advance \cb_break_penalty by -2
+ \else
+ \save_spacefactor=\spacefactor
+ \let\do_in_vmode=\vadjust
+ \advance \cb_break_penalty by -3
+ \fi
+ \do_in_vmode{%
+ \penalty\cb_break_penalty% first call to \output
+ \null
+ \advance \cb_break_penalty by 2
+ \penalty\cb_break_penalty% second call to \output
+ }%
+ \ifhmode \spacefactor=\save_spacefactor \fi
+ }%
+ \fi
+ }% cb_trigger_output
+%%% \endprog
+
+
+%%% \sect Using the output routine for passing
+%%% information has it's difficulties. One of the hard parts is
+%%% \beginchange
+%%% handling page marks. These are token lists which are set by the
+%%% |\mark| command. They record information that can later
+%%% be accessed by the output routine. The canonical example of such
+%%% a use of the |\mark| command is in creating
+%%% \endchange
+%%% dictionary-style entry headings.
+%%%
+%%% The output routine can access one of three
+%%% token lists through three control sequences: |\botmark| is the
+%%% last page mark given, |\topmark| is the |\botmark| of the previous
+%%% page, and |\firstmark| is the first page mark on the actual page or
+%%% |\topmark| if none was given. Here ``page'' is used in the \TeX{}
+%%% sense, i.e.\ as the material which has been collected between two
+%%% |\output| invocations. Of course, the page marks must not be
+%%% destroyed---and that means they must be reinserted after each
+%%% special use of the output routine.
+
+%%% But we are lucky: A ``special use'' consists of two |\output|
+%%% invocations, so we can insert |\topmark| again as a page mark after
+%%% the first invocation where it will be the only page mark on that
+%%% \TeX{} page. The second invocation will automatically transform this
+%%% page mark into the ``last page mark on the previous page,'' i.e.\ in
+%%% |\topmark|---that's what we need! Furthermore |\firstmark| and
+%%% |\botmark| are saved in control sequences during the first invocation,
+%%% they will be inserted again, too.
+
+%%% There's one situation where this approach doesn't work: in front of
+%%% the first page mark. Here, |\topmark|, |\firstmark|, and |\botmark| expand
+%%% to an empty token list. If we save them then and insert their old
+%%% values we have inserted empty page marks. If other page marks follow
+%%% on the same ``real'' page, |\firstmark| will be empty instead of
+%%% expanding to the token list of the first page mark. To prevent this
+%%% we must not save and restore page marks before the first |\mark| has
+%%% been added to the main vertical list.
+
+%%% Well, that can be controlled with a switch---but this switch must be
+%%% set very carefully. If it is set immediately by the first |\mark|
+%%% this may be in horizontal mode and special output invocations can
+%%% occur above this page mark (i.e., there may be a |\beginchange| in the
+%%% same paragraph in front of the |\mark|). Therefore the setting of the
+%%% switch must be delayed until the vertical position of the |\mark|
+%%% (precisely: the position of the |\mark| in the current list) is
+%%% reached. In horizontal mode this can be done with a |\vadjust| and
+%%% the output routine! Voil\`a, this is another command group for the
+%%% output routine with only one command.
+
+%%% \beginprog
+\newif\if_cb_save_mark@ \_cb_save_mark@false
+
+\def\mark_penalty_group{-102}
+%%% \endprog
+
+
+%%% \sect We will redefine |\mark| so that the first page mark either sets
+%%% the switch to true (in vertical mode all possible special page breaks
+%%% are already handled) or forces the |\output| routine to do this at an
+%%% appropriate place. In the last case we can use |\cb_trigger_output|
+%%% again. Afterwards we restore the original meaning of |\mark| again to
+%%% reduce the processing overhead (and the dead cycles).
+
+%%% This change of |\mark| has the consequence that the first |\mark| in a
+%%% document cannot be used anymore in horizontal mode inside a vertical
+%%% box that shall be split afterwards. But this is only sensible if this
+%%% mark shall be used as |\splitfirstmark| because it will almost never
+%%% migrate to the outer list---really a rare case!
+
+%%% \beginprog
+\let\cb_mark=\mark
+\def\mark{%
+ \ifvmode
+ \ifinner \else \global\_cb_save_mark@true \fi % split marks!
+ \else
+ \cb_break_penalty=\mark_penalty_group00 % this will corrupt \vsplit
+ \cb_trigger_output
+ \fi
+ \global\let\mark=\cb_mark
+ \cb_mark
+ }
+%%% \endprog
+
+
+%%% \sect
+%%% \begin{newsloppy}
+%%% If the output routine is triggered with the mark penalty value,
+%%% it will call {\tt \bs cb\_save\discretionary{\_}{}{}page\_marks}.
+%%% \end{newsloppy}
+
+%%% \beginprog
+\def\cb_save_page_marks{% % this may be executed twice
+ \unvbox\@cclv
+ \global\_cb_save_mark@true
+ }
+%%% \endprog
+
+
+%%% \sect To finish the treatment of page marks we can formulate the two
+%%% macros which are used at the first resp.\ second invocation of a
+%%% ``special output,'' the principles have already been explained.
+
+%%% \beginprog
+\def\cb_backup_page_marks{%
+ \if_cb_save_mark@
+ \mark{\topmark}%
+ \xdef\cb_save_firstmark{\firstmark}%
+ \xdef\cb_save_botmark{\botmark}%
+ \fi
+ }
+
+\def\cb_restore_page_marks{%
+ \if_cb_save_mark@
+ \mark{\cb_save_firstmark}\mark{\cb_save_botmark}%
+ \fi
+ }
+%%% \endprog
+
+
+
+
+
+%%% \chap Positioning the Change Bars.
+
+%%% \begin{newsloppy}
+%%% Now we handle the positions of the bars.
+%%% The dimension |\cb_bot_change_pos| will hold
+%%% the position of the end of the change bar, i.e.\ the distance between
+%%% top of page the end of the changed area. The dimension
+%%% |\cb_top_change_pos| will hold the beginning of a changed
+%%% area; a value of |\maxdimen| indicates that no change is in effect. If
+%%% a changed area is completed, it is appended to the list |\cb_bar_list| as
+%%% an element {\tt \bs cb\_bar(\bs cb\_top\_change\_pos,
+%%% \bs cb\_bot\_change\_pos, \bs changebar\-width)}. This list contains all
+%%% changed areas within the current page so that bars can be written later
+%%% on. A single bar will be produced by |\cb_write_bar|.
+
+%%% \noindent The definition of |\cb_bar| to |\relax| allows the concatenation
+%%% of new elements to |\cb_bar_list| with |\xdef|.
+
+%%% Local dimension register |\halfwidth| is used to center the change bar.
+%%% \end{newsloppy}
+
+%%% \beginprog
+\newdimen\cb_bot_change_pos
+\newdimen\cb_top_change_pos \cb_top_change_pos=\maxdimen
+
+\let\cb_bar_list=\empty
+
+\let\cb_bar=\relax
+\def\cb_write_bar(#1,#2,#3){{%
+ \dimendef\halfwidth=255%
+ \setbox0=\hbox{\vrule width #3 height -#1 depth #2}%
+ \dp0=0pt \ht0=0pt \wd0=0pt%
+ \halfwidth=#3 \divide\dimen255 by 2%
+ \hskip -\halfwidth%
+ \box0%
+ \hskip \halfwidth%
+ }}
+%%% \endprog
+
+
+%%% \sect If the output routine was activated by a |\outputpenalty| value
+%%% within the range of our reserved penalties, the change handling will
+%%% occur, otherwise standard plain output can be done. There may be
+%%% a lot of interaction between the routines which set change bars and
+%%% the output routine. These interactions should not be recorded in
+%%% |\deadcycles| or else \TeX{} will soon grumble. One might consider
+%%% doing the same for the|\mark_penalty_group|. But since this
+%%% group is called once it shouldn't matter all that much.
+
+%%% One might also consider adding a counter like |\deadcycles| just
+%%% to count the change bar interactions as is done for the calls to
+%%% |\output|, and have {\TeX} grumble if there are ``too many'' of
+%%% them. For now we don't do this---all of this code is correct
+%%% anyway!
+
+%%% First we save away the old output routine in case the user had redefined
+%%% this beforehand.
+
+%%% \beginprog
+\newtoks\cb_oldoutput
+\edef\cb_oldoutput{\the\output}
+
+\newcount\penalty_group
+
+\output={%
+ \boxmaxdepth=\maxdepth
+ \penalty_group=\outputpenalty \divide \penalty_group by 100
+ \ifnum \penalty_group=\cb_penalty_group\space
+ {\countdef\new_deadcycles=255% don't count as a dead cycle
+ \new_deadcycles=\deadcycles
+ \advance \new_deadcycles by -1
+ \deadcycles=\new_deadcycles}
+ \cb_change_handling
+ \else
+ \ifnum \penalty_group=\mark_penalty_group\space
+ \cb_save_page_marks
+ \else \cb_oldoutput
+ \fi
+ \fi
+ }
+%%% \endprog
+
+
+%%% \sect As explained before, the change handling must differentiate
+%%% between the kind of the change command (beginning is indicated by
+%%% $|\cb_change_cmd|=0$, end by~1) and between the mode (horizontal indicated
+%%% by an odd |\cb_change_mode| value, vertical by an even). A change mode
+%%% higher than one indicates that we are doing the first page break that
+%%% has to backup the page as far as it exists already and results in an
+%%% empty current list of page elements.
+
+%%% \beginprog
+\newcount\cb_change_cmd
+\newcount\cb_change_mode
+
+\def\cb_change_handling{%
+ \cb_change_cmd=-\outputpenalty % ==> absolute value
+ \advance \cb_change_cmd by \cb_penalty_group00 % subtraction
+ \cb_change_mode=\cb_change_cmd
+ \divide \cb_change_cmd by 10 % second-to-last digit
+ \advance \cb_change_mode by -\number\cb_change_cmd0 % last digit
+ \ifnum \cb_change_mode>1 \cb_backup_page
+ \else
+ \ifcase \cb_change_cmd \cb_begin_change
+ \or \cb_end_change
+ \else \errmessage{Invalid changepenalty}%
+ \fi
+ \fi
+ }
+%%% \endprog
+
+
+%%% \sect Processing a mark during the second trigger of the output routine
+%%% means restoring the page and storing the positions. At the beginning,
+%%% the begin of the change is saved, at the end, we know the bar already
+%%% and put it into the bar list. Then the positioning values are
+%%% reinitialized.
+
+%%% As within every output invocation, the box 255 must be unboxed. As we
+%%% are here in the second invocation of the output routine the |\box255|
+%%% consists only of the empty |\vbox| we have inserted in
+%%% |\cb_trigger_output|. We can therefore throw it away.
+
+%%% \beginprog
+\def\cb_begin_change{%
+ \cb_restore_page
+ \setbox0=\box\@cclv
+ \ifdim \cb_top_change_pos=\maxdimen
+ \global\cb_top_change_pos=\cb_bot_change_pos
+ \global\cb_bot_change_pos=0pt
+ \else \errmessage{Nested change bars are not supported}%
+ \fi
+ }
+
+\def\cb_end_change{%
+ \cb_restore_page
+ \setbox0=\box\@cclv
+ \ifdim \cb_top_change_pos=\maxdimen
+ \errmessage{No change is in effect}%
+ \else
+ \xdef\cb_bar_list{\cb_bar_list
+ \cb_bar(\the\cb_top_change_pos,\the\cb_bot_change_pos,
+ \the\cb_changebarwidth)}
+ \global\cb_top_change_pos=\maxdimen
+ \global\cb_bot_change_pos=0pt
+ \fi
+ }
+%%% \endprog
+
+
+%%% \chap Handling the Page Contents.
+
+%%% We handle the part of the page that was collected up to now by putting
+%%% it into a box. This fixes the position of the change mark so that
+%%% |\cb_bot_change_pos| can be set and stored in |\cb_top_change_pos|
+%%% later on or as the lower end of a bar in |\cb_bar_list|.
+
+%%% In the first output invocation, we save the contents of the
+%%% page in |\cb_save_page|. Before that, we store the size of the
+%%% box (which equals |\pagegoal|!)\ in |\cb_page_goal|. If the unboxing
+%%% caused an increase of height (i.e.\ if $|\pagetotal|>|\pagegoal|$),
+%%% we eject the page up to the change mark. Now we have to compute the
+%%% current position of our mark in |\cb_bot_change_pos|. It is fixed by the size
+%%% of the |\cb_save_page|, but if the change begins in horizontal mode we
+%%% must decrease it from the baseline position to the top of the last line.
+%%% Finally, we must save the values for the allowed insertions and change
+%%% them to the maximal value so that a rest that is split from an insertion
+%%% will be appended to the insertion box at the second invocation in every
+%%% case.
+
+%%% The |\vsize| is initialized to |\maxdimen|. This allows to control
+%%% whether this first output invocation ocurred or if it was discarded.
+%%% For the same reason |\cb_bot_change_pos| is initialized to~0pt.
+
+%%% \beginprog
+\newbox\cb_save_page
+
+\newdimen\cb_page_goal
+\newdimen\cb_save_vsize \cb_save_vsize=\maxdimen
+\newdimen\cb_save_dimen_topins
+\newdimen\cb_save_dimen_footins
+
+\def\cb_backup_page{%
+ \global\cb_page_goal=\ht\@cclv
+ \global\setbox\cb_save_page=\vbox{\unvbox\@cclv}%
+ \ifdim \ht\cb_save_page>\cb_page_goal
+ \cb_eject_page_so_far \fi
+ \cb_bot_change_pos=\ht\cb_save_page
+ \global\advance \cb_bot_change_pos by \dp\cb_save_page
+ \ifnum \cb_change_cmd=\cb_penalty_begin\space
+ \ifodd \cb_change_mode \higher_change_pos \fi
+ \fi
+ \global\cb_save_vsize=\vsize \global\vsize=\maxdimen
+ \global\cb_save_dimen_footins=\dimen\footins
+ \global\dimen\footins=\maxdimen
+ \cb_backup_page_marks
+ }
+
+\cb_bot_change_pos=0pt
+%%% \endprog
+
+
+%%% \sect To eject a page as far as it is we restore it from the
+%%% |\cb_save_page| back to box~255. In horizontal mode and at a begin mark
+%%% the last line contains the mark and must not be output. So we remove it
+%%% and the preceding glue from the stored rest, just leaving a single hbox
+%%% to be on top of the actual page (in |\cb_save_page|) now. Then normal
+%%% output can be done with box~255.
+
+%%% \beginprog
+\def\cb_eject_page_so_far{%
+ \begingroup
+ \vbadness=20000 % don't complain about underfull vboxes
+ \global\setbox\@cclv=\vbox to \cb_page_goal{%
+ \unvbox\cb_save_page
+ \ifnum \cb_change_cmd=\cb_penalty_begin\space
+ \ifodd \cb_change_mode
+ \global\setbox\cb_save_page=\lastbox
+ \unskip
+ \fi
+ \fi
+ }%
+ \endgroup
+ \cb_oldoutput
+ }
+%%% \endprog
+
+
+%%% \sect
+%%% \begin{newsloppy}
+%%% In horizontal mode and at a begin mark, we need the position of
+%%% the mark ({\tt \bs cb\_bot\discretionary{\_}{}{}change\_pos}) on the upper boundary of
+%%% the last line in
+%%% |\cb_save_page|. If there is just one line left from a recent eject, the
+%%% height is given by |\topskip| decreased by the height of this hbox. If
+%%% the height of the box is larger than |\topskip| the skip will not be
+%%% inserted and the change position results to~0pt. Otherwise,
+%%% |\cb_save_page| is a vbox whose last hbox we delete temporarily using
+%%% box~0. Height and depth of the rest are the actual position on the page.
+%%% \end{newsloppy}
+
+%%% The double of the page we have constructed this way will immediately be
+%%% fed back to the garbage collector because it could have become
+%%% reasonably large.
+
+%%% \beginprog
+\def\higher_change_pos{%
+ \ifhbox \cb_save_page % rest of page from \cb_eject_page_so_far
+ \cb_bot_change_pos=\topskip
+ \global\advance \cb_bot_change_pos by -\ht\cb_save_page
+ \ifdim \cb_bot_change_pos<0pt
+ \global\cb_bot_change_pos=0pt
+ \fi
+ \else
+ \setbox0=\vbox{%
+ \unvcopy\cb_save_page
+ \setbox0=\lastbox % delete last line
+ }%
+ \cb_bot_change_pos=\ht0
+ \global\advance \cb_bot_change_pos by \dp0
+ \setbox0=\box\voidb@x
+ \fi
+ }
+%%% \endprog
+
+
+%%% \sect To restore a page during the second output invocation, we first
+%%% restore the saved values, but only if they were really changed (this can
+%%% be discovered by the value of |\cb_save_vsize|). Now the |\cb_save_page| is
+%%% appended to the current list as a box, which stops later usage of its
+%%% stretch- and shrinkability! Then the collected insertions can be
+%%% inserted again. The page marks have to be inserted, too.
+
+%%% \beginprog
+\def\cb_restore_page{%
+ \ifdim \cb_save_vsize=\maxdimen
+ \else \global\vsize=\cb_save_vsize
+ \global\dimen\footins=\cb_save_dimen_footins
+ \global\cb_save_vsize=\maxdimen
+ \cb_restore_page_marks
+ \fi
+ \box\cb_save_page % discards stretch- and shrinkability!
+ \ifvoid \footins
+ \else \insert\footins{\floatingpenalty=20000 \unvbox\footins}%
+ \fi
+ }
+%%% \endprog
+
+
+%%% \sect {\em Please note, that there is still a problem with this concept
+%%% of handling the output trigger:}
+
+%%% \bigskip
+
+%%% If the first output trigger is discarded because a page break has occurred
+%%% just in front, footnote parts may be juggled around. I.e., if a
+%%% footnote is split in three parts, the first part was just been shipped
+%%% out, the second part is inserted back into the recent contributions by
+%%% the output routine but {\em behind\/} the third part which is saved in
+%%% the ``special place'' (according to the \TeX{}book, p.~125). A solution to
+%%% this problem might be to insert a |\do_change| again within the second
+%%% output trigger and finishing the treatment afterwards. Afterwards a
+%%% full triggering process (two output invocations) is executed again and
+%%% all insertion parts will be accessible in the insertion box.
+
+%%% By the way, the almost same problem appears in \LaTeX{}, too. Almost: in
+%%% \LaTeX{} this can happen every time because at the first output invocation
+%%% the |\dimen|-values of the footnote insertion is not increased. I leave
+%%% the problem open to the reader\,\dots
+
+
+
+
+
+%%% \chap Writing the Stuff.
+
+%%% The positions of the bars which mark the changed areas are relative to
+%%% the top of the text, i.e.\ the height of the top insertion is not
+%%% included. Therefore it is best to write them just after the top
+%%% insertions before the page text---but to do this we have to change the
+%%% \beginchange
+%%% either the {\sc Plain} {\TeX} macro |\pagecontents| or the {\LaTeX}
+%%% macro |\@makecol|.
+%%% \endchange
+
+%%% Below is the new definition, I have just rearranged it a little bit so
+%%% that it is more legible. The new lines have been marked with
+%%% `|%%%%|'. |\cb_insert_current_bar| inserts a last element in |\cb_bar_list|
+%%% if a changed area is not yet finished, afterwards all bars can be
+%%% written.
+
+%%% \beginprog
+\def\@makecol{%
+ \ifvoid\footins
+ \setbox\@outputbox
+ \vbox{
+ %\typeout{write all bars -- no footins}
+ \cb_insert_current_bar \cb_write_all_bars %%%%
+ \unvbox\@cclv%
+ }
+ \else
+ \setbox\@outputbox
+ \vbox{\boxmaxdepth \maxdepth
+ %\typeout{write all bars}
+ \cb_insert_current_bar \cb_write_all_bars %%%%
+ \unvbox\@cclv\vskip\skip\footins\footnoterule\unvbox\footins%
+ }
+ \fi%
+ \xdef\@freelist{\@freelist\@midlist}\gdef\@midlist{}\@combinefloats
+ \setbox\@outputbox\vbox to\@colht{\boxmaxdepth\maxdepth
+ \@texttop\dimen128=\dp\@outputbox\unvbox\@outputbox
+ \vskip-\dimen128\@textbottom}%
+ \global\maxdepth\@maxdepth}
+%%% \endprog
+
+%%% \sect If $|\cb_top_change_pos|=|\maxdimen|$ no change is active. Otherwise
+%%% the current change reaches from the begin mark (|\cb_top_change_pos|) to
+%%% the end of the page, i.e.\ we insert a virtual end mark. Because the
+%%% change continues on the next page we insert a virtual begin mark on the
+%%% top of the page, too.
+
+%%% \beginprog
+\def\cb_insert_current_bar{%
+ \ifdim \cb_top_change_pos=\maxdimen
+ \else%
+ \cb_bot_change_pos=\ht\@cclv
+ \advance\cb_bot_change_pos by \dp\@cclv
+ \xdef\cb_bar_list{\cb_bar_list
+ \cb_bar(\the\cb_top_change_pos,
+ \the\cb_bot_change_pos,
+ \the\changebarwidth)}%
+ \global\cb_top_change_pos=0pt
+ \fi%
+ }
+%%% \endprog
+
+
+%%% \sect Now we can write all bars---if they exist anyway. It's rather
+%%% easy, we just have to define |\cb_bar| to |\cb_write_bar| and execute
+%%% |\cb_bar_list|. The resulting output must not use vertical place. We must
+%%% not forget to delete the list, or we will get the same bars on the next
+%%% page again.
+
+%%% \beginprog
+\newbox\cb_bars
+\newdimen\cb_offset
+
+\def\cb_write_all_bars{%
+ \ifx \cb_bar_list\empty
+ \else % changes exist
+ \ifchbarRight
+ \cb_offset = \hsize
+ \advance \cb_offset by \BarDistance
+ \else
+ \cb_offset = \hoffset
+ \advance \cb_offset by -\BarDistance
+ \fi
+ \setbox\cb_bars=\hbox to \cb_offset{%
+ \hskip\cb_offset
+ \vbox to 0pt{\offinterlineskip
+ \let\cb_bar=\cb_write_bar \cb_bar_list
+ }%
+ \hss
+ }%
+ \ht\cb_bars=0pt \dp\cb_bars=0pt \box\cb_bars
+ \global\let\cb_bar_list=\empty
+ \fi
+ }
+%%% \endprog
+
+
+%%% \beginchange\chap Cleaning Up.\endchange
+
+%%% We finish the macro file so that garbage (e.g.\ of exchanges
+%%% between systems) can come afterwards.
+
+%%% \beginprog
+\catcode`\@=\atcode
+\catcode`\_=\uscode
+
+\endinput
+%%% \endprog
+
+
+
+%%% \end{document}
+