% \iffalse meta-comment
%
%% Copyright 1994-2026 (C) Johannes Braams.  All rights reserved.
%
% This file is part of the changebar package.
% -------------------------------------------
%
% It may be distributed and/or modified under the
% conditions of the LaTeX Project Public License, either version 1.3
% of this license or (at your option) any later version.
% The latest version of this license is in
%   http://www.latex-project.org/lppl.txt
% and version 1.3 or later is part of all distributions of LaTeX
% version 2003/12/01 or later.
%
% This work has the LPPL maintenance status "maintained".
%
% The Current Maintainer of this work is Johannes Braams.
%
% The list of all files belonging to the changebar package is
% given in the file `manifest.txt.
%
% The list of derived (unpacked) files belonging to the distribution
% and covered by LPPL is defined by the unpacking scripts (with
% extension .ins) which are part of the distribution.
% \fi
% \CheckSum{3148}
%
%\iffalse
%    This file is built for \LaTeXe, so we make sure an error is
%    generated when it is used with another format
%    \begin{macrocode}
%<+package>\NeedsTeXFormat{LaTeX2e}
%    \end{macrocode}
%
%    Now announce the package name and its version:
%    \begin{macrocode}
%<*dtx>
\ProvidesFile{changebar.dtx}
%</dtx>
%<+package>\ProvidesPackage{changebar}
           [2026/07/19 v3.7g Indicate changes with marginal bars]
%    \end{macrocode}
%
% \section{A driver for this document}
%
%    The next bit of code contains the documentation driver file for
%    \TeX{}, i.e., the file that will produce the documentation you
%    are currently reading. It will be extracted from this file by the
%    \textsc{docstrip} program.
%
%    \begin{macrocode}
%<*driver>
\documentclass{ltxdoc}
\usepackage[pdftex,rightbars,color,traceon,tracestacks]{changebar}
\cbcolor{red}
\DoNotIndex{\@@,\@Esphack,\@Mii,\@cons,\@empty,\@gobble}
\DoNotIndex{\@ifundefined,\@ne,\@spaces,\@whilenum}
\DoNotIndex{\advance,\begingroup,\bgroup,\egrou,\endgroup}
\DoNotIndex{\catcode,\chardef,\clearpage,\closein,\closeout}
\DoNotIndex{\csname,\endcsname,\def,\dimen@,\divide,\do,\dp}
\DoNotIndex{\edef,\expandafter}
\DoNotIndex{\gdef,\global}
\DoNotIndex{\GenericWarning,\hoffset,\ht}
\DoNotIndex{\ifcase,\or,\fi,\ifdim,\else,\fi,\ifeof,\fi,\ifnum,\fi}
\DoNotIndex{\ifvmode,\fi,\ifx,\fi,\ignorespaces,\immediate,\InputIfFileExists}
\DoNotIndex{\jobname,\let,\long,\m@ne,\maxdepth,\MessageBreak}
\DoNotIndex{\newcommand,\newcount,\newcounter,\newdimen,\newenvironment}
\DoNotIndex{\newlength,\newread,\newwrite,\next,\noexpand,\normalcolor}
\DoNotIndex{\openin,\openout,\OptionNotUsed,\p,\PacakgeError}
\DoNotIndex{\PackageWarning,\point,\ProcessOptions,\read,\relax}
\DoNotIndex{\RequirePackage,\setbox,\setcounter,\setlength,\space}
\DoNotIndex{\string,\strutbox,\t,\textwidth,\the,\thr@@,\tw@}
\DoNotIndex{\unvbox,\uppercase,\vadjust,\vbox,\vskip,\vss,\write,\xdef,\z@}
%    \end{macrocode}
%    We do want an index, using linenumbers
%    \begin{macrocode}
\EnableCrossrefs
\CodelineIndex
%    \end{macrocode}
%    This document uses some extra \texttt{doc} style macros.
%    \begin{macrocode}
\makeatletter
\def\DescribeVar#1{\leavevmode\@bsphack
    \marginpar{\raggedleft\PrintDescribeEnv{#1}}%
    \SpecialVarUsageIndex{#1}\@esphack\ignorespaces}
\def\SpecialVarMainIndex#1{\@bsphack
    \index{#1\actualchar\texttt{#1}\encapchar main}%
    \@esphack}
\def\SpecialVarUsageIndex#1{\@bsphack
    \index{#1\actualchar\texttt{#1}\encapchar usage}%
    \@esphack}
\let\@SpecialMainIndex\SpecialMainIndex
\def\Var{\let\SpecialMainIndex\SpecialVarMainIndex\macro}
\def\endVar{\endmacro\let\SpecialMainIndex\@SpecialMainIndex}
\makeatother
%    \end{macrocode}
%    Some commonly used abbreviations
%    \begin{macrocode}
\newcommand{\Lopt}[1]{\textsf {#1}}
\newcommand{\Lenv}[1]{\textsf {#1}}
\newcommand{\file}[1]{\texttt {#1}}
\newcommand{\pkg}[1]{\texttt {#1}}
\newcommand{\Lcount}[1]{\textsl {\small#1}}
\newcommand{\pstyle}[1]{\textsl {#1}}
%    \end{macrocode}
%    We also want the full details.
%    \begin{macrocode}
\begin{document}
\DocInput{changebar.dtx}
\end{document}
%</driver>
%    \end{macrocode}
%\fi
%
% \GetFileInfo{changebar.dtx}
%
% \changes{3.1}{1993/07/02}{Removed a number of typos}
% \changes{3.1a}{1993/08/03}{Uncommented \cs{filedate} and
%    \cs{fileversion}}
% \changes{3.2}{1994/04/21}{Incorporated Robin Fairbairns suggestions
%    for the upgrade for \LaTeX2e}
% \changes{3.2a}{1995/03/20}{Fixed bug about cross-page bars}
% \changes{v3.2b}{1995/06/26}{Removed use of \cs{file...} commands}
% \changes{v3.2b}{1995/06/26}{Use \LaTeX's Warning mechanisms}
% \changes{v3.2c}{1996/03/26}{Reinserted \cs{driver} for compatibility
%    reasons} 
% \changes{v3.4e}{2001/09/14}{Store original definitions using the
%    \texttt{ltx} prefix, define own versions with \texttt{cb} prefix,
%    the use \cmd{let} to replace \LaTeX\ macro.}
% \changes{v3.5a}{2005/05/23}{Piet van Oostrum: Resolved bugs in twocolumn
%    mode, mid-document changes to page number, added pdflatex support.}
% \changes{v3.6a}{2011/04/30}{Added support for XeTeX provided by
%    Apostolos Syropoulos}
% \changes{v3.6b}{2018/02/03}{Added a macro for pdf scaling for
%    Xe\TeX}
% \changes{v3.6e}{2023/08/13}{Added supprt for luaTeX}
% \changes{v3.7b}{2023/12/28}{Added a few lines that were
%    inadvertantly removed}
% \changes{v3.7b}{2023/12/30}{the cb2-file uses delimiting chars that may
%   change meaning when they end up in the wrong situation}
% \changes{v3.7e}{2024/07/17}{The use of the character `;´ as a string
%    separator clashes with it's active variant when babel/french has
%    been loaded} 
% \changes{v3.7f}{2026/07/12}{Avoid quadratic history-stack searches
%    when the page data recorded by the previous run no longer
%    matches the document}
% \changes{v3.7g}{2026/07/18}{Also avoid the searches that would
%    succeed, and the quadratic scans of the pdf coordinates list}
%
% \title{The Changebar package
%         \thanks{This file has version number \fileversion,
%                 last revised \filedate.}}
%
% \author{Michael Fine\\Distributed Systems Architecture \and
%         Johannes Braams\\
%         \texttt{texniek at texniek.nl}}
%
% \date{Printed \today}
%
% \maketitle
%
% \begin{multicols}{2}
%  \tableofcontents
% \end{multicols}
%
% \begin{abstract}
%    This package implements a way to indicate
%    modifications in a \LaTeX-document by putting bars in the
%    margin. It realizes this by making use of the |\special|
%    commands supported by `dvi drivers'. Currently six different
% \changes{v3.5a}{2005/05/23}{PDF\TeX{} support added}
% \changes{v3.6a}{2011/04/30}{Xe\TeX{} support added}
%    drivers are supported, plus pdftex,  Xe\TeX\ and lua\TeX\  
%    support. More can easily be added. 
% \end{abstract}
%
% \section{Introduction}
%
%    \textbf{Important note} Just as with cross references and labels,
%    you usually need to process the document twice (and sometimes
%    three times) to ensure that the changebars come out
%    correctly. However, a warning will be given if another pass is
%    required. 
%
%    \textbf{Features}
%    \begin{itemize}
%    \item Changebars may be nested within each other.  Each level of
%    nesting can be given a different thickness bar. 
%
%    \item Changebars may be nested in other environments including
%    floats and footnotes.
%
%    \item Changebars are applied to all the material within the
%    ``barred'' environment, including floating bodies regardless of
%    where the floats float to.  An exception to this is margin
%    floats.
%
%    \item Changebars may cross page boundaries.
%
%    \item Changebars can appear on the \emph{outside} of the columns
%    of \Lopt{twocolumn} text.
%
%    \item The colour of the changebars can be changed. This has sofar
% \changes{v3.5a}{2005/05/23}{Pdftex support added}
% \changes{v3.6a}{2011/05/02}{xetex support added}
%      been tested with the \Lopt{dvips}, \Lopt{pdftex},
%      \Lopt{vtex} and\Lopt{xetex} drivers, 
%      but it may also work with other PostScript based drivers. It will 
%      \emph{not} work for the \texttt{DVItoLN03} and em\TeX\ drivers.
%      For colored changebars to work, make sure that you specify the
% \changes{v3.5a}{2005/05/23}{Option xcolor mentioned}
%      option \Lopt{color} or \Lopt{xcolor}.
%    \end{itemize}
%
% \section{The user interface}
%
%    This package has options to specify some details of its
%    operation, and also defines several macros.
%
% \subsection{The package options}
% \subsubsection{Specifying the printer driver}
%
%    One set of package options\footnote{For older documents the
%    command \cs{driver} is available in the preamble of the document.
%    It takes the options as defined for \LaTeXe\ as argument.}
%    specify the driver that will be used to print the document can be
%    indicated. The driver may be one of: 
%    \begin{itemize}
%      \item DVItoLN03
%      \item DVItoPS
%      \item DVIps
%      \item em\TeX
%      \item \TeX tures
%      \item V\TeX
% \changes{v3.5a}{2005/05/23}{Pdftex support added}
%      \item PDF\TeX
% \changes{v3.6a}{2011/04/30}{XeTeX added}
%      \item Xe\TeX
% \changes{3.6e}{2023/08/13}{luaTeX added}
%       \item lua\TeX
%      \end{itemize}
%    The drivers are represented in the normal typewriter method of
%    typing these names, or by the same entirely in lower case.
%    Since version 3.4d the driver can be specified in a configuration
%    file, not surprisingly called \file{changebar.cfg}. If it
%    contains the command |\ExecuteOption{textures}| the
%    \Lopt{textures} option will be used for all documents that are
%    processed while the configuration file is in \TeX's search path.
%
% \subsubsection{Specifying the bar position}
%    The position of the bars may either be on the inner edge of the
%    page (the left column on a recto or single-sided page, the right
%    column of a verso page) by use of the \Lopt{innerbars} package
%    option (the default), or on the outer edge of the page by use of
%    the \Lopt{outerbars} package option.
%
%    Another set of options gives the user the possibility of
%    specifying that the bars should \emph{always} come out on the
%    left side of the text (\Lopt{leftbars}) or on the right side of
%    the text (\Lopt{rightbars}). 
%
%    \emph{Note} that these options only work for \emph{onecolumn}
%    documents and will be ignored for a twocolumn document. 
%
% \subsubsection{Color}
%    For people who want their changebars to be colourfull the options
%    \Lopt{color} and \Lopt{xcolor} are available. They define the
%    user command |\cbcolor| and load either the \pkg{color} or the
%    \pkg{xcolor} package.
%
%    If a configuration file specifies the \Lopt{color} option and you
%    want to override it for a certain document you can use the
%    \Lopt{grey} option.
%
% \subsubsection{Tracing}
%    The package also implements tracing for its own debugging. The
%    package options \Lopt{traceon} and \Lopt{traceoff} control
%    tracing. An additional option \Lopt{tracestacks} is available for
%    the die hard who wants to know what goes on in the internal stacks
%    maintained by this package.
%
% \subsection{Macros defined by the package}
%
% \DescribeMacro{\cbstart}
% \DescribeMacro{\cbend}
%    All material between the macros |\cbstart| and |\cbend| is
%    barred.  The nesting of multiple changebars is allowed.  The
%    macro |\cbstart| has an optional parameter that specifies the
%    width of the bar. The syntax is |\cbstart[|\meta{dimension}|]|.
%    If no width is specified, the current value of the parameter
%    |\changebarwidth| is used.  Note that |\cbstart| and |\cbend| can
%    be used anywhere but must be correctly nested with floats and
%    footnotes.  That is, one cannot have one end of the bar inside a
%    floating insertion and the other outside, but that would be a
%    meaningless thing to do anyhow.
%
% \DescribeEnv{changebar}
%    Apart from the macros |\cbstart| and |\cbend| a proper \LaTeX\
%    environment is defined. The advantage of using the environment
%    whenever possible is that \LaTeX\ will do all the work of
%    checking the correct nesting of different environments.
%
% \DescribeMacro{\cbdelete}
%    The macro |\cbdelete| puts a square bar in the margin to indicate
%    that some text was removed from the document. The macro has an
%    optional argument to specify the width of the bar. When no
%    argument is specified the current value of the parameter
%    |\deletebarwidth| will be used.
%
% \DescribeMacro{\nochangebars}
%    The macro |\nochangebars| disables the changebar commands.
%
% \DescribeMacro{\cbcolor}
%    This macro is defined when the \Lopt{color} option is
%    selected. It's syntax is the same as the |\color| command from
%    the \pkg{color} package.
%
% \subsection{Changebar parameters}
%
% \DescribeMacro{\changebarwidth}
%    The width of the changebars is controlled with the \LaTeX\ length
%    parameter |\changebarwidth|.
%    Its value can be changed with the |\setlength| command.
%    Changing the value of |\changebarwidth| affects all subsequent
%    changebars subject to the scoping rules of |\setlength|.
%
% \DescribeMacro{\deletebarwidth}
%    The width of the deletebars is controlled with the \LaTeX\ length
%    parameter |\deletebarwidth|.
%    Its value can be changed with the |\setlength| command.
%    Changing the value of |\deletebarwidth| affects all subsequent
%    deletebars subject to the scoping rules of |\setlength|.
%
% \DescribeMacro{\changebarsep}
%    The separation between the text and the changebars is determined
%    by the value of the \LaTeX\ length parameter |\changebarsep|.
%
% \DescribeVar{changebargrey}
%    When one of the supported dvi to PostScript translators is used
%    the `blackness' of the bars can be controlled. The \LaTeX\
%    counter \texttt{changebargrey} is used for this purpose. Its
%    value can be changed with a command like:
%    \begin{verbatim}
%    \setcounter{changebargrey}{85}
%    \end{verbatim}
%    The value of the counter is a percentage, where the value 0 yields
%    black bars, the value 100 yields white bars.
%
% \DescribeVar{outerbars}
%    The changebars will be printed in the `inside' margin of your
%    document.  This means they appear on the left side of the
%    page. When \Lopt{twoside} is in effect the bars will be printed
%    on the right side of even pages.
%
%
% \section{Deficiencies and bugs}
%
% \begin{itemize}
% \item The macros blindly use special points |\cb@minpoint| through
%    |\cb@maxpoint|. If this conflicts with another set of macros, the
%    results will be unpredictable.  (What is really needed is a
%    |\newspecialpoint|, analogous to |\newcount| etc.~--- it's not
%    provided because the use of the points is rather rare.)
%
% \item There is a limit of 
%    $(\mbox{\texttt{\bslash cb@maxpoint}}-
%    \mbox{\texttt{\bslash cb@minpoint}}+1)/4$ bars per page
%    (four special points per bar).  Using more than this number yields
%    unpredictable results (but that could be called a feature for a
%    page with so many bars).  This limitation could be increased if
%    desired.
% \changes{v3.5a}{2005/05/23}{Pdftex support added}
% \changes{v3.6a}{2011/04/30}{XeTeX suport added}
%    There is no such limit with PDF\TeX or Xe\TeX.
%
% \item Internal macro names are all of the form |\cb@xxxx|.  No
%    checking for conflicts with other macros is done.
%
% \item This implementation does not work with the
%    \texttt{multicolumn} package.
%
% \item The algorithms may fail if a floating insertion is split over
%    multiple pages.  In \LaTeX\ floats are not split but footnotes
%    may be.  The simplest fix to this is to prevent footnotes from
%    being split but this may make \TeX\ very unhappy.
%
% \item The |\cbend| normally gets ``attached'' to the token after it
%    rather than the one before it.  This may lead to a longer bar
%    than intended.  For example, consider the sequence `word1
%    |\cbend| word2'.  If there is a line break between `word1' and
%    `word2' the bar will incorrectly be extended an extra line.  This
%    particular case can be fixed with the incantation
%    `word1|\cbend{}| word2'.
%
% \item The colour support has only been tested with the \Lopt{dvips}
% \changes{v3.5a}{2005/05/23}{Pdftex support added}
%    and \Lopt{pdftex} drivers. 
%  \end{itemize}
%
% \section{The basic algorithm}
%
%    The changebars are implemented using the |\specials| of various
%    \texttt{dvi} interpreting programs like \texttt{DVItoLN03} or
%    \texttt{DVIps}.  In essence, the start of a changebar defines two
%    |\special| points in the margins at the current vertical position
%    on the page.  The end of a changebar defines another set of two
%    points and then joins (using the ``connect'' |\special|) either
%    the two points to the left or the two points to the right of the
%    text, depending on the setting of \Lopt{innerbars},
%    \Lopt{outerbars}, \Lopt{leftbars}, \Lopt{rightbars} and/or
%    \Lopt{twoside}. 
%
%    This works fine as long as the two points being connected lie on
%    the same page.  However, if they don't, the bar must be
%    artificially terminated at the page break and restarted at the
%    top of the next page.  The only way to do this (that I can think
%    of) is to modify the output routine so that it checks if any bar
%    is in progress when it ships out a page and, if so, adds the
%    necessary artificial end and begin.
%
%    The obvious way to indicate to the output routine that a bar is
%    in progress is to set a flag when the bar is begun and to unset
%    this flag when the bar is ended.  This works most of the time
%    but, because of the asynchronous behavior of the output routine,
%    errors occur if the bar begins or ends near a page break.  To
%    illustrate, consider the following scenario.
%
%    \begin{verbatim}
%    blah blah blah          % page n
%    blah blah blah
%    \cbstart                % this does its thing and set the flag
%    more blah
%               <-------------- pagebreak occurs here
%    more blah
%    \cbend                  % does its thing and unsets flag
%    blah blah
%    \end{verbatim}
%
%    Since \TeX\ processes ahead of the page break before invoking the
%    output routine, it is possible that the |\cbend| is
%    processed, and the flag unset, before the output routine is
%    called.  If this happens, special action is required to generate
%    an artificial end and begin to be added to page $n$ and $n+1$
%    respectively, as it is not possible to use a flag to signal
%    the output routine that a bar crosses a page break.
%
%    The method used by these macros is to create a stack of the
%    beginning and end points of each bar in the document together
%    with the page number corresponding to each point.  Then, as a
%    page is completed, a modified output routine checks the stack to
%    determine if any bars begun on or before the current page are
%    terminated on subsequent pages, and handles those bars
%    appropriately.  To build the stack, information about each
%    changebar is written to the \file{.aux} file as bars are processed.
%    This information is re-read when the document is next processed.
%    Thus, to ensure that changebars are correct, the document must
%    be processed twice.  Luckily, this is generally required for
%    \LaTeX\ anyway. 
%    With PDF\LaTeX{} generally three (or even more) runs
%    are necessary.
%
%    This approach is sufficiently general to allow nested bars, bars
%    in floating insertions, and bars around floating insertions.
%    Bars inside floats and footnotes are handled in the same way as
%    bars in regular text.  Bars that encompass floats or footnotes
%    are handled by creating an additional bar that floats with the
%    floating material.  Modifications to the appropriate \LaTeX\
%    macros check for this condition and add the extra bar.
%
%\StopEventually{
% \IndexPrologue{\section*{Index}%
%  \markboth{Index}{Index}%
%     Numbers in \emph{italics} indicate the page where the
%     macro is described, the underlined numbers indicate
%     the number of the line of code where the macro is defined,
%     all other numbers indicate where a macro is used.}
%
% \GlossaryPrologue{\section*{History of changes}%
%    \markboth{History of changes}{History of changes}%
%    The numbers behind the changes indicate the page where
%    the macrocode is described.\hfil\null}
%
%  \PrintIndex
%^^AA \PrintChanges
% }
% \section{The implementation}
%
% \subsection{Declarations And Initializations}
%
% \begin{macro}{\cb@maxpoint}
%    The original version of \texttt{changebar.sty} only supported the
%    \texttt{DVItoLN03} specials. The \texttt{LN03} printer has a
%    maximum number of points that can be defined on a page. Also for
%    some PostScript printers the number of points that can be defined
%    can be limited by the amount of memory used. Therefore, the
%    consecutive numbering of points has to be reset when the maximum
%    is reached. This maximum can be adapted to the printers needs.
%    \begin{macrocode}
%<*package>
\def\cb@maxpoint{80}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\cb@minpoint}
%    When resetting the point number we need to know what to reset it
%    to, this is minimum number is stored in |\cb@minpoint|.
%    \textbf{This number has to be \emph{odd}} because the algorithm
%    that decides whether a bar has to be continued on the next page
%    depends on this.
%    \begin{macrocode}
\def\cb@minpoint{1}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\cb@nil}
%    Sometimes a void value for a point has to be returned by one
%    of the macros. For this purpose |\cb@nil| is used.
%    \begin{macrocode}
\def\cb@nil{0}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\cb@nextpoint}
%    The number of the next special point is stored in the count
%    register |\cb@nextpoint| and initially equal to
%    |\cb@minpoint|.
%    \begin{macrocode}
\newcount\cb@nextpoint
\cb@nextpoint=\cb@minpoint
%    \end{macrocode}
% \end{macro}
%
%  \begin{macro}{\cb@topleft}
% \changes{v3.3a}{1997/09/26}{Renamed \cs{cb@currentpoint} to
%    \cs{cb@topleft}}
%  \begin{macro}{\cb@topright}
% \changes{v3.3a}{1997/09/26}{New counter}
%  \begin{macro}{\cb@botleft}
% \changes{v3.3a}{1997/09/26}{New counter}
%  \begin{macro}{\cb@botright}
% \changes{v3.3a}{1997/09/26}{New counter}
%    These four counters are used to identify the four special points
%    that specify a changebar. The point defined by |\cb@topleft| is
%    the one used to identify the changebar; the values of the other
%    points are derived from it.
%    \begin{macrocode}
\newcount\cb@topleft
\newcount\cb@topright
\newcount\cb@botleft
\newcount\cb@botright
%    \end{macrocode}
%  \end{macro}
%  \end{macro}
%  \end{macro}
%  \end{macro}
%
%  \begin{macro}{\cb@cnta}
% \changes{v3.4f}{2003/10/18}{New temporary storage counter, replaces
%    the use of \cs{@tempcnta}}
%  \begin{macro}{\cb@cntb}
% \changes{v3.4f}{2003/10/18}{New temporary storage counter, replaces
%    the use of \cs{@tempcntb}}
%  \begin{macro}{\cb@dima}
% \changes{v3.4f}{2003/10/18}{New temporary storage dimension}
%    Sometimes we need temporarily store a value. For this purpose two
%    count registers and a dimension register are allocated.
%    \begin{macrocode}
\newcount\cb@cnta
\newcount\cb@cntb
\newdimen\cb@dima
%    \end{macrocode}
%  \end{macro}
%  \end{macro}
%  \end{macro}
%
%  \begin{macro}{\cb@curbarwd}
% \changes{v3.3a}{1997/09/26}{Introduced \cs{curbarwd} to eliminate
%    the use of \cs{@tempdima}} 
%    The dimension register |\cb@curbarwd| is used to store the width of
%    the current bar.
%    \begin{macrocode}
\newdimen\cb@curbarwd
%    \end{macrocode}
%  \end{macro}
%
% \begin{macro}{\cb@page}
% \begin{macro}{\cb@pagecount}
% \changes{v3.5a}{2005/05/23}{Twocolumn support changes}
%    The macros need to keep track of the number of pages/columns
%    output so far.  To this end the counter |\cb@pagecount| is used.
%    When a pagenumber is read from the history stack, it is stored in
%    the counter |\cb@page|. The counter |\cb@pagecount| is initially
%    $0$; it gets incremented during the call to |\@makebox| (see
%    section~\ref{pagebreak}).
%    \begin{macrocode}
\newcount\cb@page
\newcount\cb@pagecount
\cb@pagecount=0
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\cb@barsplace}
% \changes{v3.5a}{2005/05/23}{Changes for better twocolumn support}
%    A switch is provided to control where the changebars will be
%    printed. 
%    The value depends on the options given:
%    \begin{itemize}
%    \item[0] for innerbars (default),
%    \item[1] for outerbars,
%    \item[2] gives leftbars,
%    \item[3] gives rightbars.
%    \end{itemize}
%    \begin{macrocode}
\def\cb@barsplace{0}
%    \end{macrocode}
% \end{macro}
%
%  \begin{Var}{@cb@trace}
%    A switch to enable tracing of the actions of this package.
%    \begin{macrocode}
\newif\if@cb@trace
%    \end{macrocode}
%  \end{Var}
%
%  \begin{Var}{@cb@firstcolumn}
% \changes{v3.5a}{2005/05/23}{Changes for better twocolumn support}
%    A switch to find out if a point is in the left column of a
%    twocolumn page. 
%    \begin{macrocode}
\newif\if@cb@firstcolumn
%    \end{macrocode}
%  \end{Var}
%
% \begin{macro}{\cb@pdfxy}
% \changes{v3.5a}{2005/05/23}{Pdftex support added}
%    The macro |\cb@pdfxy| populates the pdf x,y coordinates file.
%    In \Lopt{pdftex} and \Lopt{xetex} mode it writes one line to
%    \file{.cb2} file which is equivalent to one bar point. The
%    default implementation is a noop. 
%    If the \Lopt{pdftex} or \Lopt{xetex} option is given it is
%    redefined.
%    \begin{macrocode}
\def\cb@pdfxy#1#2#3#4#5{}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\cb@positions}
%
%    This macro calculates the (horizontal) positions of the
%    changebars.  
%
%  \begin{macro}{\cb@odd@left}
% \changes{v3.3a}{1997/09/26}{Renamed from \cs{b@odd}}
%  \begin{macro}{\cb@odd@right}
% \changes{v3.3a}{1997/09/26}{New dimension register}
%  \begin{macro}{\cb@even@left}
% \changes{v3.3a}{1997/09/26}{Renamed from \cs{b@even}}
%  \begin{macro}{\cb@even@right}
% \changes{v3.3a}{1997/09/26}{New dimension register}
%    Because the margins can differ for even and odd pages and because
%    changebars are sometimes on different sides of the paper we need
%    four dimensions to store the result.
%
%    \begin{macrocode}
\newdimen\cb@odd@left
\newdimen\cb@odd@right
\newdimen\cb@even@left
\newdimen\cb@even@right
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
%
%    Since the changebars are drawn with the \textsc{PostScript}
%    command \texttt{lineto} and not as \TeX{}-like rules the
%    reference points lie on the center of the changebar, therefore
%    the calculation has to add or subtract half of the width of the
%    bar to keep |\changebarsep| whitespace between the bar and the
%    body text.
%
%    First the position for odd pages is calculated.
% \changes{v3.1}{1993/07/02}{Corrected positioning of PostScript bars}
% \changes{v3.3a}{1997/09/26}{calculate horizontal positions
%    independent of options used}
% \changes{v3.3d}{1997/10/28}{Removed bogus offset}
% \changes{v3.3g}{1999/06/11}{Don't use \cs{evensidemargin} when
%    \Lopt{twoside} is \emph{not} in effect}
%    \begin{macrocode}
\def\cb@positions{%
  \global\cb@odd@left=\hoffset
  \global\cb@even@left\cb@odd@left
  \global\advance\cb@odd@left by \oddsidemargin
  \global\cb@odd@right\cb@odd@left
  \global\advance\cb@odd@right by \textwidth
  \global\advance\cb@odd@right by \changebarsep
  \global\advance\cb@odd@right by 0.5\changebarwidth
  \global\advance\cb@odd@left by -\changebarsep
  \global\advance\cb@odd@left by -0.5\changebarwidth
%    \end{macrocode}
%    On even sided pages we need to use |\evensidemargin| in the
%    calculations when \Lopt{twoside} is in effect. 
%    \begin{macrocode}
  \if@twoside
    \global\advance\cb@even@left by \evensidemargin
    \global\cb@even@right\cb@even@left
    \global\advance\cb@even@left by -\changebarsep
    \global\advance\cb@even@left by -0.5\changebarwidth
    \global\advance\cb@even@right by \textwidth
    \global\advance\cb@even@right by \changebarsep
    \global\advance\cb@even@right by 0.5\changebarwidth
  \else
%    \end{macrocode}
%    Otherwise just copy the result for odd pages.
%    \begin{macrocode}
    \global\let\cb@even@left\cb@odd@left
    \global\let\cb@even@right\cb@odd@right
  \fi
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\cb@removedim}
%    In PostScript code, length specifications are without dimensions.
%    Therefore we need a way to remove the letters `pt' from the
%    result of the operation |\the\|\meta{dimen}.
%    This can be done by defining a command that has a delimited
%    argument like:
%    \begin{verbatim}
%    \def\cb@removedim#1pt{#1}
%    \end{verbatim}
%    We encounter one problem though, the category code of the letters
%    `pt' is 12 when produced as the output from |\the\|\meta{dimen}.
%    Thus the characters that delimit the argument of |\cb@removedim|
%    also have to have category code 12. To keep the changes local
%    the macro |\cb@removedim| is defined in a group.
%    \begin{macrocode}
{\catcode`\p=12\catcode`\t=12 \gdef\cb@removedim#1pt{#1}}
%    \end{macrocode}
% \end{macro}
%
% \subsection{Option Processing}
%
%    The user should select the specials that should be used by
%    specifying the driver name as an option to the
%    |\usepackage| call.
% \changes{v3.5a}{2005/05/23}{Added the option \Lopt{PDFTeX}}
% \changes{v3.6a}{2011/04/30}{Added the option \Lopt{XeTeX}}
% \changes{v3.6e}{2023/08/13}{Added the option \Lopt{luaTeX}}
%    Possible choices are:
%    \begin{itemize}
%    \item DVItoLN03
%    \item DVItoPS
%    \item DVIps
%    \item em\TeX
%    \item Textures
%    \item V\TeX
%    \item PDF\TeX
%    \item Xe\TeX
%    \item luaTeX
%    \end{itemize}
%
%    The intent is that the driver names should be case-insensitive,
%    but the following code doesn't achieve this: it only permits the
%    forms given above and their lower-case equivalents.
% \changes{v3.3e}{1998/02/24}{Added the option \Lopt{textures}}
% \changes{v3.4a}{2001/04/18}{Added the option \Lopt{VTeX}}
% \changes{v3.5a}{2005/05/23}{Added the option \Lopt{PDFTeX}}
% \changes{v3.6a}{2011/04/30}{Added the option \Lopt{XeTeX}}
%    \begin{macrocode}
\DeclareOption{DVItoLN03}{\global\chardef\cb@driver@setup=0\relax}
\DeclareOption{dvitoln03}{\global\chardef\cb@driver@setup=0\relax}
\DeclareOption{DVItoPS}{\global\chardef\cb@driver@setup=1\relax}
\DeclareOption{dvitops}{\global\chardef\cb@driver@setup=1\relax}
\DeclareOption{DVIps}{\global\chardef\cb@driver@setup=2\relax}
\DeclareOption{dvips}{\global\chardef\cb@driver@setup=2\relax}
\DeclareOption{emTeX}{\global\chardef\cb@driver@setup=3\relax}
\DeclareOption{emtex}{\global\chardef\cb@driver@setup=3\relax}
\DeclareOption{textures}{\global\chardef\cb@driver@setup=4\relax}
\DeclareOption{Textures}{\global\chardef\cb@driver@setup=4\relax}
\DeclareOption{VTeX}{\global\chardef\cb@driver@setup=5\relax}
\DeclareOption{vtex}{\global\chardef\cb@driver@setup=5\relax}
%    \end{macrocode}
%    \begin{macrocode}
\DeclareOption{PDFTeX}{\cb@pdftexcheck}
\DeclareOption{pdftex}{\cb@pdftexcheck}
%    \end{macrocode}
% \changes{v3.5a}{2005/05/23}{PDFTeX support added}
%    For the \Lopt{pdftex} option we have to check that the current
%    \LaTeX{} run is using PDF\TeX{} and that PDF output is selected.
%    If it is, we initialize the option and open an additional output file.
%    If not, we ignore the option and issue a warning.
%    \begin{macrocode}
\def\cb@pdftexcheck{%
  \ifx\pdfsavepos\@undefined\cb@pdftexerror
  \else\ifx\pdfoutput\@undefined\cb@pdftexerror
  \else\ifnum\pdfoutput>0
    \global\chardef\cb@driver@setup=6\relax
    \ifx\cb@writexy\@undefined
      \newwrite\cb@writexy
      \newread\cb@readxy
      \immediate\openout\cb@writexy=\jobname.cb2\relax
    \fi
%    \end{macrocode}
%    Redefine the |\cb@pdfxy| macro to write point coordinates to the
%    \file{.cb2} file.
% \changes{v3.7b}{2023/12/30}{use ";" instead of "," as delimiter}
% \changes{v3.7e}{2024/07/17}{Use "/" instead of ";" as delimiter}
%    \begin{macrocode}
    \gdef\cb@pdfxy##1##2##3##4##5{%
      \immediate\write\cb@writexy{##1.##2p##3/##4/##5}%
      \expandafter\gdef\csname cb@##1.##2\endcsname{##3,##4,##5}}
  \else\cb@pdftexerror\fi\fi\fi}
%    \end{macrocode}
%    Give a warning if we cannot support the \Lopt{pdftex} option.
%    \begin{macrocode}
\def\cb@pdftexerror{\PackageError
      {changebar}%
      {PDFTeX option cannot be used}%
      {You are using a LaTeX run which does not generate PDF\MessageBreak
        or you are using a very old version of PDFTeX}}
%    \end{macrocode}
%
%    \begin{macrocode}
\DeclareOption{XeTeX}{\cb@xetexcheck}
\DeclareOption{xetex}{\cb@xetexcheck}
%    \end{macrocode}
% \changes{v3.6a}{2005/05/23}{XeTeX support added}
%    For the \Lopt{xetex} option we have to check that the current
%    \LaTeX{} run is using Xe\TeX{}.
%    If it is, we initialize the option and open an additional output file.
%    If not, we ignore the option and issue a warning..
%    \begin{macrocode}
\def\cb@xetexcheck{%
  \expandafter\ifx\csname XeTeXrevision\endcsname\@undefined \cb@xetexerror
  \else
    \global\chardef\cb@driver@setup=7\relax
    \ifx\cb@writexy\@undefined
      \newwrite\cb@writexy
      \newread\cb@readxy
      \immediate\openout\cb@writexy=\jobname.cb2\relax
    \fi
%    \end{macrocode}
%    Redefine the |\cb@pdfxy| macro to write point coordinates to the
%    \file{.cb2} file.
% \changes{v3.7b}{2023/12/30}{use ";" instead of "," as delimiter}
% \changes{v3.7e}{2024/07/17}{Use "/" instead of ";" as delimiter}
%    \begin{macrocode}
    \gdef\cb@pdfxy##1##2##3##4##5{%
      \immediate\write\cb@writexy{##1.##2p##3/##4/##5}%
      \expandafter\gdef\csname cb@##1.##2\endcsname{##3,##4,##5}}
    \gdef\sec@nd@ftw@##1 ##2{##2}
  \fi}
%    \end{macrocode}
%
%    Give a warning if we cannot support the \Lopt{xetex} option.
%    \begin{macrocode}
\def\cb@xetexerror{\PackageError
      {changebar}%
      {XeTeX option cannot be used}%
      {You are not using XeLaTeX}}
%    \end{macrocode}
%
%    \begin{macrocode}
\DeclareOption{luaTeX}{\cb@luatexcheck}
\DeclareOption{luatex}{\cb@luatexcheck}
%    \end{macrocode}
% \changes{v3.6e}{2023/08/13}{luaTeX support added}
%    For the \Lopt{luatex} option we have to check that the current
%    \LaTeX{} run is using lua\TeX{}.
%    If it is, we initialize the option and open an additional output file.
%    If not, we ignore the option and issue a warning..
%    \begin{macrocode}
\def\cb@luatexcheck{%
  \ifx\directlua\@undefined \cb@luatexerror
  \else
    \global\chardef\cb@driver@setup=8\relax
    \ifx\cb@writexy\@undefined
      \newwrite\cb@writexy
      \newread\cb@readxy
      \immediate\openout\cb@writexy=\jobname.cb2\relax
    \fi
%    \end{macrocode}
%    Redefine the |\cb@pdfxy| macro to write point coordinates to the
%    \file{.cb2} file.
% \changes{v3.7b}{2023/12/30}{use ";" instead of ",¨ as delimiter}
% \changes{v3.7e}{2024/07/17}{Use "/" instead of ";" as delimiter}
%    \begin{macrocode}
    \gdef\cb@pdfxy##1##2##3##4##5{%
      \immediate\write\cb@writexy{##1.##2p##3/##4/##5}%
      \expandafter\gdef\csname cb@##1.##2\endcsname{##3,##4,##5}}
  \fi}
%    \end{macrocode}
%
%    Give a warning if we cannot support the \Lopt{luatex} option.
%    \begin{macrocode}
\def\cb@luatexerror{\PackageError
      {changebar}%
      {luaTeX option cannot be used}%
      {You are not using luaLaTeX}}
%    \end{macrocode}
%
%    The new features of \LaTeXe\ make it possible to implement the
%    \Lopt{outerbars} option.
% \changes{v3.5a}{2005/05/23}{Changes for better twocolumn support}
%    \begin{macrocode}
\DeclareOption{outerbars}{\def\cb@barsplace{1}}
\DeclareOption{innerbars}{\def\cb@barsplace{0}}
%    \end{macrocode}
%
%    It is also possible to specify that the change bars should
%    \emph{always} be printed on either the left or the right side of
%    the text. For this we have the options \Lopt{leftbars} and
%    \Lopt{rightbars}. Specifying \emph{either} of these options will
%    overrule a possible \Lopt{twoside} option at the document level.
% \changes{v3.2b}{1995/06/27}{Added the options\Lopt{leftbars} and
%    \Lopt{rightbars}}
% \changes{v3.3d}{1997/10/28}{Removed bogus offset}
% \changes{v3.3g}{1999/06/11}{take the setting of \Lopt{twoside} into
%    account}
% \changes{v3.5a}{2005/05/23}{Changes for better twocolumn support}
%    \begin{macrocode}
\DeclareOption{leftbars}{\def\cb@barsplace{2}}
\DeclareOption{rightbars}{\def\cb@barsplace{3}}
%    \end{macrocode}
% \changes{v3.3j}{2000/09/26}{\cs{cb@even@right} erroneously wasn't
%    set in the oneside mode with option rightbars}
%    A set of options to control tracing.
% \changes{v3.4b}{2001/08/27}{Added tracing of push and pop
%    operations}
%    \begin{macrocode}
\DeclareOption{traceon}{\@cb@tracetrue}
\DeclareOption{traceoff}{\@cb@tracefalse}
\DeclareOption{tracestacks}{%
  \let\cb@trace@stack\cb@@show@stack
  \def\cb@trace@push#1{\cb@trace{%
      Pushed point \the\cb@topleft\space on \noexpand#1: #1}}%
  \def\cb@trace@pop#1{\cb@trace{%
      Popped point \the\cb@topleft\space from \noexpand#1: #1}}%
  }
%    \end{macrocode}
%    Three options are introduced for colour support. The first one,
%    \Lopt{grey}, is activated by default.
% \changes{v3.4b}{2001/08/28}{Added options \Lopt{grey} and
%    \Lopt{color}}
%    \begin{macrocode}
\DeclareOption{grey}{%
  \def\cb@ps@color{\thechangebargrey\space 100 div setgray}}
%    \end{macrocode}
%    The second option activates support for the \pkg{color} package.
%    \begin{macrocode}
\DeclareOption{color}{%
  \def\cb@ps@color{\expandafter\c@lor@to@ps\cb@current@color\@@}%
  \def\cb@color@pkg{color}}
%    \end{macrocode}
%    The third option adds support for the \pkg{xcolor} package.
% \changes{v3.4h}{2004/08/26}{Added option \Lopt{xcolor} to support
%    the \pkg{xcolor} package}
%    \begin{macrocode}
\DeclareOption{xcolor}{%
  \def\cb@ps@color{\expandafter\c@lor@to@ps\cb@current@color\@@}%
  \def\cb@color@pkg{xcolor}}
%    \end{macrocode}
%
%    Signal an error if an unknown option was specified.
% \changes{v3.5a}{2005/05/23}{Added 'pdftex' to the option list}
% \changes{v3.6a}{2011/04/30}{Added 'xetex' to the option list}
%    \begin{macrocode}
\DeclareOption*{\OptionNotUsed\PackageError
      {changebar}%
      {Unrecognised option `\CurrentOption'\MessageBreak
        known options are dvitoln03, dvitops, dvips,\MessageBreak
        emtex, textures, pdftex, vtex and xetex, 
        grey, color, xcolor,\MessageBreak
        outerbars, innerbars, leftbars and rightbars}}
%    \end{macrocode}
%
%    The default is to have grey change bars on the left side of the
%    text on odd pages. When V\TeX\ is used the option \Lopt{dvips} is
%    not the right one, so in that case we have \Lopt{vtex} as the
%    default driver.
%    When PDF\TeX{} is producing PDF output, the \Lopt{pdftex} option is
%    selected. 
% \changes{v3.2c}{1996/03/26}{Added `dvips' to the list of default
%    options} 
% \changes{v3.4b}{2001/08/28}{Added `grey' to the list of default
%    options}
% \changes{v3.4d}{2001/09/04}{Added detection of V\TeX}
% \changes{v3.5a}{2005/05/23}{Added detection of PDF\TeX}
% \changes{v3.6a}{2011/04/30}{Added detection of Xe\TeX}
%    \begin{macrocode}
\ifx\VTeXversion\@undefined
  \expandafter\ifx\csname XeTeXrevision\endcsname\@undefined
    \ifx\pdfoutput\@undefined
      \ExecuteOptions{innerbars,traceoff,dvips,grey}
    \else
      \ifnum\pdfoutput>0
        \ExecuteOptions{innerbars,traceoff,pdftex,grey}
      \else
        \ExecuteOptions{innerbars,traceoff,dvips,grey}
      \fi
    \fi
  \else
    \ExecuteOptions{innerbars,traceoff,xetex,grey}
  \fi
\else
  \ExecuteOptions{innerbars,traceoff,vtex,grey}
\fi
%    \end{macrocode}
%
%    A local configuration file may be used to define a site wide
%    default for the driver, by calling |\ExecuteOptions| with the
%    appropriate option. This will override the default specified
%    above.
% \changes{v3.4d}{2001/09/04}{Added the possibility of loading a
%    configuration file}
%    \begin{macrocode}
\InputIfFileExists{changebar.cfg}{}{}
%    \end{macrocode}
%
%  \begin{macro}{\cb@@show@stack}
% \changes{v3.3g}{1999/06/11}{Macro added}
%    When the stack tracing facility is turned on this command is
%    executed. It needs to be defined \emph{before} we call
%    |\ProcessOptions|. This command shows the contents of the stack
%    with currently `open' bars, the stack with pending ends and the
%    history stack. It does \emph{not} show the temporary stack.
% \changes{v3.3h}{1999/06/15}{Added the historystack to the stack
%    tracing}
%    \begin{macrocode}
\def\cb@@show@stack#1{%
  \cb@trace{%
    stack status at #1:\MessageBreak
    current stack: \cb@currentstack\MessageBreak
    \@spaces end stack: \cb@endstack\MessageBreak
    \space\space begin stack: \cb@beginstack\MessageBreak
    history stack: \cb@historystack 
    }}
%    \end{macrocode}
%    The default is to \emph{not} trace the stacks. This is achieved by
%    |\let|ting |\cb@trace@stack| to |\@gobble|.
%    \begin{macrocode}
\let\cb@trace@stack\@gobble
%    \end{macrocode}
%  \end{macro}
%
%  \begin{macro}{\cb@trace@push}
%  \begin{macro}{\cb@trace@pop}
% \changes{v3.4b}{2001/08/27}{Added macros for tracing stack push and
%    pop operations} 
%    When stack tracing is turned on, these macros are used to display
%    the push and pop operations that go on. They are defined when the 
%    package option \Lopt{tracestacks} is selected.
%
%    The default is to \emph{not} trace the stacks. 
%    \begin{macrocode}
\let\cb@trace@push\@gobble
\let\cb@trace@pop\@gobble
%    \end{macrocode}
%  \end{macro}
%  \end{macro}
%
%    Now make all the selected options active, but...
%    \begin{macrocode}
\ProcessOptions\relax
%    \end{macrocode}
%
%    We have to make sure that when the document is being processed by
%    pdf\LaTeX, while also creating pdf as output, the driver to be
%    used is the pdf driver. Therefore we add an extra check, possibly
%    overriding a \Lopt{dvips} option that might still have been in
%    the doucment.
% \changes{v3.5b}{2005/05/31}{Added an extra check for pdftex in pdf
%    mode}
%    \begin{macrocode}
\ifx\pdfsavepos\@undefined
\else
  \ifx\pdfoutput\@undefined
  \else
    \ifnum\pdfoutput>0
      \global\chardef\cb@driver@setup=6\relax
    \fi
  \fi
\fi
%    \end{macrocode}
%
%  \begin{macro}{\cb@trace}
%    A macro that formats the tracing messages.
% \changes{v3.3g}{1999/06/11}{removed line number from tracing
%    messages}
%    \begin{macrocode}
\newcommand{\cb@trace}[1]{%
  \if@cb@trace
    \GenericWarning
      {(changebar)\@spaces\@spaces}%
      {Package changebar: #1\@gobble}%
  \fi
  }
%    \end{macrocode}
%  \end{macro}
%
% \subsection{User Level Commands And Parameters}
%
% \begin{macro}{\driver}
%    The user can select the specials that should be used by calling
%    the command |\driver{|\meta{drivername}|}|.
% \changes{v3.5a}{2005/05/23}{Added 'PDFtex' option}
%    Possible choices are:
%    \begin{itemize}
%    \item DVItoLN03
%    \item DVItoPS
%    \item DVIps
%    \item em\TeX
%    \item \TeX tures
%    \item V\TeX
%    \item PDF\TeX
%    \item Xe\TeX
%    \end{itemize}
%    This command can only be used in the preamble of the document.
%
%    The argument should be case-insensitive, so it is turned into
%    a string containing all uppercase characters. To keep some definitions
%    local, everything is done within a group.
% \changes{v3.1}{1993/07/02}{Removed some spurious spaces}
% \changes{v3.2c}{1996/03/26}{Reintroduced \cs{driver} in
%    compatibility mode} 
% \changes{v3.3e}{1998/02/24}{Added \cs{Textures}}
% \changes{v3.5a}{2005/05/23}{Added 'PDFtex' option}
% \changes{v3.6a}{2011/04/30}{Added 'XeTeX' option}
%    \changes{v3.6e}{2023/08/13}{Added 'luaTeX' option}
%    \begin{macrocode}
\if@compatibility
  \def\driver#1{%
    \bgroup\edef\next{\def\noexpand\tempa{#1}}%
      \uppercase\expandafter{\next}%
      \def\LN{DVITOLN03}%
      \def\DVItoPS{DVITOPS}%
      \def\DVIPS{DVIPS}%
      \def\emTeX{EMTEX}%
      \def\Textures{TEXTURES}%
      \def\VTeX{VTEX}%
      \def\pdfTeX{PDFTEX}%
      \def\xeTeX{XETEX}
      \def\luaTeX{LUATEX}
%    \end{macrocode}
%
%    The choice has to be communicated to the macro
%    \verb=\cb@setup@specials= that will be called from within
%    \verb=\document=. For this purpose the control sequence
%    \verb=\cb@driver@setup= is used. It receives a numeric value
%    using \verb=\chardef=. 
% \changes{v3.6a}{2011/04/30}{Added 'XeTeX' option}
% \changes{v3.6e}{2023/08/13}{Added 'luaTeX' option}
%    \begin{macrocode}
      \global\chardef\cb@driver@setup=0\relax
      \ifx\tempa\LN       \global\chardef\cb@driver@setup=0\fi
      \ifx\tempa\DVItoPS  \global\chardef\cb@driver@setup=1\fi
      \ifx\tempa\DVIPS    \global\chardef\cb@driver@setup=2\fi
      \ifx\tempa\emTeX    \global\chardef\cb@driver@setup=3\fi
      \ifx\tempa\Textures \global\chardef\cb@driver@setup=4\fi
      \ifx\tempa\VTeX     \global\chardef\cb@driver@setup=5\fi
      \ifx\tempa\pdfTeX   \cb@pdftexcheck\fi
      \ifx\tempa\xeTeX    \cb@xetexcheck\fi
      \ifx\tempa\luaTeX   \cb@luatexcheck\fi
    \egroup}
%    \end{macrocode}
%    We add \verb+\driver+ to \verb+\@preamblecmds+, which is a
%    list of commands to be used only in the preamble of a document.
%    \begin{macrocode}
  {\def\do{\noexpand\do\noexpand}
    \xdef\@preamblecmds{\@preamblecmds \do\driver}
    }
\fi
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\cb@setup@specials}
%    The macro |\cb@setup@specials| defines macros containing the
%    driver specific |\special| macros. It will be called from
%    within the |\begin{document}| command.
%
%  \begin{macro}{\cb@trace@defpoint}
%    When tracing is on, write information about the point being defined
%    to the log file.
% \changes{v3.3a}{1997/09/26}{use \cs{cb@trace} instead of \cs{wlog}}
%    \begin{macrocode}
\def\cb@trace@defpoint#1#2{%
  \cb@trace{%
    defining point \the#1 at position \the#2
    \MessageBreak
    cb@pagecount: \the\cb@pagecount; page \thepage}}
%    \end{macrocode}
%  \end{macro}
%
%
%  \begin{macro}{\cb@trace@connect}
%    When tracing is on, write information about the points being
%    connected to the log file.
% \changes{v3.3a}{1997/09/26}{use \cs{cb@trace} instead of \cs{wlog}}
%    \begin{macrocode}
\def\cb@trace@connect#1#2#3{%
  \cb@trace{%
    connecting points \the#1 and \the#2; barwidth: \the#3
    \MessageBreak
    cb@pagecount: \the\cb@pagecount; page \thepage}}
%    \end{macrocode}
%  \end{macro}
%
% \begin{macro}{\cb@defpoint}
%    The macro |\cb@defpoint| is used to define one of the two
%    points of a bar. It has two arguments, the number of the point
%    and the distance from the left side of the paper. Its syntax
%    is:
%    |\cb@defpoint{|\meta{number}|}{|\meta{length}|}|.
% \begin{macro}{\cb@resetpoints}
%    The macro |\cb@resetpoints| can be used to instruct the printer
%    driver that it should send a corresponding instruction to the
%    printer. This is really only used for the \textsf{LN03} printer.
%
% \begin{macro}{\cb@connect}
%    The macro |\cb@connect| is used to instruct the printer driver
%    to connect two points with a bar. The syntax is
%    |\cb@connect{|\meta{number}|}{|\meta{number}|}{|\meta{length}|}|
%    The two \meta{number}s indicate the two points to be connected;
%    the \meta{length} is the width of the bar.
%
%    \begin{macrocode}
\def\cb@setup@specials{%
%    \end{macrocode}
%    The control sequence |\cb@driver@setup| expands to a number which
%    indicates the driver that will be used.  The original
%    \file{changebar.sty} was written with only the |\special|
%    syntax of the program \texttt{DVItoLN03} (actually one of its
%    predecessors, \texttt{ln03dvi}). Therefore this syntax is defined
%    first.
%    \begin{macrocode}
\ifcase\cb@driver@setup
  \def\cb@defpoint##1##2{%
    \special{ln03:defpoint \the##1(\the##2,)}%
    \cb@trace@defpoint##1##2}
  \def\cb@connect##1##2##3{%
    \special{ln03:connect \the##1\space\space \the##2\space \the##3}%
    \cb@trace@connect##1##2##3}
  \def\cb@resetpoints{%
    \special{ln03:resetpoints \cb@minpoint \space\cb@maxpoint}}
%    \end{macrocode}
%    The first extension to the \textsf{changebar} package was for the
%    |\special| syntax of the program \texttt{DVItoPS} by James Clark.
%    \begin{macrocode}
\or
  \def\cb@defpoint##1##2{%
    \special{dvitops: inline
                \expandafter\cb@removedim\the##2\space 6.5536 mul\space
                /CBarX\the##1\space exch def currentpoint exch pop
                /CBarY\the##1\space exch def}%
    \cb@trace@defpoint##1##2}
%    \end{macrocode}
% \changes{v3.4b}{2001/08/29}{now use \cs{cb@ps@color} instead of
%    setting the greyness directly}
%    \begin{macrocode}
  \def\cb@connect##1##2##3{%
    \special{dvitops: inline
                gsave \cb@ps@color\space
                \expandafter\cb@removedim\the##3\space 6.5536 mul\space
                CBarX\the##1\space\space CBarY\the##1\space\space moveto
                CBarX\the##2\space\space CBarY\the##2\space\space lineto
                stroke grestore}%
    \cb@trace@connect##1##2##3}
  \let\cb@resetpoints\relax
%    \end{macrocode}
%    The program \texttt{DVIps} by Thomas Rokicki is also
%    supported. The PostScript code is nearly the same as for
%    \texttt{DVItoPS}, but the coordinate space has a different
%    dimension. Also this code has been made resolution independent,
%    whereas the code for \texttt{DVItoPS} might still be resolution
%    dependent.
%
%    So far all the positions have been calculated in \texttt{pt}
%    units.  DVIps uses pixels internally, so we have to convert
%    \texttt{pt}s into pixels which of course is done by dividing by
%    72.27 (\texttt{pt}s per inch) and multiplying by
%    \texttt{Resolution} giving the resolution of the
%    \textsc{PostScript} device in use as a \textsc{PostScript}
%    variable.
%    \begin{macrocode}
\or
  \def\cb@defpoint##1##2{%
     \special{ps:
                \expandafter\cb@removedim\the##2\space
                Resolution\space mul\space 72.27\space div\space
                /CBarX\the##1\space exch def currentpoint exch pop
                /CBarY\the##1\space exch def}%
    \cb@trace@defpoint##1##2}
%    \end{macrocode}
% \changes{v3.4b}{2001/08/29}{now use \cs{cb@ps@color} instead of
%    setting the greyness directly}
%    \begin{macrocode}
  \def\cb@connect##1##2##3{%
    \special{ps:
                gsave \cb@ps@color\space
                \expandafter\cb@removedim\the##3\space
                Resolution\space mul\space 72.27\space div\space
                setlinewidth
                CBarX\the##1\space\space CBarY\the##1\space\space moveto
                CBarX\the##2\space\space CBarY\the##2\space\space lineto
                stroke grestore}%
    \cb@trace@connect##1##2##3}
  \let\cb@resetpoints\relax
%    \end{macrocode}
%    The following addition is for the drivers written by Eberhard
%    Mattes.  The |\special| syntax used here is supported since
%    version 1.5 of his driver programs.
% \changes{v3.3a}{1997/09/24}{Removed warning about emTeX support from
%    dvidrv 1.5 upwards}  
% \changes{v3.3b}{1997/10/01}{em\TeX{} drivers have their origin in a
%    different position then dvips} 
% \changes{v3.3d}{1997/10/28}{Removed bogus offset}
%    \begin{macrocode}
\or
  \def\cb@defpoint##1##2{%
    \special{em:point \the##1,\the##2}%
    \cb@trace@defpoint##1##2}
  \def\cb@connect##1##2##3{%
    \special{em:line \the##1,\the##2,\the##3}%
    \cb@trace@connect##1##2##3}
  \let\cb@resetpoints\relax
%    \end{macrocode}
%
%    The following definitions are validated with \TeX tures
%    version~1.7.7, but will very likely also work with later
%    releases of \TeX tures. 
%
%    The \cs{cbdelete} command seemed to create degenerate lines
%    (i.e., lines of 0 length). PostScript will not render such lines
%    unless the linecap is set to 1, (semicircular ends) in which case
%    a filled circle is shown for such lines.
% \changes{v3.3e}{1998/02/24}{Added the definitions for textures
%    support}
% \changes{v3.5c}{2005/09/18}{A small change was submitted by Gordon
%    Lee from Blue Sky Systems}
%    \begin{macrocode}
\or
  \def\cb@defpoint##1##2{%
    \special{postscript 0 0 transform}% leave [x,y] on the stack
    \special{rawpostscript
                \expandafter\cb@removedim\the##2\space
                /CBarX\the##1\space exch def
                itransform exch pop
                /CBarY\the##1\space exch def}%
    \if@cb@trace\cb@trace@defpoint##1##2\fi}
%    \end{macrocode}
% \changes{v3.4b}{2001/08/29}{now use \cs{cb@ps@color} instead of
%    setting the greyness directly}
%    \begin{macrocode}
  \def\cb@connect##1##2##3{%
    \special{rawpostscript
                gsave 1 setlinecap \cb@ps@color\space
                \expandafter\cb@removedim\the##3\space
                setlinewidth
                CBarX\the##1\space\space CBarY\the##1\space\space moveto
                CBarX\the##2\space\space CBarY\the##2\space\space lineto
                stroke grestore}%
    \if@cb@trace\cb@trace@connect##1##2##3\fi}
  \let\cb@resetpoints\relax
%    \end{macrocode}
%    The following definitions were kindly provided by Michael Vulis.
% \changes{v3.4a}{2001/04/18}{Added the definitions for V\TeX\
%    support}
%    \begin{macrocode}
\or
  \def\cb@defpoint##1##2{%
    \special{pS:
                \expandafter\cb@removedim\the##2\space
                Resolution\space mul\space 72.27\space div\space
                /CBarX\the##1\space exch def currentpoint exch pop
                /CBarY\the##1\space exch def}%
    \cb@trace@defpoint##1##2}
%    \end{macrocode}
% \changes{v3.4b}{2001/08/29}{now use \cs{cb@ps@color} instead of
%    setting the greyness directly}
%    \begin{macrocode}
  \def\cb@connect##1##2##3{%
    \special{pS:
                gsave \cb@ps@color\space
                \expandafter\cb@removedim\the##3\space
                Resolution\space mul\space 72.27\space div\space
                setlinewidth
                CBarX\the##1\space\space CBarY\the##1\space\space moveto
                CBarX\the##2\space\space CBarY\the##2\space\space lineto
                stroke grestore}%
    \cb@trace@connect##1##2##3}
  \let\cb@resetpoints\relax
%    \end{macrocode}
% \changes{v3.5a}{2005/05/23}{PDF\TeX{} support added}
%    The code for PDF\TeX{} is more elaborate as the calculations have to
%    be done in \TeX. |\cb@defpoint| will write information about the
%    coordinates of the point to the \file{.aux} file, from where it will
%    be picked up in the next run. Then we will construct the PDF
%    code necessary to draw the changebars.
%    \begin{macrocode}
\or
  \immediate\closeout\cb@writexy
  \immediate\openin\cb@readxy=\jobname.cb2\relax
%    \end{macrocode}
%
% \begin{macro}{\cb@pdfpoints}
% \begin{macro}{\cb@pdfpagenr}
%   The |\cb@pdfpoints| macro contains the list of coordinates of points
%   that have been read in memory from the \file{.cb2} file. The
%   |\cb@pdfpagenr| macro contains the next pagecount to be read in.
%    \begin{macrocode}
  \def\cb@pdfpoints{}
  \def\cb@pdfpagenr{0}
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \begin{macro}{\cb@findpdfpoint}
%    The |\cb@findpdfpoint| macro finds the coordinates of point \#1 on
%    pagecount \#2. First we expand the arguments to get the real values.
%    \begin{macrocode}
  \def\cb@findpdfpoint##1##2{%
      \edef\cb@temp
        {\noexpand\cb@@findpdfpoint{\the##1}{\the##2}}%
      \cb@temp
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\cb@@findpdfpoint}
%   The |\cb@@findpdfpoint| macro finds the coordinates of point \#1 on
%   pagecount \#2. \cbdelete The coordinates of the current point in the text
%   will be delivered in |\cb@pdfx| and |\cb@pdfy|, and |\cb@pdfz| will get
%   the x coordinate of the changebar. If the point is unknown, |\cb@pdfx|
%   will be set to |\relax|. 
%   \begin{changebar} %^^A 3.7g
% \changes{v3.7g}{2026/07/18}{Look records up in the control
%    sequences \cs{cb@}\meta{point}\texttt{.}\meta{pagecount} that
%    \cs{cb@pdfxy} defines while the auxiliary file is replayed,
%    instead of scanning the \cs{cb@pdfpoints} list; the list scan
%    moves, unchanged, to \cs{cb@listfindpdfpoint}}
%
%    Scanning |\cb@pdfpoints| gets expensive when the list grows: the
%    recursive |\cb@pdffind| re-absorbs the whole remainder of the
%    list as a macro argument at every element it steps over, and a
%    search that fails removes nothing. On a run during which the
%    page breaks move (the situation described at |\cb@checkpage|,
%    where nearly every lookup asks for a pagecount that disagrees
%    with the recorded one and therefore fails) the list only ever
%    grows and every later search scans all of it; with a few
%    thousand bars such a run can take hours. |\cb@pdfxy| already
%    stores every record in a control sequence
%    |\cb@|\meta{point}|.|\meta{pagecount} while the auxiliary file
%    is replayed, and as long as point numbers are unique that store
%    is an exact index of the list, so we probe it directly. Two
%    details preserve the original behaviour: a record that has been
%    delivered once is removed from the list by |\cb@pdffind|, so a
%    marker |\cb@xyused@|\meta{point}|.|\meta{pagecount} makes any
%    second lookup fail just as it would have; and the check
%    performed at the end of the document must see every record
%    again, so once |\if@cb@enddocument| is set the markers are
%    ignored and no new ones are recorded. When point numbers are
%    not unique the original code path in |\cb@listfindpdfpoint| is
%    taken instead: later records overwrite earlier ones in the
%    control-sequence store, which makes it unreliable exactly then.
%    \begin{macrocode}
  \def\cb@@findpdfpoint##1##2{%
    \if@cb@pointsunique
      \let\cb@pdfx\relax
      \ifnum##2<0\relax\else
        \ifcsname cb@##1.##2\endcsname
          \if@cb@enddocument
            \edef\cb@temp{\csname cb@##1.##2\endcsname}%
            \expandafter\cb@parsexyrecord\cb@temp\cb@xynil
          \else
            \ifcsname cb@xyused@##1.##2\endcsname
            \else
              \edef\cb@temp{\csname cb@##1.##2\endcsname}%
              \expandafter\cb@parsexyrecord\cb@temp\cb@xynil
              \global\expandafter\let
                \csname cb@xyused@##1.##2\endcsname\@empty
            \fi
          \fi
        \fi
      \fi
    \else
      \cb@listfindpdfpoint{##1}{##2}%
    \fi
  }
%    \end{macrocode}
%  \end{changebar} %^^A 3.7g
% \end{macro}
%
% \begin{macro}{\cb@listfindpdfpoint}
% \changes{v3.7g}{2026/07/18}{Macro added; it contains the previous
%    body of \cs{cb@@findpdfpoint}, unchanged}
% \begin{changebar} %^^A 3.7g
%   If the information is not yet in memory it is read from
%   the \file{.cb2} file.
%    \begin{macrocode}
  \def\cb@listfindpdfpoint##1##2{%
%    \end{macrocode}
%   \end{changebar} %^^A 3.7g
%    \begin{macrocode}
    \ifnum##2<\cb@pdfpagenr\relax\else
      \cb@pdfreadxy{##2}%
    \fi
    \let\cb@pdfx\relax
    \ifx\cb@pdfpoints\@empty\else
      \ifnum##2<0\relax
      \else
        \edef\cb@temp{\noexpand\cb@pdffind{##1}{##2}\cb@pdfpoints\relax{}}%
        \cb@temp
      \fi
    \fi
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\cb@pdffind}
%    The |\cb@pdffind| recursively searches through |\cb@pdfpoints| to find
%    point \#1 on pagecount \#2. |\cb@pdfpoints| contains entries of the
%    form\\
%    \meta{pointnr}.\meta{pagecount}p\meta{x},\meta{y},\meta{z}pt.
%    When the point is found it is removed from |\cb@pdfpoints|. \#9
%    contains the cumulative head of the list to construct the new list
%    with the entry removed. \#3--\#8 are for pattern matching.
% \changes{v3.7b}{2023/12/30}{use ";" instead of "," as delimiter}
% \changes{v3.7e}{2024/07/17}{Use "/" instead of ";" as delimiter}
%    \begin{macrocode}
  \def\cb@pdffind##1##2##3.##4p##5/##6/##7pt##8\relax##9{%
    \def\cb@next{%
      \cb@pdffind{##1}{##2}##8\relax{##9##3.##4p##5/##6/##7pt}}%
    \ifnum ##1=##3
      \ifnum ##2=##4
        \def\cb@pdfx{##5sp}%
        \def\cb@pdfy{##6sp}%
        \def\cb@pdfz{##7pt}%
        \let\cb@next\relax
        \gdef\cb@pdfpoints{##9##8}%
      \fi
    \fi
    \ifx\relax##8\relax
      \let\cb@next\relax
    \fi
    \cb@next
  }%
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\cb@pdfreadxy}
%    The |\cb@pdfreadxy| macro reads lines from the \file{.cb2} file in
%    |\cb@pdfpoints| until the pagecount is greater than \#1 or the end of
%    the file is reached. This ensures that all entries belonging to the
%    current column are in memory.
%    \begin{macrocode}
  \def\cb@pdfreadxy##1{%
    \let\cb@next\relax
    \ifeof\cb@readxy
      \global\let\cb@pdfpagenr\cb@maxpoint
    \else
      {\endlinechar=-1\read\cb@readxy to\cb@temp
        \ifx\cb@temp\@empty\else
          \expandafter\cb@pdfparsexy\cb@temp
          \ifnum\cb@pdfpg<0\else
            \xdef\cb@pdfpoints{\cb@pdfpoints\cb@temp}%
            \cb@trace{PDFpoints=\cb@pdfpoints}%
            \global\let\cb@pdfpagenr\cb@pdfpg
          \fi
          \ifnum\cb@pdfpg>##1\else
            \global\def\cb@next{\cb@pdfreadxy{##1}}%
          \fi
        \fi
      }%
    \fi
    \cb@next
  }%
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\cb@pdfparsexy}
%    The |\cb@pdfparsexy| macro extracts the pagecount from an entry read in
%    from the \file{.cb2} file.
%    \changes{v3.7e}{2024/07/17}{Use "/" instead of ";" as delimiter}
%    \begin{macrocode}
  \def\cb@pdfparsexy##1.##2p##3/##4/##5pt{%
    \def\cb@pdfpg{##2}}%
%    \end{macrocode}
% \end{macro}
%
%    As PDF is not a programming language it does not have any variables to
%    remember the coordinates of the current point. Therefore we write the
%    information to the \file{.aux} file and read it in in the next run. We
%    write the x,y coordinates of the current point in the text and the x
%    coordinate of the change bar. 
%    We also need the value of |\cb@pagecount| here, not during the write.
%    \begin{macrocode}
  \def\cb@defpoint##1##2{%
    \if@filesw
      \begingroup
        \edef\point{{\the##1}{\the\cb@pagecount}}%
        \let\the=\z@
        \pdfsavepos
        \edef\cb@temp{\write\@auxout
          {\string\cb@pdfxy\point
            {\the\pdflastxpos}{\the\pdflastypos}{\the##2}}}%
        \cb@temp
      \endgroup
    \fi
    \cb@trace@defpoint##1##2%
  }%
%    \end{macrocode}
%
% \begin{macro}{\cb@cvtpct}
%    The macro |\cb@cvtpct| converts a percentage between 0 and 100 to a
%    decimal fraction.
%    \begin{macrocode}
  \def\cb@cvtpct##1{%
    \ifnum##1<0 0\else
    \ifnum##1>99 1\else
    \ifnum##1<10 0.0\the##1\else
    0.\the##1\fi\fi\fi}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\cb@pdf@scale}
% \changes{v3.6a}{2018/02/03}{Added macro for scale factor}
%    In order to get things in the right spot we need a little scaling
%    factor. We define it here.
%    \begin{macrocode}
  \def\cb@pdf@scale{0.996264009963}
%    \end{macrocode}
% \end{macro}
%
%    The |\cb@connect| finds the coordinates of the begin and end points,
%    converts them to PDF units and draws the bar with |\pdfliteral|. It
%    also sets the color or gray level, if necessary. When any of the
%    points is unknown the bar is skipped and a rerun is signalled.
%    \begin{macrocode}
  \def\cb@connect##1##2##3{%
    \cb@findpdfpoint{##1}\cb@pagecount
    \ifx\cb@pdfx\relax\cb@rerun
    \else
      \let\cb@pdftopy\cb@pdfy
      \cb@findpdfpoint{##2}\cb@pagecount
      \ifx\cb@pdfx\relax\cb@rerun
      \else
%    \end{macrocode}
%    We do everything in a group, so that we can freely use all kinds of
%    registers.
%    \begin{macrocode}
         \begingroup
           \cb@dima=\cb@pdfz
           \advance\cb@dima by-\cb@pdfx
           \advance\cb@dima by1in%
           \cb@dima=\cb@pdf@scale\cb@dima\relax
%    \end{macrocode}
%    First we let PDF save the graphics state. Then we generate the color
%    selection code followed by the code to draw the changebar. Finally the
%    graphics state is restored. We cannot use the color commands from the
%    color package here, as the generated PDF code may be moved to the next
%    line.
%    \begin{macrocode}
           \ifx\cb@current@color\@undefined
             \def\cb@temp{\cb@cvtpct\c@changebargrey}%
             \pdfliteral{q \cb@temp\space g \cb@temp\space G}%
           \else
             \pdfliteral{q \cb@current@color}%
           \fi
           \edef\cb@temp{\expandafter\cb@removedim\the\cb@dima\space}%
           \cb@dima=\cb@pdftopy
           \advance\cb@dima-\cb@pdfy\relax
           \cb@dima=\cb@pdf@scale\cb@dima\relax
           ##3=\cb@pdf@scale##3\relax
           \pdfliteral direct{\expandafter\cb@removedim\the##3 w
             \cb@temp 0 m
             \cb@temp \expandafter\cb@removedim\the\cb@dima\space l S Q}%
        \endgroup
%    \end{macrocode}
%    We look up the two unused points to get them removed from |\cb@pdfpoints|.
%    \begin{macrocode}
        \cb@cntb=##1\relax
        \ifodd\cb@cntb\advance\cb@cntb 1\else\advance\cb@cntb -1\fi
        \cb@findpdfpoint\cb@cntb\cb@pagecount
        \cb@cntb=##2\relax
        \ifodd\cb@cntb\advance\cb@cntb 1\else\advance\cb@cntb -1\fi
        \cb@findpdfpoint\cb@cntb\cb@pagecount
      \fi
    \fi
    \cb@trace@connect##1##2##3%
  }%
%    \end{macrocode}
%
% \begin{macro}{\cb@checkPdfxy}
%    The macro |\cb@checkPdfxy| checks if the coordinates of a point have
%    changed during the current run. If so, we need to rerun \LaTeX.
% \changes{v3.6c}{2018/03/09}{Use \cs{ifdim} instead of \cs{ifnum} as
%    \cs{cb@pdfx} is defined as a dimension}
%    \begin{macrocode}
  \gdef\cb@checkPdfxy##1##2##3##4##5{%
    \cb@@findpdfpoint{##1}{##2}%
%    \end{macrocode}
%    \begin{macrocode}
    \ifdim##3sp=\cb@pdfx\relax
      \ifdim##4sp=\cb@pdfy\relax
%    \end{macrocode}
%    \begin{macrocode}
        \ifdim##5=\cb@pdfz\relax
        \else
        \cb@error
        \fi
      \else
        \cb@error
      \fi
    \else
      \cb@error
    \fi
  }
%    \end{macrocode}
% \end{macro}
%
%    For PDF\TeX{} we don't need a limit on the number of bar points.
%    \begin{macrocode}
  \def\cb@maxpoint{9999999}
  \let\cb@resetpoints\relax
\or
%    \end{macrocode}
%
% \changes{v3.6a}{2011/04/30}{Xe\TeX{} support added}
%    The code for Xe\TeX{} is, like for PDF\TeX{}, more elaborate as
%    the calculations have to 
%    be done in \TeX. |\cb@defpoint| will write information about the
%    coordinates of the point to the \file{.aux} file, from where it will
%    be picked up in the next run. Then we will construct the PDF
%    code necessary to draw the changebars.
%    \begin{macrocode}
  \immediate\closeout\cb@writexy
  \immediate\openin\cb@readxy=\jobname.cb2\relax
%    \end{macrocode}
%
% \begin{macro}{\cb@pdfpoints}
% \begin{macro}{\cb@pdfpagenr}
%   The |\cb@pdfpoints| macro contains the list of coordinates of points
%   that have been read in memory from the \file{.cb2} file. The
%   |\cb@pdfpagenr| macro contains the next pagecount to be read in.
%    \begin{macrocode}
  \def\cb@pdfpoints{}
  \def\cb@pdfpagenr{0}
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
%  \begin{macro}{\cb@findpdfpoint}
%    The |\cb@findpdfpoint| macro finds the coordinates of point \#1 on
%    pagecount \#2. First we expand the arguments to get the real values.
%    \begin{macrocode}
  \def\cb@findpdfpoint##1##2{%
      \edef\cb@temp
        {\noexpand\cb@@findpdfpoint{\the##1}{\the##2}}%
      \cb@temp
  }
%    \end{macrocode}
%  \end{macro}
%
%  \begin{macro}{\pdfliteral}
%    For Xe\TeX{} we mimick PDF\TeX's command |\pdfliteral|.
%    \begin{macrocode}
  \def\pdfliteral##1{\special{pdf:literal ##1}}
%    \end{macrocode}
%  \end{macro}
%
% \begin{macro}{\cb@@findpdfpoint}
%   The |\cb@@findpdfpoint| macro finds the coordinates of point \#1 on
%   pagecount \#2. \cbdelete The coordinates of the current point in the text
%   will be delivered in |\cb@pdfx| and |\cb@pdfy|, and |\cb@pdfz| will get
%   the x coordinate of the changebar. If the point is unknown, |\cb@pdfx|
%   will be set to |\relax|.
%   \begin{changebar} %^^A 3.7g
% \changes{v3.7g}{2026/07/18}{Look records up in the control
%    sequences \cs{cb@}\meta{point}\texttt{.}\meta{pagecount} that
%    \cs{cb@pdfxy} defines while the auxiliary file is replayed,
%    instead of scanning the \cs{cb@pdfpoints} list; the list scan
%    moves, unchanged, to \cs{cb@listfindpdfpoint}}
%
%    Scanning |\cb@pdfpoints| gets expensive when the list grows: the
%    recursive |\cb@pdffind| re-absorbs the whole remainder of the
%    list as a macro argument at every element it steps over, and a
%    search that fails removes nothing. On a run during which the
%    page breaks move (the situation described at |\cb@checkpage|,
%    where nearly every lookup asks for a pagecount that disagrees
%    with the recorded one and therefore fails) the list only ever
%    grows and every later search scans all of it; with a few
%    thousand bars such a run can take hours. |\cb@pdfxy| already
%    stores every record in a control sequence
%    |\cb@|\meta{point}|.|\meta{pagecount} while the auxiliary file
%    is replayed, and as long as point numbers are unique that store
%    is an exact index of the list, so we probe it directly. Two
%    details preserve the original behaviour: a record that has been
%    delivered once is removed from the list by |\cb@pdffind|, so a
%    marker |\cb@xyused@|\meta{point}|.|\meta{pagecount} makes any
%    second lookup fail just as it would have; and the check
%    performed at the end of the document must see every record
%    again, so once |\if@cb@enddocument| is set the markers are
%    ignored and no new ones are recorded. When point numbers are
%    not unique the original code path in |\cb@listfindpdfpoint| is
%    taken instead: later records overwrite earlier ones in the
%    control-sequence store, which makes it unreliable exactly then.
%    \begin{macrocode}
  \def\cb@@findpdfpoint##1##2{%
    \if@cb@pointsunique
      \let\cb@pdfx\relax
      \ifnum##2<0\relax\else
        \ifcsname cb@##1.##2\endcsname
          \if@cb@enddocument
            \edef\cb@temp{\csname cb@##1.##2\endcsname}%
            \expandafter\cb@parsexyrecord\cb@temp\cb@xynil
          \else
            \ifcsname cb@xyused@##1.##2\endcsname
            \else
              \edef\cb@temp{\csname cb@##1.##2\endcsname}%
              \expandafter\cb@parsexyrecord\cb@temp\cb@xynil
              \global\expandafter\let
                \csname cb@xyused@##1.##2\endcsname\@empty
            \fi
          \fi
        \fi
      \fi
    \else
      \cb@listfindpdfpoint{##1}{##2}%
    \fi
  }
%    \end{macrocode}
% \end{changebar} %^^A 3.7g
%
% \end{macro}
%
% \begin{macro}{\cb@listfindpdfpoint}
% \changes{v3.7g}{2026/07/18}{Macro added; it contains the previous
%    body of \cs{cb@@findpdfpoint}, unchanged}
%  \begin{changebar} %^^A 3.7g
%   If the information is not yet in memory it is read from
%   the \file{.cb2} file.
%    \begin{macrocode}
  \def\cb@listfindpdfpoint##1##2{%
%    \end{macrocode}
% \end{changebar} %^^A 3.7g
%    \begin{macrocode}
    \ifnum##2<\cb@pdfpagenr\relax\else
      \cb@pdfreadxy{##2}%
    \fi
    \let\cb@pdfx\relax
    \ifx\cb@pdfpoints\@empty\else
      \ifnum##2<0\relax
      \else
%    \end{macrocode}
% \begin{changebar} %^^A 3.7g
%    \begin{macrocode}
        \edef\cb@temp{%
          \noexpand\cb@pdffind{##1}{##2}\cb@pdfpoints\relax{}}%
%    \end{macrocode}
% \end{changebar} %^^A 3.7g
%    \begin{macrocode}
        \cb@temp
      \fi
    \fi
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\cb@pdffind}
%    The |\cb@pdffind| recursively searches through |\cb@pdfpoints| to find
%    point \#1 on pagecount \#2.  |\cb@pdfpoints| contains entries of the
%    form\\
%    \meta{pointnr}.\meta{pagecount}p\meta{x},\meta{y},\meta{z}pt.
%    When the point is found it is removed from |\cb@pdfpoints|. \#9
%    contains the cumulative head of the list to construct the new list
%    with the entry removed. \#3--\#8 are for pattern matching.
% \changes{v3.7b}{2023/12/30}{use ";" instead of "," as delimiter}
% \changes{v3.7e}{2024/07/17}{Use "/" instead of ";" as delimiter}
%    \begin{macrocode}
  \def\cb@pdffind##1##2##3.##4p##5/##6/##7pt##8\relax##9{%
    \def\cb@next{%
      \cb@pdffind{##1}{##2}##8\relax{##9##3.##4p##5/##6/##7pt}}%
    \ifnum ##1=##3
      \ifnum ##2=##4
        \def\cb@pdfx{##5sp}%
        \def\cb@pdfy{##6sp}%
        \def\cb@pdfz{##7pt}%
        \let\cb@next\relax
        \gdef\cb@pdfpoints{##9##8}%
      \fi
    \fi
    \ifx\relax##8\relax
      \let\cb@next\relax
    \fi
    \cb@next
  }%
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\cb@pdfreadxy}
%    The |\cb@pdfreadxy| macro reads lines from the \file{.cb2} file in
%    |\cb@pdfpoints| until the pagecount is greater than \#1 or the end of
%    the file is reached. This ensures that all entries belonging to the
%    current column are in memory.
%    \begin{macrocode}
  \def\cb@pdfreadxy##1{%
    \let\cb@next\relax
    \ifeof\cb@readxy
      \global\let\cb@pdfpagenr\cb@maxpoint
    \else
      {\endlinechar=-1\read\cb@readxy to\cb@temp
        \ifx\cb@temp\@empty\else
          \expandafter\cb@pdfparsexy\cb@temp
          \ifnum\cb@pdfpg<0\else
            \xdef\cb@pdfpoints{\cb@pdfpoints\cb@temp}%
            \cb@trace{PDFpoints=\cb@pdfpoints}%
            \global\let\cb@pdfpagenr\cb@pdfpg
          \fi
          \ifnum\cb@pdfpg>##1\else
            \global\def\cb@next{\cb@pdfreadxy{##1}}%
          \fi
        \fi
      }%
    \fi
    \cb@next
  }%
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\cb@pdfparsexy}
%    The |\cb@pdfparsexy| macro extracts the pagecount from an entry read in
%    from the \file{.cb2} file.
%    \changes{v3.7e}{2024/07/17}{Use "/" instead of ";" as delimiter}
%    \begin{macrocode}
  \def\cb@pdfparsexy##1.##2p##3/##4/##5pt{%
    \def\cb@pdfpg{##2}}%
%    \end{macrocode}
% \end{macro}
%
%    As \textsc{pdf} is not a programming language it does not have
%    any variables to remember the coordinates of the current
%    point. Therefore we write the information to the \file{.aux} file
%    and read it in in the next run. We write the x,y coordinates of
%    the current point in the text and the x coordinate of the change bar. 
%    We also need the value of |\cb@pagecount| here, not during the write.
%    \begin{macrocode}
  \def\cb@defpoint##1##2{%
    \if@filesw
      \begingroup
        \edef\point{{\the##1}{\the\cb@pagecount}}%
        \let\the=\z@
        \pdfsavepos
        \edef\cb@temp{\write\@auxout
          {\string\cb@pdfxy\point
            {\the\pdflastxpos}{\the\pdflastypos}{\the##2}}}%
        \cb@temp
      \endgroup
    \fi
    \cb@trace@defpoint##1##2%
  }%
%    \end{macrocode}
%
% \begin{macro}{\cb@cvtpct}
%    The macro |\cb@cvtpct| converts a percentage between 0 and 100 to a
%    decimal fraction.
%    \begin{macrocode}
  \def\cb@cvtpct##1{%
    \ifnum##1<0 0\else
    \ifnum##1>99 1\else
    \ifnum##1<10 0.0\the##1\else
    0.\the##1\fi\fi\fi}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\cb@pdf@scale}
% \changes{v3.6a}{2018/02/03}{Added macro for scale factor}
%    In order to get things in the right spot we need a little scaling
%    factor. We define it here.
%    \begin{macrocode}
  \def\cb@pdf@scale{0.996264009963}
%    \end{macrocode}
% \end{macro}
%
%    The |\cb@connect| finds the coordinates of the begin and end points,
%    converts them to PDF units and draws the bar with |\pdfliteral|. It
%    also sets the color or gray level, if necessary. When any of the
%    points is unknown the bar is skipped and a rerun is signalled.
%    \begin{macrocode}
  \def\cb@connect##1##2##3{%
    \cb@findpdfpoint{##1}\cb@pagecount
    \ifx\cb@pdfx\relax\cb@rerun
    \else
      \let\cb@pdftopy\cb@pdfy
      \cb@findpdfpoint{##2}\cb@pagecount
      \ifx\cb@pdfx\relax\cb@rerun
      \else
%    \end{macrocode}
%    We do everything in a group, so that we can freely use all kinds of
%    registers.
%    \begin{macrocode}
         \begingroup
           \cb@dima=\cb@pdfz
           \advance\cb@dima by-\cb@pdfx
           \advance\cb@dima by1in%
           \cb@dima=\cb@pdf@scale\cb@dima\relax
%    \end{macrocode}
%    First we let PDF save the graphics state. Then we generate the color
%    selection code followed by the code to draw the changebar. Finally the
%    graphics state is restored. We cannot use the color commands from the
%    color package here, as the generated PDF code may be moved to the next
%    line.
%    \begin{macrocode}
           \ifx\cb@current@color\@undefined
             \def\cb@temp{\cb@cvtpct\c@changebargrey}%
             \pdfliteral{q \cb@temp\space g \cb@temp\space G}%
           \else
             \pdfliteral{q \expandafter\sec@nd@ftw@\cb@current@color\space RG 
                           \expandafter\sec@nd@ftw@\cb@current@color\space rg}%
           \fi
           \edef\cb@temp{\expandafter\cb@removedim\the\cb@dima\space}%
           \cb@dima=\cb@pdftopy
           \advance\cb@dima-\cb@pdfy\relax
           \cb@dima=\cb@pdf@scale\cb@dima\relax
           ##3=\cb@pdf@scale##3\relax
           \pdfliteral{\expandafter\cb@removedim\the##3 w
             \cb@temp 0 m
             \cb@temp \expandafter\cb@removedim\the\cb@dima\space l S Q}%
        \endgroup
%    \end{macrocode}
%    We look up the two unused points to get them removed from |\cb@pdfpoints|.
%    \begin{macrocode}
        \cb@cntb=##1\relax
        \ifodd\cb@cntb\advance\cb@cntb 1\else\advance\cb@cntb -1\fi
        \cb@findpdfpoint\cb@cntb\cb@pagecount
        \cb@cntb=##2\relax
        \ifodd\cb@cntb\advance\cb@cntb 1\else\advance\cb@cntb -1\fi
        \cb@findpdfpoint\cb@cntb\cb@pagecount
      \fi
    \fi
    \cb@trace@connect##1##2##3%
  }%
%    \end{macrocode}
%
% \begin{macro}{\cb@checkPdfxy}
%    The macro |\cb@checkPdfxy| checks if the coordinates of a point have
%    changed during the current run. If so, we need to rerun \LaTeX.
%    \begin{macrocode}
  \gdef\cb@checkPdfxy##1##2##3##4##5{%
    \cb@@findpdfpoint{##1}{##2}%
    \ifdim##3sp=\cb@pdfx\relax
      \ifdim##4sp=\cb@pdfy\relax
        \ifdim##5=\cb@pdfz\relax
        \else
        \cb@error
        \fi
      \else
        \cb@error
      \fi
    \else
      \cb@error
    \fi
  }
%    \end{macrocode}
% \end{macro}
%
%    For Xe\TeX{} we don't need a limit on the number of bar points.
%    \begin{macrocode}
  \def\cb@maxpoint{9999999}
  \let\cb@resetpoints\relax
%    \end{macrocode}
%
% \changes{v3.6e}{2023/08/13}{lua\TeX{} support added}
%    The code for lua\TeX{}, like for pdf\TeX\ and Xe\TeX,
%    is more elaborate as the calculations have to
%    be done in \TeX. |\cb@defpoint| will write information about the
%    coordinates of the point to the \file{.aux} file, from where it will
%    be picked up in the next run. Then we will construct the PDF
%    code necessary to draw the changebars.
%    \begin{macrocode}
\or
  \immediate\closeout\cb@writexy
  \immediate\openin\cb@readxy=\jobname.cb2\relax
%    \end{macrocode}
%
% \begin{macro}{\cb@pdfpoints}
% \begin{macro}{\cb@pdfpagenr}
%   The |\cb@pdfpoints| macro contains the list of coordinates of points
%   that have been read in memory from the \file{.cb2} file. The
%   |\cb@pdfpagenr| macro contains the next pagecount to be read in.
%    \begin{macrocode}
  \def\cb@pdfpoints{}
  \def\cb@pdfpagenr{0}
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\cb@findpdfpoint}
%    The |\cb@findpdfpoint| macro finds the coordinates of point \#1 on
%    pagecount \#2. First we expand the arguments to get the real values.
%    \begin{macrocode}
  \def\cb@findpdfpoint##1##2{%
      \edef\cb@temp
        {\noexpand\cb@@findpdfpoint{\the##1}{\the##2}}%
      \cb@temp
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pdfliteral}
%    For lua\TeX{} we also mimick PDF\TeX's command |\pdfliteral|.
%    \begin{macrocode}
  \def\pdfliteral##1{\pdfextension literal {##1}}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\cb@@findpdfpoint}
%   The |\cb@@findpdfpoint| macro finds the coordinates of point \#1 on
%   pagecount \#2. The coordinates of the current point in the text
%   will be delivered in |\cb@pdfx| and |\cb@pdfy|, and |\cb@pdfz| will get
%   the x coordinate of the changebar. If the point is unknown, |\cb@pdfx|
%   will be set to |\relax|.
%   \begin{changebar} %^^A 3.7g
% \changes{v3.7g}{2026/07/18}{Look records up in the control
%    sequences \cs{cb@}\meta{point}\texttt{.}\meta{pagecount} that
%    \cs{cb@pdfxy} defines while the auxiliary file is replayed,
%    instead of scanning the \cs{cb@pdfpoints} list; the list scan
%    moves, unchanged, to \cs{cb@listfindpdfpoint}}
%
%    Scanning |\cb@pdfpoints| gets expensive when the list grows: the
%    recursive |\cb@pdffind| re-absorbs the whole remainder of the
%    list as a macro argument at every element it steps over, and a
%    search that fails removes nothing. On a run during which the
%    page breaks move (the situation described at |\cb@checkpage|,
%    where nearly every lookup asks for a pagecount that disagrees
%    with the recorded one and therefore fails) the list only ever
%    grows and every later search scans all of it; with a few
%    thousand bars such a run can take hours. |\cb@pdfxy| already
%    stores every record in a control sequence
%    |\cb@|\meta{point}|.|\meta{pagecount} while the auxiliary file
%    is replayed, and as long as point numbers are unique that store
%    is an exact index of the list, so we probe it directly. Two
%    details preserve the original behaviour: a record that has been
%    delivered once is removed from the list by |\cb@pdffind|, so a
%    marker |\cb@xyused@|\meta{point}|.|\meta{pagecount} makes any
%    second lookup fail just as it would have; and the check
%    performed at the end of the document must see every record
%    again, so once |\if@cb@enddocument| is set the markers are
%    ignored and no new ones are recorded. When point numbers are
%    not unique the original code path in |\cb@listfindpdfpoint| is
%    taken instead: later records overwrite earlier ones in the
%    control-sequence store, which makes it unreliable exactly then.
%    \begin{macrocode}
  \def\cb@@findpdfpoint##1##2{%
    \if@cb@pointsunique
      \let\cb@pdfx\relax
      \ifnum##2<0\relax\else
        \ifcsname cb@##1.##2\endcsname
          \if@cb@enddocument
            \edef\cb@temp{\csname cb@##1.##2\endcsname}%
            \expandafter\cb@parsexyrecord\cb@temp\cb@xynil
          \else
            \ifcsname cb@xyused@##1.##2\endcsname
            \else
              \edef\cb@temp{\csname cb@##1.##2\endcsname}%
              \expandafter\cb@parsexyrecord\cb@temp\cb@xynil
              \global\expandafter\let
                \csname cb@xyused@##1.##2\endcsname\@empty
            \fi
          \fi
        \fi
      \fi
    \else
      \cb@listfindpdfpoint{##1}{##2}%
    \fi
  }
%    \end{macrocode}
% \end{changebar} %^^A 3.7g
% \end{macro}
%
% \begin{macro}{\cb@listfindpdfpoint}
% \changes{v3.7g}{2026/07/18}{Macro added; it contains the previous
%    body of \cs{cb@@findpdfpoint}, unchanged}
% \begin{changebar} %^^A 3.7g
%   If the information is not yet in memory it is read from
%   the \file{.cb2} file.
%    \begin{macrocode}
  \def\cb@listfindpdfpoint##1##2{%
%    \end{macrocode}
% \end{changebar} %^^A 3.7g
%    \begin{macrocode}
    \ifnum##2<\cb@pdfpagenr\relax\else
      \cb@pdfreadxy{##2}%
    \fi
    \let\cb@pdfx\relax
    \ifx\cb@pdfpoints\@empty\else
      \ifnum##2<0\relax
      \else
%    \end{macrocode}
% \begin{changebar} %^^A 3.7g
%    \begin{macrocode}
        \edef\cb@temp{%
          \noexpand\cb@pdffind{##1}{##2}\cb@pdfpoints\relax{}}%
%    \end{macrocode}
% \end{changebar} %^^A 3.7g
%    \begin{macrocode}
        \cb@temp
      \fi
    \fi
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\cb@pdffind}
%    The |\cb@pdffind| recursively searches through |\cb@pdfpoints| to find
%    point \#1 on pagecount \#2.  |\cb@pdfpoints| contains entries of the
%    form\\
%    \meta{pointnr}.\meta{pagecount}p\meta{x},\meta{y},\meta{z}pt.
%    When the point is found it is removed from |\cb@pdfpoints|. \#9
%    contains the cumulative head of the list to construct the new list
%    with the entry removed. \#3--\#8 are for pattern matching.
% \changes{v3.7b}{2023/12/30}{use ";" instead of "," as delimiter}
% \changes{v3.7e}{2024/07/17}{Use "/" instead of ";" as delimiter}
%    \begin{macrocode}
  \def\cb@pdffind##1##2##3.##4p##5/##6/##7pt##8\relax##9{%
    \def\cb@next{%
      \cb@pdffind{##1}{##2}##8\relax{##9##3.##4p##5/##6/##7pt}}%
    \ifnum ##1=##3
      \ifnum ##2=##4
        \def\cb@pdfx{##5sp}%
        \def\cb@pdfy{##6sp}%
        \def\cb@pdfz{##7pt}%
        \let\cb@next\relax
        \gdef\cb@pdfpoints{##9##8}%
      \fi
    \fi
    \ifx\relax##8\relax
      \let\cb@next\relax
    \fi
    \cb@next
  }%
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\cb@pdfreadxy}
%    The |\cb@pdfreadxy| macro reads lines from the \file{.cb2} file in
%    |\cb@pdfpoints| until the pagecount is greater than \#1 or the end of
%    the file is reached. This ensures that all entries belonging to the
%    current column are in memory.
%    \begin{macrocode}
  \def\cb@pdfreadxy##1{%
    \let\cb@next\relax
    \ifeof\cb@readxy
      \global\let\cb@pdfpagenr\cb@maxpoint
    \else
      {\endlinechar=-1\read\cb@readxy to\cb@temp
        \ifx\cb@temp\@empty\else
          \expandafter\cb@pdfparsexy\cb@temp
          \ifnum\cb@pdfpg<0\else
            \xdef\cb@pdfpoints{\cb@pdfpoints\cb@temp}%
            \cb@trace{PDFpoints=\cb@pdfpoints}%
            \global\let\cb@pdfpagenr\cb@pdfpg
          \fi
          \ifnum\cb@pdfpg>##1\else
            \global\def\cb@next{\cb@pdfreadxy{##1}}%
          \fi
        \fi
      }%
    \fi
    \cb@next
  }%
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\cb@pdfparsexy}
%    The |\cb@pdfparsexy| macro extracts the pagecount from an entry read in
%    from the \file{.cb2} file.
%    \changes{v3.7e}{2024/07/17}{Use "/" instead of ";" as delimiter}
%    \begin{macrocode}
  \def\cb@pdfparsexy##1.##2p##3/##4/##5pt{%
    \def\cb@pdfpg{##2}}%
%    \end{macrocode}
% \end{macro}
%
%     As PDF is not a programming language it does not have any variables to
%    remember the coordinates of the current point. Therefore we write the
%    information to the \file{.aux} file and read it in in the next run. We
%    write the x,y coordinates of the current point in the text and the x
%    coordinate of the change bar. 
%    We also need the value of |\cb@pagecount| here, not during the write.
%    \begin{macrocode}
  \def\cb@defpoint##1##2{%
    \if@filesw
      \begingroup
        \edef\point{{\the##1}{\the\cb@pagecount}}%
        \let\the=\z@
        \savepos
        \edef\cb@temp{\write\@auxout
          {\string\cb@pdfxy\point
            {\the\lastxpos}{\the\lastypos}{\the##2}}}%
        \cb@temp
      \endgroup
    \fi
    \cb@trace@defpoint##1##2%
  }%
%    \end{macrocode}
%
% \begin{macro}{\cb@cvtpct}
%    The macro |\cb@cvtpct| converts a percentage between 0 and 100 to a
%    decimal fraction.
%    \begin{macrocode}
  \def\cb@cvtpct##1{%
    \ifnum##1<0 0\else
    \ifnum##1>99 1\else
    \ifnum##1<10 0.0\the##1\else
    0.\the##1\fi\fi\fi}
%    \end{macrocode}
%  \end{macro}
%  
% \begin{macro}{\cb@pdf@scale}
% \changes{v3.6a}{2018/02/03}{Added macro for scale factor}
%    In order to get things in the right spot we need a little scaling
%    factor. We define it here.
%    \begin{macrocode}
  \def\cb@pdf@scale{0.996264009963}
%    \end{macrocode}
% \end{macro}
%
%     The |\cb@connect| finds the coordinates of the begin and end points,
%    converts them to PDF units and draws the bar with |\pdfliteral|. It
%    also sets the color or gray level, if necessary. When any of the
%    points is unknown the bar is skipped and a rerun is signalled.
%    \begin{macrocode}
  \def\cb@connect##1##2##3{%
    \cb@findpdfpoint{##1}\cb@pagecount
    \ifx\cb@pdfx\relax\cb@rerun
    \else
      \let\cb@pdftopy\cb@pdfy
      \cb@findpdfpoint{##2}\cb@pagecount
      \ifx\cb@pdfx\relax\cb@rerun
      \else
%    \end{macrocode}
%    We do everything in a group, so that we can freely use all kinds of
%    registers.
%    \begin{macrocode}
         \begingroup
           \cb@dima=\cb@pdfz
           \advance\cb@dima by-\cb@pdfx
           \advance\cb@dima by1in%
           \cb@dima=\cb@pdf@scale\cb@dima\relax
%    \end{macrocode}
%    First we let PDF save the graphics state. Then we generate the color
%    selection code followed by the code to draw the changebar. Finally the
%    graphics state is restored. We cannot use the color commands from the
%    color package here, as the generated PDF code may be moved to the next
%    line.
%    \begin{macrocode}
           \ifx\cb@current@color\@undefined
             \def\cb@temp{\cb@cvtpct\c@changebargrey}%
             \pdfliteral{q \cb@temp\space g \cb@temp\space G}%
           \else
             \pdfliteral{q \cb@current@color}%
           \fi
           \edef\cb@temp{\expandafter\cb@removedim\the\cb@dima\space}%
           \cb@dima=\cb@pdftopy
           \advance\cb@dima-\cb@pdfy\relax
           \cb@dima=\cb@pdf@scale\cb@dima\relax
           ##3=\cb@pdf@scale##3\relax
           \pdfliteral{\expandafter\cb@removedim\the##3 w
             \cb@temp 0 m
             \cb@temp \expandafter\cb@removedim\the\cb@dima\space l S Q}%
        \endgroup
%    \end{macrocode}
%    We look up the two unused points to get them removed from |\cb@pdfpoints|.
%    \begin{macrocode}
        \cb@cntb=##1\relax
        \ifodd\cb@cntb\advance\cb@cntb 1\else\advance\cb@cntb -1\fi
        \cb@findpdfpoint\cb@cntb\cb@pagecount
        \cb@cntb=##2\relax
        \ifodd\cb@cntb\advance\cb@cntb 1\else\advance\cb@cntb -1\fi
        \cb@findpdfpoint\cb@cntb\cb@pagecount
      \fi
    \fi
    \cb@trace@connect##1##2##3%
  }%
%    \end{macrocode}
%
% \begin{macro}{\cb@checkPdfxy}
%    The macro |\cb@checkPdfxy| checks if the coordinates of a point have
%    changed during the current run. If so, we need to rerun \LaTeX.
%    \begin{macrocode}
  \gdef\cb@checkPdfxy##1##2##3##4##5{%
    \cb@@findpdfpoint{##1}{##2}%
    \ifdim##3sp=\cb@pdfx\relax
      \ifdim##4sp=\cb@pdfy\relax
        \ifdim##5=\cb@pdfz\relax
        \else
        \cb@error
        \fi
      \else
        \cb@error
      \fi
    \else
      \cb@error
    \fi
  }
%    \end{macrocode}
% \end{macro}
%
%    For lua\TeX{} we don't need a limit on the number of bar points.
%    \begin{macrocode}
  \def\cb@maxpoint{9999999}
  \let\cb@resetpoints\relax
%    \end{macrocode}
% 
%    When code for other drivers should be added it can be inserted
%    here.  When someone makes a mistake and somehow selects an
%    unknown driver a warning is issued and the macros are defined to
%    be no-ops.
%    \begin{macrocode}
\else
  \PackageWarning{Changebar}{changebars not supported in unknown setup}
  \def\cb@defpoint##1##2{\cb@trace@defpoint##1##2}
  \def\cb@connect##1##2##3{\cb@trace@connect##1##2##3}
  \let\cb@resetpoints\relax
\fi
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
%
% The last thing to do is to forget about |\cb@setup@specials|.
%    \begin{macrocode}
\global\let\cb@setup@specials\relax}
%    \end{macrocode}
% \end{macro}
% 
% \begin{macro}{\cbstart}
%    The macro |\cbstart| starts a new changebar. It has an (optional)
%    argument that will be used to determine the width of the bar.
%    The default width is |\changebarwidth|.
% \changes{v3.3i}{1999/06/19}{Use \LaTeX's own mechanism to detect
%    grouping errors.}
% \changes{v3.4e}{2002/10/28}{Reverted the change from version 3.3i} 
%    \begin{macrocode}
\newcommand*{\cbstart}{\@ifnextchar[%]
                        {\cb@start}%
                        {\cb@start[\changebarwidth]}}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\cbend}
%    The macro |\cbend| (surprisingly) ends a changebar. The macros
%    |\cbstart| and |\cbend| can be used when the use of a
%    proper \LaTeX\ environment is not possible.
%    \begin{macrocode}
\newcommand*{\cbend}{\cb@end}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\cbdelete}
%    The macro |\cbdelete| inserts a `deletebar' in the margin.
%    It too has an optional argument to determine the width of the bar.
%    The default width (and length) of it are stored in
%    |\deletebarwidth|.
%    \begin{macrocode}
\newcommand*{\cbdelete}{\@ifnextchar[%]
  {\cb@delete}%
  {\cb@delete[\deletebarwidth]}}
%    \end{macrocode}
%
% \begin{macro}{\cb@delete}
%    Deletebars are implemented as a special `change bar'. The bar
%    is started and immediately ended. It is as long as it is wide.
%    \begin{macrocode}
\def\cb@delete[#1]{\vbox to \z@{\vss\cb@start[#1]\vskip #1\cb@end}}
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\changebar}
% \begin{macro}{\endchangebar}
%    The macros |\changebar| and |\endchangebar| have the same
%    function as |\cbstart| and |\cbend| but they can be used as a
%    \LaTeX\ environment to enforce correct nesting.  They can
%    \emph{not} be used in the \textsf{tabular} and \textsf{tabbing}
%    environments.
%    \begin{macrocode}
\newenvironment{changebar}%
               {\@ifnextchar[{\cb@start}%]
                             {\cb@start[\changebarwidth]}}%
               {\cb@end}
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\nochangebars}
%    To disable changebars altogether without having to remove them
%    from the document the macro |\nochangebars| is provided. It makes
%    no-ops of three internal macros.
% \changes{v3.7d}{2024/01/09}{Make sure spaces are ignored (cf. change
%    3.7c)}
%    \begin{macrocode}
\newcommand*{\nochangebars}{%
  \def\cb@start[##1]{\ignorespaces}%
  \def\cb@delete[##1]{}%
  \def\cb@end{\ignorespacesafterend}%
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\changebarwidth}
%    The default width of the changebars is stored in the dimension
%    register |\changebarwidth|.
%    \begin{macrocode}
\newlength{\changebarwidth}
\setlength{\changebarwidth}{2pt}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\deletebarwidth}
%    The default width of the deletebars is stored in the dimension
%    register |\deletebarwidth|.
%    \begin{macrocode}
\newlength{\deletebarwidth}
\setlength{\deletebarwidth}{4pt}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\changebarsep}
%    The default separation between all bars and the text is stored in
%    the dimen register |\changebarsep|.
% \changes{v3.6b}{2018/02/04}{set the default separtion between text
%    and changebars to half the separation between text and marginal
%    paragraphs} 
%    \begin{macrocode}
\newlength{\changebarsep}
\setlength{\changebarsep}{0.5\marginparsep}
%    \end{macrocode}
% \end{macro}
%
% \begin{Var}{changebargrey}
%    When the document is printed using one of the PostScript drivers
%    the bars do not need to be black; with PostScript it is possible
%    to have grey, and colored, bars. The percentage of greyness of the
%    bar is stored in the count register |\changebargrey|. It can
%    have values between $0$ (meaning white) and $100$ (meaning
%    black).
%
%    \begin{macrocode}
\newcounter{changebargrey}
\setcounter{changebargrey}{65}
%    \end{macrocode}
% \end{Var}
%
%    When one of the options \Lopt{color} or \Lopt{xcolor} was
%    selected we need to load the appropriate package. When we're run
%    by pdf\LaTeX\ we need to pass that information on to that package.
% \changes{v3.4e}{2001/09/14}{Detect pdf mode}
% \changes{v3.5a}{2005/05/23}{The option \Lopt{pdftex} will be supplied
%    automatically with the current color packages. Leave out
%    \Lopt{dvipsnames} as it is usually automatically loaded and may clash
%    if the color or xcolor package has already been loaded. Also
%    \cs{cb@color@pkg} is undefined when no color option has been given.}
%    \begin{macrocode}
\@ifpackagewith{changebar}{\csname cb@color@pkg\endcsname}{%
    \RequirePackage{\cb@color@pkg}%
%    \end{macrocode}
%    Then we need to define the command |\cbcolor| which is a slightly
%    modified copy of the command |\color| from the \pkg{color}
%    package.
%
% \begin{macro}{\cbcolor}
%    |\cbcolor{|\emph{declared-colour}|}| switches the colour of the
%    changebars to \emph{declared-colour}, which must previously have
%    been defined using |\definecolor|. This colour will stay in
%    effect until the end of the current \TeX\ group.
%
%    |\cbcolor[|\emph{model}|]{|\emph{colour-specification}|}| is
%    similar to the above, but uses a colour not declared by
%    |\definecolor|. The allowed \emph{model}'s vary depending on the
%    driver. The syntax of the \emph{colour-specification} argument
%    depends on the model.
%    \begin{macrocode}
  \DeclareRobustCommand\cbcolor{%
    \@ifnextchar[%]
      \@undeclaredcbcolor\@declaredcbcolor}
%    \end{macrocode}
%  \end{macro}
%
%  \begin{macro}{\@undeclaredcbcolor}
%    Call the driver-dependent command |\color@|\meta{model} to define
%    |\cb@current@color|.
% \changes{v3.5c}{2005/09/18}{Use the higher level interface throug
%    \cs{color} to prevent problemns with \texttt{color.sty} or
%    \texttt{xcolor.sty}}
%    \begin{macrocode}
  \def\@undeclaredcbcolor[#1]#2{%
    \begingroup
      \color[#1]{#2}%
      \global\let\cb@current@color\current@color
    \endgroup
    \ignorespaces
    }
%    \end{macrocode}
%  \end{macro}
%
%  \begin{macro}{\@declaredcbcolor}
% \changes{v3.5c}{2005/09/18}{Use the higher level interface throug
%    \cs{color} to prevent problemns with \texttt{color.sty} or
%    \texttt{xcolor.sty}}
%    \begin{macrocode}
  \def\@declaredcbcolor#1{%
    \begingroup
      \color{#1}%
      \global\let\cb@current@color\current@color
    \endgroup
    \ignorespaces}%
  }{%
%    \end{macrocode}
%    When the \Lopt{color} option wasn't specified the usage of the
%    |\cbcolor| command results in a warning message.
% \changes{v3.4d}{2001/09/04}{Isue an error when \cmd{cbcolor} is
%    used without specifying the \Lopt{color} option}
% \changes{v3.4e}{2001/09/07}{Made the error message a warning message}
%    \begin{macrocode}
  \def\cbcolor{\@ifnextchar[%]
    \@@cbcolor\@cbcolor}%
  \def\@@cbcolor[#1]#2{\cb@colwarn\def\@@cbcolor[##1]##2{}}%
  \def\@cbcolor#1{\cb@colwarn\def\@cbcolor##1{}}%
  \def\cb@colwarn{\PackageWarning{Changebar}%
    {You didn't specify the option `color';\MessageBreak
      your command \string\cbcolor\space will be ignored}}%
  }
%    \end{macrocode}
%  \end{macro}
%
% \subsection{Macros for beginning and ending bars}
%
% \begin{macro}{\cb@start}
%    This macro starts a change bar.  It assigns a new value to the
%    current point and advances the counter for the next point to be
%    assigned.  It pushes this info onto |\cb@currentstack| and then
%    sets the point by calling |\cb@setBeginPoints| with the point
%    number.  Finally, it writes the \file{.aux} file.
% \changes{v3.3h}{1999/06/15}{Added \cs{cb@checkpage} to find final
%    page from history}
%    \begin{macrocode}
\def\cb@start[#1]{%
  \cb@topleft=\cb@nextpoint
%    \end{macrocode}
%    Store the width of the< current bar in |\cb@curbarwd|.
%    \begin{macrocode}
  \cb@curbarwd#1\relax
  \cb@push\cb@currentstack
%    \end{macrocode}
%    Now find out on which page the start of this bar finaly ends up;
%    due to the asynchronous nature of the output routine it might be
%    a different page. The macro |\cb@checkpage| finds the page number
%    on the history stack.
% \changes{v3.5a}{2005/05/23}{Correction for nested changebars}
%    \begin{macrocode}
  \cb@checkpage\z@
%    \end{macrocode}
%    Temporarily assign the page number to |\cb@pagecount| as that
%    register is used by |\cb@setBeginPoints|. Note that it's value is
%    offset by one from the page counter.
%    \begin{macrocode}
  \cb@cnta\cb@pagecount
  \cb@pagecount\cb@page\advance\cb@pagecount\m@ne
  \ifvmode 
    \cb@setBeginPoints
  \else
    \vbox to \z@{%
%    \end{macrocode}
%    When we are in horizontal mode we jump up a line to set the
%    starting point of the changebar.
%    \begin{macrocode}
      \vskip -\ht\strutbox
      \cb@setBeginPoints
      \vskip \ht\strutbox}%
  \fi
%    \end{macrocode}
%    Restore |\cb@pagecount|.
% \changes{v3.7c}{2024/01/01}{Added \cs{ignorespaces} at the end to
%    prevent a spcae token from creaping into the output}
%    \begin{macrocode}
  \cb@pagecount\cb@cnta
  \cb@advancePoint\ignorespaces}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\cb@advancePoint}
%    The macro |\cb@advancePoint| advances the count register
%    |\cb@nextpoint|. When the maximum number is reached, the
%    numbering is reset.
%  \begin{changebar} % ^^A 3.7f
%    \changes{v3.7f}{2026/07/12}{Clear \cs{if@cb@pointsunique} when the
%    point numbering wraps around}
%    When the numbering is reset point numbers are no longer unique
%    and the fast path in |\cb@checkpage| must be disabled, see the
%    description of |\if@cb@pointsunique|.
%  \end{changebar} % ^^A 3.7f
%    \begin{macrocode}
\def\cb@advancePoint{%
  \global\advance\cb@nextpoint by 4\relax
  \ifnum\cb@nextpoint>\cb@maxpoint
    \global\cb@nextpoint=\cb@minpoint\relax
%    \end{macrocode}
%  \begin{changebar} % ^^A 3.7f
%    \begin{macrocode}
    \global\@cb@pointsuniquefalse
%    \end{macrocode}
%  \end{changebar} % ^^A 3.7f
%    \begin{macrocode}
  \fi}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\cb@end}
%    This macro ends a changebar. It pops the current point and
%    nesting level off |\cb@currentstack| and sets the end point by
%    calling |\cb@setEndPoints| with the parameter corresponding to
%    the \emph{beginning} point number. It writes the \file{.aux} file
%    and joins the points.
%    When in horizontal mode we put the call to |\cb@setEndPoints|
%    inside a |\vadjust|. This ensures that things with a large depth,
%    e.g. a parbox or formula will be completely covered. By default
%    these have their baseline centered, and thus otherwise the
%    changebar would stop there.
%
% \changes{v3.3a}{1997/09/26}{Added \cs{ignorespaces}}
% \changes{v3.3g}{1999/06/11}{Added stack tracing}
% \changes{v3.3h}{1999/06/15}{Now check the history stack to find the
%    page on which this point ends up}
% \changes{v3.5a}{2005/05/23}{Added \cs{vadjust} in horizontal mode.}
%    \begin{macrocode}
\def\cb@end{%
  \cb@trace@stack{end of bar on page \the\c@page}%
  \cb@pop\cb@currentstack
  \ifnum\cb@topleft=\cb@nil
    \PackageWarning{Changebar}%
      {Badly nested changebars; Expect erroneous results}%
  \else
%    \end{macrocode}
%    Call |\cb@checkpage| to find the page this point finally ends up
%    on.
% \changes{v3.5a}{2005/05/23}{Correction for nested changebars}
%    \begin{macrocode}
    \cb@checkpage\thr@@
%    \end{macrocode}
%    Again, we need to temporarily overwrite |\cb@pagecount|.
% \changes{v3.7c}{2024/01/01}{We need \cs{ignorespacesafterend} here,
%    not \cs{ignorespaces}} 
%    \begin{macrocode}
    \cb@cnta\cb@pagecount
    \cb@pagecount\cb@page\advance\cb@pagecount\m@ne
    \ifvmode
      \cb@setEndPoints
    \else
      \vadjust{\cb@setEndPoints}%
    \fi
    \cb@pagecount\cb@cnta
  \fi
  \ignorespacesafterend}
%    \end{macrocode}
%\end{macro}
%
%  \begin{changebar} % ^^A 3.7f
% \begin{Var}{@cb@pointsunique}
% \changes{v3.7f}{2026/07/12}{Switch added}
%    The fast path in |\cb@checkpage| below relies on every point
%    number occurring at most once in the history file
%    (\file{\jobname.cb}). Point numbers are reused once
%    |\cb@nextpoint| passes |\cb@maxpoint|, which is small for some
%    of the older drivers. This switch is cleared as soon as reuse is
%    detected -- either while the history entries are replayed from
%    the \file{.aux} file (|\cb@barpoint| sees the same point number
%    twice) or when |\cb@advancePoint| wraps around during the
%    current run -- after which all searches use the original code
%    again.
%    \begin{macrocode}
\newif\if@cb@pointsunique
\@cb@pointsuniquetrue
%    \end{macrocode}
% \end{Var}
%  \end{changebar} % ^^A 3.7f
%
%  \begin{changebar} %^^A 3.7g
% \begin{Var}{@cb@enddocument}
% \changes{v3.7g}{2026/07/18}{Switch added}
%    Set at the start of the |\AtEndDocument| processing. The fast
%    lookup in |c\b@@findpdfpoint| below consumes each coordinate
%    record the first time it is delivered, mirroring the removal of
%    a found record from |\cb@pdfpoints|; the verification pass at
%    the end of the document must see every record again, so while
%    this switch is true the consumed-markers are ignored and no new
%    ones are recorded.
%    \begin{macrocode}
\newif\if@cb@enddocument
%    \end{macrocode}
% \end{Var}
%
% \begin{macro}{\cb@parsexyrecord}
% \changes{v3.7g}{2026/07/18}{Macro added}
%    Deliver a coordinate record stored by |\cb@pdfxy| (of the form
%    \meta{x}|,|\meta{y}|,|\meta{z}, where \meta{x} and \meta{y} are
%    scaled-point numbers and \meta{z} carries its unit) in
%    |\cb@pdfx|, |\cb@pdfy| and |\cb@pdfz|, in exactly the form the
%    list search in |\cb@pdffind| delivers them.
%    \begin{macrocode}
\def\cb@parsexyrecord#1,#2,#3\cb@xynil{%
  \def\cb@pdfx{#1sp}\def\cb@pdfy{#2sp}\def\cb@pdfz{#3}}
%    \end{macrocode}
% \end{macro}
%    \end{changebar} %^^A 3.7g
% 
%  \begin{macro}{\cb@checkpage}
% \changes{v3.3h}{1999/06/15}{Macro added}
%    The macro |\cb@checkpage| checks the history stack in order to
%    find out on which page a set of points finaly ends up.
%
%    We expect the identification of the points in |\cb@topleft| and
%    |\cb@page|. The resulting page will be stored in |\cb@page|.
%    The parameter indicates whether we are searching for a begin
%    point (0) or end point (3).
% \changes{v3.3i}{1999/06/18}{Check for and handle the situation that
%    the history stack is too short due to new bars added to a
%    document}
% \changes{v3.5a}{2005/05/23}{Correction for nested changebars}
%  \begin{changebar} % ^^A 3.7f
% \changes{v3.7f}{2026/07/12}{Skip searches that cannot succeed; the
%    actual search now lives in \cs{cb@@checkpage}}
%
%    Searching the history stack is expensive: |\cb@FindPageNum| pops
%    the whole stack onto |\cb@tempstack| and pushes it back
%    afterwards, and every push or pop rebuilds the complete stack
%    macro, so a search that \emph{fails} costs time quadratic in the
%    number of entries still on the stack. Failed searches are rare
%    while the \file{.aux} data is stable, but on a run during which
%    the page breaks move (in particular the first runs of a document
%    compiled in a fresh directory, where the table of contents and
%    cross references are still missing) |\cb@pushNextActive| may
%    consume entries from the history stack long before the
%    corresponding |\cbstart| or |\cbend| is processed, after which
%    each of these searches fails after scanning the complete stack.
%    With a few hundred change bars such a run takes minutes instead
%    of seconds.
%
%    Fortunately, as long as point numbers are unique (see above),
%    the search never needs to run at all. A search \emph{fails}
%    unless the point was read from the history file
%    (|\cb@bp@|\meta{point} was defined when the \file{.aux} entries
%    were replayed) and has not yet been consumed by
%    |\cb@pushNextActive| (which defines |\cb@used@|\meta{point});
%    a failed search restores all registers and the stack, so
%    skipping it changes nothing. A search that \emph{succeeds} also
%    restores the stack (|\cb@FindPageNum| pushes the scanned
%    entries, including the matched one, back) and every register,
%    except that |\cb@page| receives the page number recorded for
%    the point -- and since |\cb@barpoint| now stores that page
%    number in |\cb@bp@|\meta{point}, the whole successful search
%    can be replaced by one assignment. |\cb@@checkpage| keeps the
%    original search for the non-unique fallback.
%    (|\ifcsname| is available in all engines supported by current
%    \LaTeX{}, which requires the e-\TeX{} extensions.)
%  \end{changebar} % ^^A 3.7f
%    \begin{macrocode}
\def\cb@checkpage#1{%
%    \end{macrocode}
%  \begin{changebar} % ^^A 3.7f
%    \begin{macrocode}
  \if@cb@pointsunique
    \cb@cnta\cb@topleft\relax
    \advance\cb@cnta by #1\relax
    \ifcsname cb@bp@\the\cb@cnta\endcsname
      \ifcsname cb@used@\the\cb@cnta\endcsname
      \else
%    \end{macrocode}
%  \begin{changebar} % ^^A 3.7g
%    \begin{macrocode}
        \cb@page\csname cb@bp@\the\cb@cnta\endcsname\relax
%    \end{macrocode}
%  \end{changebar} % ^^A 3.7g
%    \begin{macrocode}
      \fi
    \fi
  \else
    \cb@@checkpage{#1}%
  \fi}
%    \end{macrocode}
%  \end{changebar} % ^^A 3.7f
% \end{macro}
%
%  \begin{macro}{\cb@@checkpage}
% \changes{v3.7f}{2026/07/12}{Macro added; it contains the previous
%    body of \cs{cb@checkpage}, unchanged}
%  \begin{changebar} % ^^A 3.7f
%    \begin{macrocode}
\def\cb@@checkpage#1{%
%    \end{macrocode}
%    \end{changebar} %^^A 3.7f
%    First store the identifiers in temporary registers.
%    \begin{macrocode}
  \cb@cnta\cb@topleft\relax
  \advance\cb@cnta by #1\relax
  \cb@cntb\cb@page\relax
  \cb@dima\cb@curbarwd\relax
%    \end{macrocode}
%    Then pop the history stack.
%    \begin{macrocode}
  \cb@pop\cb@historystack
%    \end{macrocode}
%    If it was empty there is nothing to check and we're done.
%    \begin{macrocode}
  \ifnum\cb@topleft=\cb@nil
  \else
%    \end{macrocode}
% \changes{v3.5a}{2005/05/23}{Correction for moving floats}
%    Now keep popping the stack until |\cb@topleft| is found. The values
%    popped from the stack are pushed on a temporary stack to be pushed
%    back later. This could perhaps be implemented more efficiently if
%    the stacks had a different design.
%    \begin{macrocode}
    \cb@FindPageNum
%    \end{macrocode}
% \changes{v3.5a}{2005/05/23}{Correction for nested changebars}
%    \begin{macrocode}
    \ifnum\cb@topleft>\cb@maxpoint\else
%    \end{macrocode}
%    Now that we've found it overwrite |\cb@cntb| with the
%    |\cb@page| from the stack.
%    \begin{macrocode}
      \cb@cntb\cb@page
    \fi
%    \end{macrocode}
%    Now we restore the history stack to it's original state.
%    \begin{macrocode}
    \@whilenum\cb@topleft>\cb@nil\do{%
      \cb@push\cb@historystack
      \cb@pop\cb@tempstack}%
  \fi
%    \end{macrocode}
%    Finally return the correct values
% \changes{v3.5a}{2005/05/23}{Correction for nested changebars}
%    \begin{macrocode}
  \advance\cb@cnta by -#1\relax
  \cb@topleft\cb@cnta\relax
  \cb@page\cb@cntb\relax
  \cb@curbarwd\cb@dima\relax
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\cb@FindPageNum}
%    |\cb@FindPageNum| recursively searches through the history stack until
%    an entry is found that is equal to |\cb@cnta|.
%    \begin{macrocode}
\def\cb@FindPageNum{%
  \ifnum\cb@topleft=\cb@cnta
%    \end{macrocode}
%    We have found it, exit the macro, otherwise push the current entry on
%    the temporary stack and pop a new one from the history stack.
%    \begin{macrocode}
  \else
    \cb@push\cb@tempstack
    \cb@pop\cb@historystack
%    \end{macrocode}
%    When the user adds changebars to his document we might run out of
%    the history stack before we find a match. This would send \TeX\
%    into an endless loop if it wasn't detected and handled.
%    \begin{macrocode}
    \ifnum\cb@topleft=\cb@nil
      \cb@trace{Ran out of history stack, new changebar?}%
%    \end{macrocode}
%    In this case we give |\cb@topleft| an `impossible value' to
%    remember this special situation.
%    \begin{macrocode}
      \cb@topleft\cb@maxpoint\advance\cb@topleft\@ne
    \else
%    \end{macrocode}
%    Recursively call ourselves.
%    \begin{macrocode}
      \expandafter\expandafter\expandafter\cb@FindPageNum
    \fi
  \fi
  }%
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\cb@setBeginPoints}
% \changes{v3.3a}{1997/09/26}{Renamed from \cs{cb@setBeginPoint} and
%    removed parameter; use new dimension register for positioning} 
%    The macro |\cb@setBeginPoints| assigns a position to the top left
%    and top right points. It determines wether the point is on an even
%    or an odd page and uses the right dimension to position the
%    point. Keep in mind that the value of |\cb@pagecount| is one
%    less than the value of |\c@page| unless the latter has been reset
%    by the user. 
%
%    The top left point is used to write an entry on the \file{.aux}
%    file to create the history stack on the next run.
% \changes{v3.5a}{2005/05/23}{Correction for mixed onecolumn and twocolumn
%                documents and page number changes}
%    \begin{macrocode}
\def\cb@setBeginPoints{%
  \cb@topright=\cb@topleft\advance\cb@topright by\@ne
  \cb@cntb=\cb@pagecount
  \divide\cb@cntb by\tw@
  \ifodd\cb@cntb
    \cb@defpoint\cb@topleft\cb@even@left
    \cb@defpoint\cb@topright\cb@even@right
  \else
    \cb@defpoint\cb@topleft\cb@odd@left
    \cb@defpoint\cb@topright\cb@odd@right
  \fi
  \cb@writeAux\cb@topleft
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\cb@setEndPoints}
% \changes{v3.3a}{1997/09/26}{Renamed from \cs{cb@setEndPoint} and
%    removed parameter; use new dimension register for positioning} 
%    The macro |\cb@setEndPoints| assigns positions to the bottom
%    points for a change bar. It then instructs the driver to connect
%    two points with a bar. The macro assumes that the width of the
%    bar is stored in |\cb@curbarwd|. 
%
%    The bottom right point is used to write to the \file{.aux} file
%    to signal the end of the current bar on the history stack.
% \changes{v3.3g}{1999/06/12}{Take the setting of \Lopt{twoside} into
%    account}
% \changes{v3.5a}{2005/05/23}{The test for \Lopt{twoside} is really
%    unnecessary if the even side is always chosen for an even page}
% \changes{v3.5a}{2005/05/23}{Correction for mixed onecolumn and twocolumn
%    documents and page number changes}
%    \begin{macrocode}
\def\cb@setEndPoints{%
  \cb@topright=\cb@topleft\advance\cb@topright by\@ne
  \cb@botleft=\cb@topleft\advance\cb@botleft by\tw@
  \cb@botright=\cb@topleft\advance\cb@botright by\thr@@
   \cb@cntb=\cb@pagecount
  \divide\cb@cntb by\tw@
  \ifodd\cb@cntb
    \cb@defpoint\cb@botleft\cb@even@left
    \cb@defpoint\cb@botright\cb@even@right
  \else
    \cb@defpoint\cb@botleft\cb@odd@left
    \cb@defpoint\cb@botright\cb@odd@right
  \fi
  \cb@writeAux\cb@botright
  \edef\cb@leftbar{%
    \noexpand\cb@connect{\cb@topleft}{\cb@botleft}{\cb@curbarwd}}%
  \edef\cb@rightbar{%
    \noexpand\cb@connect{\cb@topright}{\cb@botright}{\cb@curbarwd}}%
%    \end{macrocode}
% \changes{v3.3a}{1997/09/26}{Added support for typesetting twocolumn
%    text with changebars} 
% \changes{v3.5a}{2005/05/23}{Checking |@firstcolumn| outside the output
%    routine is unreliable; check \cs{cb@pagecount} instead}
%    In twocolumn pages always use outerbars
%    \begin{macrocode}
  \if@twocolumn
     \ifodd\cb@pagecount\cb@rightbar\else\cb@leftbar\fi
%    \end{macrocode}
%    
% \changes{v3.4e}{2001/09/07}{The \cs{outerbars} conditional should be
%    inside an \cs{else} clause}
% \changes{v3.5a}{2005/05/23}{Series of \cs{if}s replaced by
%    \cs{ifcase} on \cs{cb@barsplace}}
%    \begin{macrocode}
  \else
    \ifcase\cb@barsplace
%    \end{macrocode}
%    0=innerbars
%    \begin{macrocode}
      \ifodd\cb@cntb
        \cb@rightbar
      \else
        \if@twoside\cb@leftbar\else\cb@rightbar\fi
      \fi
    \or
%    \end{macrocode}
%    1=outerbars
%    \begin{macrocode}
      \ifodd\cb@cntb
        \cb@leftbar
      \else
        \if@twoside\cb@rightbar\else\cb@leftbar\fi
      \fi
    \or
%    \end{macrocode}
%    2=leftbars
%    \begin{macrocode}
      \cb@leftbar
    \or
%    \end{macrocode}
%    3=rightbars
%    \begin{macrocode}
      \cb@rightbar
    \fi
  \fi
  }%
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\cb@writeAux}
%    The macro |\cb@writeAux| writes information about a changebar
%    point to the auxiliary file. The number of the point, the
%    pagenumber and the width of the bar are written out as arguments
%    to |\cb@barpoint|. This latter macro will be expanded when the
%    auxiliary file is read in.  The macro assumes that the width of
%    bar is stored in |\cb@curbarwd|.
%
%    The code is only executed when auxiliary files are enabled, as
%    there's no sense in trying to write to an unopened file.
%    \begin{macrocode}
\def\cb@writeAux#1{%
  \if@filesw
    \begingroup
      \edef\point{\the#1}%
      \edef\level{\the\cb@curbarwd}%
      \let\the=\z@
      \edef\cb@temp{\write\@auxout
        {\string\cb@barpoint{\point}{\the\cb@pagecount}{\level}}}%
      \cb@temp
    \endgroup
  \fi}
%    \end{macrocode}
% \end{macro}
%
% \subsection{Macros for Making It Work Across Page Breaks}
% \label{pagebreak}
%
% \changes{v3.5a}{2005/05/23}{Changes for twocolumn support: Detect page
%    number changes in righthand columns.}
% \begin{Var}{@cb@pagejump}
%    A switch to indicate that we have made a page correction.
%    \begin{macrocode}
\newif\if@cb@pagejump
%    \end{macrocode}
% \end{Var}
% \begin{macro}{\cb@pagejumplist}
%    The list of pagecounts to be corrected.
%    \begin{macrocode}
\def\cb@pagejumplst{-1}
%    \end{macrocode}
% \end{macro}
% \begin{macro}{\cb@nextpagejump}
%    The next pagecount from the list.
%    \begin{macrocode}
\def\cb@nextpagejump{-1}
%    \end{macrocode}
% \end{macro}
% \begin{macro}{\cb@pagejump}
%    This macro is written to the \file{.aux} file when a pagecount in a
%    lefthand column should be corrected. The argument is the incorrect
%    pagecount. 
%    \begin{macrocode}
\def\cb@pagejump#1{\xdef\cb@pagejumplst{\cb@pagejumplst,#1}}
%    \end{macrocode}
% \end{macro}
% \begin{macro}{\cb@writepagejump}
%    This macro writes a |\cb@pagejump| entry to the \file{.aux} file.
%    It does it by putting the |\write| command in the |\@leftcolumn| so
%    that it will be properly positioned relative to the bar points.
%    \begin{macrocode}
\def\cb@writepagejump#1{
  \cb@cntb=\cb@pagecount
  \advance\cb@cntb by#1\relax
  \global\setbox\@leftcolumn\vbox to\@colht{%
    \edef\cb@temp{\write\@auxout{\string\cb@pagejump{\the\cb@cntb}}}%
    \cb@temp
    \dimen@ \dp\@leftcolumn
    \unvbox \@leftcolumn
    \vskip -\dimen@
  }%
}
%    \end{macrocode}
% \end{macro}
% \begin{macro}{\cb@poppagejump}
%    Pop an entry from |pagejumplst|. The entry is put in |\cb@nextpagejump|.
%    \begin{macrocode}
\def\cb@poppagejump#1,#2\relax{%
  \gdef\cb@nextpagejump{#1}%
  \gdef\cb@pagejumplst{#2}}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\cb@checkpagecount}
% \changes{v3.5a}{2005/05/23}{Changes for better twocolumn support}
%    This macro checks that |\cb@pagecount| is correct at the beginning of
%    a column or page.
%    First we ensure that |\cb@pagecount| has the proper parity: odd in the
%    righthand column of a twocolumn page, even in the lefthand column of a
%    twocolumn page and in onecolumn pages.
%    \begin{macrocode}
\def\cb@checkpagecount{%
  \if@twocolumn
    \if@firstcolumn
      \ifodd\cb@pagecount\global\advance\cb@pagecount by\@ne\fi
    \fi
  \else
    \ifodd\cb@pagecount\global\advance\cb@pagecount by\@ne\fi
  \fi
%    \end{macrocode}
% \changes{v3.5a}{2005/05/23}{Changes for better twocolumn support}
%    Also, in twosided documents, |\cb@pagecount|/2 must be odd on even pages
%    and even on odd pages. If necessary, increase |\cb@pagecount| by 2. For
%    onesided documents, we don't do this as it doesn't matter (but it
%    would be harmless).
%    In the righthand column in twoside documents we must check if
%    |\cb@pagecount|/2 has the proper parity (see below).   
%    If it is incorrect, the page number has changed after the lefthand
%    column, so |\cb@pagecount| is incorrect there. Therefore we write a
%    command in the \file{.aux} file so that in the next run the lefthand
%    column will correct its |\cb@pagecount|. We also need to signal
%    a rerun. If the correction was
%    made in the lefthand column, the flag |@cb@pagejump| is set, and we have
%    to be careful in the righthand column. If in the righthand column the
%    flag is set and  |\cb@pagecount| is correct, the correction in the
%    lefthand column worked, but we still have to write into the
%    \file{.aux} file for the next run. If on the other hand
%    |\cb@pagecount| is incorrect while the flag is set, apparently the
%    correction in the lefthand column should not have been done (probably
%    because the document has changed), so we do nothing.
%    \begin{macrocode}
  \if@twoside
    \cb@cntb=\cb@pagecount
    \divide\cb@cntb by\tw@
    \advance\cb@cntb by-\c@page
    \ifodd\cb@cntb
%    \end{macrocode}
%    Here |\cb@pagecount| seems correct. Check if there is a page jump.
%    \begin{macrocode}
      \if@twocolumn
        \if@firstcolumn
          \@whilenum\cb@pagecount>\cb@nextpagejump\do{%
            \expandafter\cb@poppagejump\cb@pagejumplst\relax}%
          \ifnum\cb@pagecount=\cb@nextpagejump
            \cb@trace{Page jump: \string\cb@pagecount=\the\cb@pagecount}
            \global\advance\cb@pagecount by\tw@
            \global\@cb@pagejumptrue
          \else
            \global\@cb@pagejumpfalse
          \fi
        \else
%    \end{macrocode}
%    In the righthand column check the flag (see above). If set, write a
%    pagejump, but compensate for the increase done in the lefthand column.
%    \begin{macrocode}
          \if@cb@pagejump
            \cb@writepagejump{-3}%
          \fi
        \fi
      \fi
    \else
%    \end{macrocode}
%    Here |\cb@pagecount| is incorrect.
%    \begin{macrocode}
      \if@twocolumn
        \if@firstcolumn
          \global\advance\cb@pagecount by\tw@
          \global\@cb@pagejumpfalse
        \else
          \if@cb@pagejump
            \cb@trace{Page jump annulled, %
                      \string\cb@pagecount=\the\cb@pagecount}
          \else
            \cb@writepagejump{-1}%
            \global\advance\cb@pagecount by\tw@
            \cb@rerun
          \fi
        \fi
      \else
        \global\advance\cb@pagecount by\tw@
      \fi
    \fi
  \fi
}    
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@makecol}
% \begin{macro}{\@vtryfc}
%
%    These internal \LaTeX\ macros are modified in order to end the
%    changebars spanning the current page break (if any) and restart
%    them on the next page. The modifications are needed to reset the
%    special points for this page and add begin bars to top of box255.
%    The bars carried over from the previous page, and hence to be
%    restarted on this page, have been saved on the stack
%    |\cb@beginstack|. This stack is used to define new starting
%    points for the change bars, which are added to thetop of box
%    |\@cclv|.  Then the stack |\cb@endstack| is built and 
%    processed by |\cb@processActive|. Finally the original
%    |\@makecol| (saved as |\cb@makecol|) is executed.
%
% \changes{3.2}{1994/04/21}{Added setting of \cs{boxmaxdepth}}
% \changes{v3.3a}{1997/09/26}{Let \cs{cb@writeAux} be \cs{@gobble} to
%    prevent extra entries in the \file{.aux} file}
% \changes{v3.3a}{1997/09/26}{Now use the command
%    \cs{cb@startSpanBars} to define top points for bars spoanning a
%    page break} 
% \changes{v3.5a}{2005/05/23}{Changes for better twocolumn support}
%    \begin{macrocode}
\let\ltx@makecol\@makecol
\def\cb@makecol{%
  \if@twocolumn
    \cb@trace{Twocolumn: \if@firstcolumn Left \else Right \fi column}%
  \fi
  \cb@trace@stack{before makecol, page \the\c@page,
                  \string\cb@pagecount=\the\cb@pagecount}%
  \let\cb@writeAux\@gobble
%    \end{macrocode}
%    First make sure that |\cb@pagecount| is correct.
%    Then add the necessary bar points at beginning and end.
%    \begin{macrocode}
  \cb@checkpagecount
  \setbox\@cclv \vbox{%
    \cb@resetpoints
    \cb@startSpanBars
    \unvbox\@cclv
    \boxmaxdepth\maxdepth}%
  \global\advance\cb@pagecount by\@ne
  \cb@buildstack\cb@processActive
  \ltx@makecol
%    \end{macrocode}
% \changes{v3.5a}{2005/05/23}{Changes for better twocolumn support}
%    In twocolumn pages write information to the aux file to indicate which
%    column we are in. This write must precede the whole column, including
%    floats. Therefore we insert it in the front of |\@outputbox|.
%    \begin{macrocode}
   \if@twocolumn
     \global\setbox\@outputbox \vbox to\@colht {%
       \if@firstcolumn\write\@auxout{\string\@cb@firstcolumntrue}%
       \else\write\@auxout{\string\@cb@firstcolumnfalse}%
       \fi
       \dimen@ \dp\@outputbox
       \unvbox \@outputbox
       \vskip -\dimen@
       }%
   \fi
  \cb@trace@stack{after makecol, page \the\c@page,
                  \string\cb@pagecount=\the\cb@pagecount}%
  }
\let\@makecol\cb@makecol
%    \end{macrocode}
%   When \LaTeX\ makes a page with only floats it doesn't use
%   |\@makecol|; instead it calls |\@vtryfc|, so we have to modify
%   this macro as well.
% \changes{v3.3a}{1997/09/26}{Let \cs{cb@writeAux} be \cs{@gobble} to
%    prevent extra entries in the \file{.aux} file}
% \changes{v3.3a}{1997/09/26}{Now use the command
%    \cs{cb@startSpanBars} to define top points for bars spoanning a
%    page break} 
% \changes{v3.5a}{2005/05/23}{We don't want spanning changebars from a
%    previous page in a float column.
%    The original code didn't work anyway. It did set \@outputbox,
%    which is immediately discarded in \cs{@ltx@vtryfc}.}
%    In twocolumn mode we must write either \cs{@cb@firstcolumntrue} or
%    \cs{@cb@firstcolumnfalse} to the \file{.aux} file.
%    \begin{macrocode}
\let\ltx@vtryfc\@vtryfc
\def\cb@vtryfc#1{%
  \cb@trace{In vtryfc, page \the\c@page,
                  \string\cb@pagecount=\the\cb@pagecount}%
  \let\cb@writeAux\@gobble
%    \end{macrocode}
%    First make sure that |\cb@pagecount| is correct.
%    Then generate a |\@cb@firstcolumntrue| or |\@cb@firstcolumnfalse| in
%    twocolumn mode.
%    \begin{macrocode}
  \cb@checkpagecount
  \ltx@vtryfc{#1}%
  \if@twocolumn
    \global\setbox\@outputbox \vbox to\@colht{%
      \if@firstcolumn\write\@auxout{\string\@cb@firstcolumntrue}%
      \else\write\@auxout{\string\@cb@firstcolumnfalse}%
      \fi
      \unvbox\@outputbox
      \boxmaxdepth\maxdepth
    }%
  \fi
  \global\advance\cb@pagecount by \@ne
}
\let\@vtryfc\cb@vtryfc
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\cb@processActive}
%
%    This macro processes each element on span stack. Each element
%    represents a bar that crosses the page break. There could be more
%    than one if bars are nested. It works as follows:
%
% \begin{verbatim}
%    pop top element of span stack
%    if point null (i.e., stack empty) then done
%    else
%      do an end bar on box255
%      save start for new bar at top of next page in \cb@startSaves
%      push active point back onto history stack (need to reprocess
%         on next page).
% \end{verbatim}
%
%    \begin{macrocode}
\def\cb@processActive{%
  \cb@pop\cb@endstack
  \ifnum\cb@topleft=\cb@nil
  \else
    \setbox\@cclv\vbox{%
      \unvbox\@cclv
      \boxmaxdepth\maxdepth
      \advance\cb@pagecount by -1\relax
      \cb@setEndPoints}%
    \cb@push\cb@historystack
%    \end{macrocode}
%    
% \changes{v3.3a}{1997/09/26}{Now also push points on (new)
%    \cs{cb@beginstack}}
%    \begin{macrocode}
    \cb@push\cb@beginstack
    \expandafter\cb@processActive
  \fi}
%    \end{macrocode}
% \end{macro}
%
% \changes{v3.3a}{1997/09/26}{Removed \cs{cb@saveBeginPoints}}
%
%  \begin{macro}{\cb@startSpanBars}
% \changes{v3.3a}{1997/09/26}{New macro}
%    This macro defines new points for each bar that was pushed on the
%    |\cb@beginstack|. Afterwards |\cb@beginstack| is empty.
% \changes{v3.3g}{1999/06/11}{Added stack tracing; no longer push
%    points on \cs{cb@currenstack}}
%    \begin{macrocode}
\def\cb@startSpanBars{%
  \cb@pop\cb@beginstack
  \ifnum\cb@topleft=\cb@nil
  \else
    \cb@setBeginPoints
    \cb@trace@stack{after StartSpanBars, page \the\c@page}%
    \expandafter\cb@startSpanBars
  \fi
  }
%    \end{macrocode}
%  \end{macro}
%
% \begin{macro}{\cb@buildstack}
% \begin{macro}{\cb@endstack}
%
%    The macro |\cb@buildstack| initializes the stack with open bars
%    and starts populating it.
%    \begin{macrocode}
\def\cb@buildstack{%
  \cb@initstack\cb@endstack
  \cb@pushNextActive}
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\cb@pushNextActive}
%    This macro pops the top element off the history stack
%    (|\cb@historystack|).  If the top left point is on a future page,
%    it is pushed back onto the history stack and processing stops.
%    If the point on the current or a previous page and it has an odd
%    number, the point is pushed on the stack with end points
%    |\cb@endstack|); if the point has an even number, it is popped
%    off the stack with end points since the bar to which it belongs
%    has terminated on the current page.
%  \begin{changebar} % ^^A 3.7f
%    \changes{v3.7f}{2026/07/12}{Record consumed points for the fast
%    path in \cs{cb@checkpage}}
%    Each point that is consumed here is recorded by defining
%    |\cb@used@|\meta{point}, so that |\cb@checkpage| knows a search
%    for it can no longer succeed.
%  \end{changebar} % ^^A 3.7f
%    \begin{macrocode}
\def\cb@pushNextActive{%
  \cb@pop\cb@historystack
  \ifnum\cb@topleft=\cb@nil
  \else
    \ifnum\cb@page>\cb@pagecount
      \cb@push\cb@historystack
    \else
%    \end{macrocode}
%  \begin{changebar} % ^^A 3.7f
%    \begin{macrocode}
      \expandafter\gdef\csname cb@used@\the\cb@topleft\endcsname{}%
%    \end{macrocode}
%  \end{changebar} % ^^A 3.7f
%    \begin{macrocode}
      \ifodd\cb@topleft
        \cb@push\cb@endstack
      \else
        \cb@pop\cb@endstack
      \fi
      \expandafter\expandafter\expandafter\cb@pushNextActive
    \fi
  \fi}
%    \end{macrocode}
% \end{macro}
%
% \subsection{Macros For Managing The Stacks of Bar points}
%
%    The macros make use of four stacks corresponding to |\special|
%    defpoints.  Each stack takes the form \texttt{<element>
%    ... <element>}
%
%    Each element is of the form \texttt{xxxnyyypzzzl} where
%    \texttt{xxx} is the number of the special point, \texttt{yyy} is
%    the page on which this point is set, and \texttt{zzz} is the
%    dimension used when connecting this point.
%
%    The stack |\cb@historystack| is built from the log information
%    and initially lists all the points.  As pages are processed,
%    points are popped off the stack and discarded.
%
%    The stack |\cb@endstack| and |\cb@beginstack| are two temporary
%    stacks used by the output routine and contain the stack with
%    definitions for of all bars crossing the current pagebreak (there
%    may be more than one with nested bars). 
%    They are built by popping elements off the history stack.
%
%    The stack |\cb@currentstack| contains all the current bars.
%    A |\cb@start| pushes an element onto this stack.
%    A |\cb@end| pops the top element off the stack and uses the
%    info to terminate the bar.
%
%    For performance and memory reasons, the history stack, which can
%    be very long, is special cased and a file is used to store this
%    stack rather than an internal macro.  The ``external'' interface
%    to this stack is identical to what is described above.  However,
%    when the history stack is popped, a line from the file is first
%    read and appended to the macro |\cb@historystack|.
%
% \begin{macro}{\cb@initstack}
%    A macro to (globally) initialize a stack.
%    \begin{macrocode}
\def\cb@initstack#1{\xdef#1{}}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\cb@historystack}
% \begin{macro}{\cb@write}
% \begin{macro}{\cb@read}
%    We need to initialise a stack to store the entries read from the
%    external history file.
%    \begin{macrocode}
\cb@initstack\cb@historystack
%    \end{macrocode}
%    We also need to allocate a read and a write stream for the
%    history file.
%    \begin{macrocode}
\newwrite\cb@write
\newread\cb@read
%    \end{macrocode}
%    And we open the history file for writing (which is done when the
%    \file{.aux} file is read in).
%    \begin{macrocode}
\immediate\openout\cb@write=\jobname.cb\relax
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\cb@endstack}
% \begin{macro}{\cb@beginstack}
%    Allocate two stacks for the bars that span the current page break.
%    \begin{macrocode}
\cb@initstack\cb@endstack
\cb@initstack\cb@beginstack
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
%  \begin{macro}{\cb@tempstack}
%    Allocate a stack for temporary storage
%    \begin{macrocode}
\cb@initstack\cb@tempstack
%    \end{macrocode}
%  \end{macro}
%
% \begin{macro}{\cb@currentstack}
%    And we allocate an extra stack that is needed to implement nesting
%    without having to rely on \TeX's grouping mechanism.
%    \begin{macrocode}
\cb@initstack\cb@currentstack
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\cb@pop}
%
%    This macro pops the top element off the named stack and puts the
%    point value into |\cb@topleft|, the page value into |\cb@page|
%    and the bar width into |\cb@curbarwd|. If the stack is empty, it
%    returns a void value (|\cb@nil|) in |\cb@topleft| and sets
%    |\cb@page=0|.
%
% \changes{v3.4b}{2001/08/27}{Use global assignments, added more stack
%    tracing info}
%  \changes{v3.5a}{2005/05/23}{The check for history stack is improved.
%    Originally it succeeded if the stack contents was equal to the history
%    stack; now it specifically checks that we are popping the history
%    stack itself. Moreover we read from file only if the history
%    stack is empty.}
%    \begin{macrocode}
\def\cb@thehistorystack{\cb@historystack}
\def\cb@pop#1{%
  \ifx #1\@empty
    \def\cb@temp{#1}%
    \ifx\cb@temp\cb@thehistorystack
      \ifeof\cb@read
      \else
        {\endlinechar=-1\read\cb@read to\cb@temp
         \xdef\cb@historystack{\cb@historystack\cb@temp}%
        }%
      \fi
    \fi
  \fi
  \ifx#1\@empty
    \global\cb@topleft\cb@nil
    \global\cb@page\z@\relax
  \else
    \expandafter\cb@carcdr#1e#1%
  \fi
  \cb@trace@pop{#1}}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\cb@carcdr}
%    This macro is used to `decode' a stack entry.
% \changes{v3.3a}{1997/09/26}{No longer use \cs{@tempdima}}
% \changes{v3.4b}{2001/08/27}{Use global assignments}
%    \begin{macrocode}
\def\cb@carcdr#1n#2p#3l#4e#5{%
  \global\cb@topleft#1\relax
  \global\cb@page#2\relax
  \global\cb@curbarwd#3\relax
  \xdef#5{#4}}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\cb@push}
%
%    The macro |\cb@push| Pushes |\cb@topleft|, |\cb@page| and
%    |\cb@curbarwd| onto the top of the named stack.
%
% \changes{v3.4b}{2001/08/27}{Added more stack tracing info}
%    \begin{macrocode}
\def\cb@push#1{%
  \xdef#1{\the\cb@topleft n\the\cb@page p\the\cb@curbarwd l#1}%
  \cb@trace@push{#1}}

%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\cb@barpoint}
%    The macro |\cb@barpoint| populates the history file.  It writes
%    one line to \file{.cb} file which is equivalent to one
%    \meta{element} described above.
% \changes{v3.5a}{2005/05/23}{Changes for twocolumn support: if a bar point
%    is in the left column we have to subtract one from the pagecount.}
%  \begin{changebar} % ^^A 3.7f
%    \changes{v3.7f}{2026/07/12}{Record the points present in the
%    history file for the fast path in \cs{cb@checkpage}; detect
%    reused point numbers}
%    Each point that goes into the history file is recorded by
%    defining |\cb@bp@|\meta{point}, whose replacement text is the
%    (column-adjusted) pagecount recorded for the point -- exactly
%    what a successful history search would deliver, so
%    |\cb@checkpage| can skip the search altogether. When a point
%    number shows up for the second time the previous run reused
%    point numbers and the fast paths are disabled.
%  \end{changebar} % ^^A 3.7f
%    \begin{macrocode}
\def\cb@barpoint#1#2#3{%
%    \end{macrocode}
%  \begin{changebar} % ^^A 3.7f
%    \begin{macrocode}
  \cb@cnta=#2
  \if@cb@firstcolumn\advance\cb@cnta by\m@ne\fi
%    \end{macrocode}
%  \end{changebar} % ^^A 3.7f
%    \begin{macrocode}
  \ifcsname cb@bp@#1\endcsname
    \global\@cb@pointsuniquefalse
  \else
%    \end{macrocode}
%  \begin{changebar} % ^^A 3.7f
%    \begin{macrocode}
    \expandafter\xdef\csname cb@bp@#1\endcsname{\the\cb@cnta}%
%    \end{macrocode}
%  \end{changebar} % ^^A 3.7f
%    \begin{macrocode}
  \fi
  \immediate\write\cb@write{#1n\the\cb@cnta p#3l}}
%    \end{macrocode}
% \end{macro}
%
% \subsection{Macros For Checking That The \file{.aux} File Is Stable}
%
% \begin{macro}{\AtBeginDocument}
%
%    While reading the \file{.aux} file, \LaTeX{} has created the
%    history stack in a separate file. We need to close that file and
%    open it for reading. Also the `initialisation' of the
%    |\special| commands has to take place.  While we are
%    modifying the macro we also include the computation of the
%    possible positions of the changebars
%
%    For these actions we need to add to the \LaTeX\ begin-document
%    hook.
% \changes{3.2}{1994/04/21}{Use the \cs{AtBeginDocument} instead of
%    redefining \cs{document}}
%    \begin{macrocode}
\AtBeginDocument{%
  \cb@setup@specials
%    \end{macrocode}
% \changes{v3.5a}{2005/05/23}{Changes for better twocolumn support}
%    Add a sentinel to \cs{cb@pagejumplst}.
%    \begin{macrocode}
  \cb@pagejump{999999999,}%
%    \end{macrocode}
% \changes{v3.5a}{2005/05/23}{Adaption of \cs{cb@pagecount} is no longer
%    necessary, as \cs{cb@pagecount} will be adjusted at the beginning of
%    \cs{@makecol} and \cs{@vtryfc}.}
%    Compute the left and right positions of the changebars.
% \changes{v3.4g}{2004/01/09}{Added tracing information for the left
%    and right postions} 
% \changes{v3.6d}{2022-05-06}{Added \cs{relax} to end the filename}
%    \begin{macrocode}
  \cb@positions
  \cb@trace{%
    Odd left : \the\cb@odd@left\space
    Odd right : \the\cb@odd@right\MessageBreak
    Even left: \the\cb@even@left\space
    Even right: \the\cb@even@right
    }%
  \immediate\closeout\cb@write
  \immediate\openin\cb@read=\jobname.cb\relax}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\AtEndDocument}
%    We need to issue a |\clearpage| to flush rest of document.  (Note
%    that I believe there is contention in this area: are there in
%    fact situations in which the end-document hooks need to be called
%    \emph{before} the final |\clearpage|? --- the documentation of
%    \LaTeX\ itself implies that there are.)  Then closes the \file{.cb}
%    file and reopens it for checking.  Initialize history stack (to
%    be read from file).  Let |\cb@barpoint=\cb@checkHistory| for
%    checking. 
% \changes{3.2}{1994/04/21}{Use \cs{AtEndDocument} now instead of
%    redefining \cs{enddocument}}
% \changes{v3.6d}{2022-05-06}{Added \cs{relax} to end the filename}
%    \begin{macrocode}
\AtEndDocument{%
%    \end{macrocode}
% \changes{v3.7g}{2026/07/18}{Signal the end-of-document check to
%    \cs{cb@@findpdfpoint}}
%  \begin{changebar} % ^^A 3.7g
%    \begin{macrocode}
  \global\@cb@enddocumenttrue
%    \end{macrocode}
%  \end{changebar} % ^^A 3.7g
%    \begin{macrocode}
  \clearpage
  \cb@initstack\cb@historystack
  \immediate\closein\cb@read
  \immediate\openin\cb@read=\jobname.cb\relax
%    \end{macrocode}
%    
% \changes{v3.5a}{2005/05/23}{For pdftex we also close and reread the
%    \file{.cb2} file.}
%    Let |\cb@pdfxy=\cb@checkPdfxy| for checking. Make |\cb@pagejump| dummy.
%    \begin{macrocode}
  \ifx\cb@readxy\@undefined
  \else
    \immediate\closein\cb@readxy
    \immediate\openin\cb@readxy=\jobname.cb2\relax
    \def\cb@pdfpoints{}%
    \def\cb@pdfpagenr{0}%
  \fi
  \@cb@firstcolumnfalse
  \cb@checkrerun
  \let\cb@pdfxy\cb@checkPdfxy
  \let\cb@pagejump\@gobble
  \let\cb@barpoint\cb@checkHistory}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\cb@checkHistory}
%
%    Pops the top of the history stack (|\jobname.cb|) and checks to
%    see if the point and page numbers are the same as the arguments
%    $\#1$ and $\#2$ respectively.  Prints a warning message if
%    different.
% \changes{v3.5a}{2005/05/23}{Changes for twocolumn support: if a bar point
%    is in the left column we have to subtract one from the pagecount.}
%    \begin{macrocode}
\def\cb@checkHistory#1#2#3{%
  \cb@pop\cb@historystack
  \ifnum #1=\cb@topleft\relax
    \cb@cnta=#2
    \if@cb@firstcolumn\advance\cb@cnta by\m@ne\fi
    \ifnum \cb@cnta=\cb@page\relax
%    \end{macrocode}
%    Both page and point numbers are equal; do nothing,
%    \begin{macrocode}
    \else
%    \end{macrocode}
%    but generate a warning when page numbers don't match, or
%    \begin{macrocode}
      \cb@error
    \fi
  \else
%    \end{macrocode}
%    when point numbers don't match.
%    \begin{macrocode}
    \cb@error
  \fi}
%    \end{macrocode}
%    Dummy definition for |\cb@checkPdfxy|. This will be overwritten by
%    the \Lopt{pdftex} and \Lopt{xetex} options.
%    \begin{macrocode}
\def\cb@checkPdfxy#1#2#3#4#5{}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\cb@rerun}
% \changes{v3.5a}{2005/05/23}{Changes for better twocolumn support}
%    The macro |\cb@rerun| is called when we detect that we need to rerun
%    \LaTeX. 
%    \begin{macrocode}
\def\cb@rerun{%
  \global\let\cb@checkrerun\cb@error}
\let\cb@checkrerun\relax
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\cb@error}
%    When a mismatch between the changebar information in the
%    auxiliary file and the history stack is detected a warning is
%    issued; further checking is disabled.
% \changes{v3.5a}{2005/05/23}{Added pdftex support}
%    For pdf\TeX and Xe\TeX we also disable
%    |\cb@checkPdfxy|.
%    \begin{macrocode}
\def\cb@error{%
  \PackageWarning{Changebar}%
    {Changebar info has changed.\MessageBreak
     Rerun to get the bars right}
  \gdef\cb@checkHistory##1##2##3{}%
  \let\cb@barpoint\cb@checkHistory
  \gdef\cb@checkPdfxy##1##2##3##4##5{}%
  \let\cb@pdfxy\cb@checkPdfxy}
%    \end{macrocode}
% \end{macro}
%
% \subsection{Macros For Making It Work With Nested Floats/Footnotes}
%
% \begin{macro}{\end@float}
%    This is a replacement for the \LaTeX-macro of the same name.  All
%    it does is check to see if changebars are active and, if so, it
%    puts changebars around the box containing the float.  Then it
%    calls the original \LaTeX\ |\end@float|.
%
%    \begin{macrocode}
\let\ltx@end@float\end@float
%    \end{macrocode}
% \changes{v3.3g}{1999/06/11}{Added stack tracing}
% \changes{v3.4b}{2001/08/27}{Call \cs{@endfloatbox} en use
%    \cs{color@vbox} to take the extra box and group for color into
%    account}
%    \begin{macrocode}
\def\cb@end@float{%
  \cb@trace@stack{end float on page \the\c@page}%
  \cb@pop\cb@currentstack
  \ifnum\cb@topleft=\cb@nil
  \else
    \cb@push\cb@currentstack
    \global\cb@curbarwd=\cb@curbarwd
    \@endfloatbox
    \global\setbox\@currbox
      \color@vbox
      \normalcolor
      \vbox\bgroup\cb@start[\cb@curbarwd]\unvbox\@currbox\cb@end
  \fi
  \ltx@end@float}
\let\end@float\cb@end@float
%    \end{macrocode}
%    This only works if this new version of |\end@float| is really
%    used. With \LaTeX2.09 the documentstyles used to contain:
% \begin{verbatim}
%    \let\endfigure\end@float
% \end{verbatim}
%    In that case this binding has to be repeated after the
%    redefinition of |\end@float|. However, the \LaTeXe\ class files
%    use |\newenvironment| to define the \Lenv{figure} and
%    \Lenv{table} environments. In that case there is no need to
%    rebind |\endfigure|.
% \changes{3.2}{1994/04/21}{Removed
%    \cs{let}\cs{endfigure}\cs{end@float}, no longer necessary}
%
%  \begin{macro}{\@xympar}
%    There is one snag with this redefinition in that the macro
%    |\end@float| is also used by the command |\marginpar|. This may
%    lead to problems with stack underflow. Therefore we need to
%    redefine an internal macro from the marginal paragraph mechanism
%    as well. The solution is to make sure the this macro uses the
%    original definition of |\end@float|.
% \changes{v3.5d}{2005/12/24}{Redefine \cs{@xympar} to use the
%    original version of \cs{end@float}}
%    \begin{macrocode}
\let\ltx@@xympar\@xympar
\def\@xympar{%
  \let\end@float\ltx@end@float
  \ltx@@xympar
  \let\end@float\cb@end@float}
%    \end{macrocode}
%  \end{macro}
%
% \end{macro}
%
%  \begin{macro}{\float@end}
%    When the \pkg{float} package is being used we need to take care
%    of its changes to the float mechanism. It defines it's own macros
%    (|\float@end| and |\float@dblend| which need to be modified for
%    changebars to work.
%
%    First we'll save the original as |\flt@float@end|.
%    \begin{macrocode}
\let\flt@float@end\float@end
%    \end{macrocode}
%    Then we redefine it to insert the changebarcode.
%    \begin{macrocode}
\def\float@end{%
  \cb@trace@stack{end float on page \the\c@page}%
  \cb@pop\cb@currentstack
  \ifnum\cb@topleft=\cb@nil
  \else
    \cb@push\cb@currentstack
    \global\cb@curbarwd\cb@curbarwd
    \@endfloatbox
    \global\setbox\@currbox
      \color@vbox
      \normalcolor
      \vbox\bgroup\cb@start[\cb@curbarwd]\unvbox\@currbox\cb@end
  \fi
  \let\end@float\ltx@end@float
  \flt@float@end
  }
%    \end{macrocode}
%  \end{macro}
%
% \begin{macro}{\end@dblfloat}
%    This is a replacement for the \LaTeX-macro of the same name.  All
%    it does is check to see if changebars are active and, if so, it
%    puts changebars around the box containing the float. In this case
%    the \LaTeX\ macro had to be rewritten.
%
% \changes{v3.4e}{2001/09/07}{Double column floats only carry a
%    changebar with an appropriate change of \cs{end@dblfloat}}
%    \begin{macrocode}
\let\ltx@end@dblfloat\end@dblfloat
\def\cb@end@dblfloat{%
  \if@twocolumn
    \cb@trace@stack{end dblfloat on page \the\c@page}%
    \cb@pop\cb@currentstack
    \ifnum\cb@topleft=\cb@nil
    \else
      \cb@push\cb@currentstack
      \global\cb@curbarwd=\cb@curbarwd
      \@endfloatbox
      \global\setbox\@currbox
        \color@vbox
        \normalcolor
        \vbox\bgroup\cb@start[\cb@curbarwd]\unvbox\@currbox\cb@end
    \fi
    \@endfloatbox
    \ifnum\@floatpenalty <\z@
      \@largefloatcheck
      \@cons\@dbldeferlist\@currbox
    \fi
    \ifnum \@floatpenalty =-\@Mii \@Esphack\fi
  \else
    \end@float
  \fi}
\let\end@dblfloat\cb@end@dblfloat
%    \end{macrocode}
% \end{macro}
%
%  \begin{macro}{\float@dblend}
%    Something similar needs to be done for the case where the
%    \pkg{float} package is being used...
%    \begin{macrocode}
\let\flt@float@dblend\float@dblend
\def\float@dblend{%
  \cb@trace@stack{end dbl float on page \the\c@page}%
  \cb@pop\cb@currentstack
  \ifnum\cb@topleft=\cb@nil
  \else
    \cb@push\cb@currentstack
    \global\cb@curbarwd=\cb@curbarwd
    \@endfloatbox
    \global\setbox\@currbox
      \color@vbox
      \normalcolor
      \vbox\bgroup\cb@start[\cb@curbarwd]\unvbox\@currbox\cb@end
  \fi
  \let\end@dblfloat\ltx@end@dblfloat
  \flt@float@dblend
  }
%    \end{macrocode}
%  \end{macro}
%
% \begin{macro}{\@footnotetext}
%    This is a replacement for the \LaTeX\ macro of the same name.
%    It simply checks to see if changebars are active, and if so,
%    wraps the macro argument (i.e., the footnote) in changebars.
%
% \changes{3.1b}{1993/10/11}{Added missing percent sign to prevent
%    spurious white space in the output.}
%    \begin{macrocode}
\let\ltx@footnotetext\@footnotetext
%    \end{macrocode}
% \changes{v3.3g}{1999/06/11}{Added stack tracing}
%    \begin{macrocode}
\long\def\cb@footnotetext#1{%
  \cb@trace@stack{end footnote on page \the\c@page}%
  \cb@pop\cb@currentstack
  \ifnum\cb@topleft=\cb@nil
    \ltx@footnotetext{#1}%
  \else
    \cb@push\cb@currentstack
    \edef\cb@temp{\the\cb@curbarwd}%
    \ltx@footnotetext{\cb@start[\cb@temp]#1\cb@end}%
  \fi}
\let\@footnotetext\cb@footnotetext
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@mpfootnotetext}
%
%    Replacement for the \LaTeX\ macro of the same name.  Same thing
%    as |\@footnotetext|.
%
% \changes{3.1b}{1993/10/11}{Added missing percent sign to prevent
%    spurious white space in the output.}
%    \begin{macrocode}
\let\ltx@mpfootnotetext\@mpfootnotetext
%    \end{macrocode}
%    \begin{macrocode}
\long\def\cb@mpfootnotetext#1{%
  \cb@pop\cb@currentstack
  \ifnum\cb@topleft=\cb@nil
    \ltx@mpfootnotetext{#1}%
  \else
    \cb@push\cb@currentstack
    \edef\cb@temp{\the\cb@curbarwd}%
    \ltx@mpfootnotetext{\cb@start[\cb@temp]#1\cb@end}%
  \fi}
\let\@mpfootnotetext\cb@mpfootnotetext
%</package>
%    \end{macrocode}
% \end{macro}
%
% 
% \Finale
%
\endinput
%% \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         \~}
%%
%%
