<html><head><meta name="color-scheme" content="light dark"></head><body><pre style="word-wrap: break-word; white-space: pre-wrap;">% 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                  % ==&gt; 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&gt;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|&gt;|\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&gt;\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&lt;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}
 
</pre></body></html>