% \iffalse meta-comment
%
% Copyright (C) 2010 by Jason Gross (JasonGross9+locality@gmail.com)
%
% This file may be distributed and/or modified under the
% conditions of the LaTeX Project Public License, either
% version 1.3c 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.3c or later is part of all distributions of
% LaTeX version 2005/12/01 or later.
%
% \fi
%
%
% \iffalse
%<package>\NeedsTeXFormat{LaTeX2e}[1999/12/01]
%<package>\ProvidesPackage{locality}
%<package> [2010/11/11 v0.2 Various macros for keeping things local]
%<package>\RequirePackage{etoolbox}[2009/08/06]
%
%<*driver>
\documentclass{ltxdoc}
\usepackage{locality}
\EnableCrossrefs
\CodelineIndex
\RecordChanges
\begin{document}
  \DocInput{locality.dtx}
\end{document}
%</driver>
% \fi
%
% \CheckSum{573}
%
% \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         \~}
%
% \changes{v0.1}{2010/06/15}{Initial version.  Please note that some macros
%                            have not yet been tested.}
% \changes{v0.2}{2010/11/11}{Switched the order of tests in \string
%           \manyaftergroup, eliminating an infinite loop.  Added \string
%           \DeclareNonlocal*s\space, \string\pushvalues, \string\popvalues,
%           \string\pushvalue, \string\popvalue, and a few others. Fixed 
%           \string\DeclareNonlocal*\space to work with \string\aftergroup.
%           Added requirement for etoolbox, so that patching takes place at
%           the end of the preamble.}
%
% \GetFileInfo{locality.sty}
%
% \DoNotIndex{\#,\$,\%,\&,\@,\\,\{,\},\^,\_,\~,\ }
% \DoNotIndex{}
%
% \title{The \textsf{locality} package\thanks{This document
%   corresponds to \textsf{locality}~\fileversion,
%   dated~\filedate.}}
% \author{Jason Gross \\ \texttt{JasonGross9+locality@gmail.com}}
%
% \maketitle
%
% \section{Introduction}
% 
% The \textsf{locality} package provides various macros to keep changes local
% to the current group.  This allows one to (re)define helper macros
% without worrying about accidentally changing the functionality of another
% package's or the user's definitions.  Additionally, it allows recursive
% macros to have some definitions persist between calls, and others be local.
%
% \section{Usage}
% I give the usage and specification of every macro defined.  I give bugs when
% I know them (please email me if you find other bugs, or have fixes for the
% bugs I list).  I sometimes give extra description or justification.
%
% \DescribeMacro{\manyaftergroup}
% \noindent Usage: |\manyaftergroup|\marg{tokens} \par\noindent
% Specification: The \meta{tokens} get placed after the current group \par\noindent
% Bugs: No braces are permitted, spaces are stripped
%
% I've often wanted to use \TeX's |\aftergroup| with a variable-length
% argument. This macro allows this.  It is expandable (may be used in
% |\edef|), but it gobbles spaces.
%
% ToDo: Write a version of this macro that preserves spaces, allows braces.
%
% \DescribeMacro{\locallydefine}
% \noindent Usage: |\locallydefine|\marg{macro}\marg{processing} \par\noindent
% Specification: Execute \meta{processing} inside of a group, and make
% the definition of |\macro| persist after the group ends. \par\noindent
% Bugs: Changes via |\let| to an unexpandable macro yield an infinite recursive
% loop.
%
% Normally, when you define a macro in a group, it's definition reverts after
% the group ends, unless you use |\global|.  If you use |\global|, then the
% new definition replaces the current definition on all levels.  This macro
% provides something in between.
%
% \DescribeMacro{\DeclareNonlocalMacro}
% \noindent Usage: |\DeclareNonlocalMacro|\marg{macro} \par\noindent
% Specification: Any changes to the definition of |\macro| persist
% after the end of the current group. \par\noindent
% Bugs: Changes via |\let| to an unexpandable macro yield an infinite recursive
% loop.  Only works with |\begingroup| |\endgroup| (not with braces).
%
% This macro generalized |\locallydefine|.
%
%
% \DescribeMacro{\DeclareNonlocalMacros}
% \noindent Usage: |\DeclareNonlocalMacros|\marg{macro list} \par\noindent
% \noindent Example: |\DeclareNonlocalMacros{\macroi,\macroii}| \par\noindent
% Specification: \marg{macro list} Should be a comma-separated list of macros.
% This command will run |\DeclareNonlocalMacro| on each argument.
%
%
% \DescribeMacro{\DeclareNonlocalTheRegister}\DescribeMacro{\DeclareNonlocalCount}
% \DescribeMacro{\DeclareNonlocalDimen}\DescribeMacro{\DeclareNonlocalSkip}
% \DescribeMacro{\DeclareNonlocalMuskip}\DescribeMacro{\DeclareNonlocalToks}
% \noindent Usage: |\DeclareNonlocalCount|\marg{count} \par\noindent
% \phantom{Usage:} |\DeclareNonlocalDimen|\marg{dimen} \par\noindent
% \phantom{Usage:} |\DeclareNonlocalSkip|\marg{skip} \par\noindent
% \phantom{Usage:} |\DeclareNonlocalMuskip|\marg{muskip} \par\noindent
% \phantom{Usage:} |\DeclareNonlocalToks|\marg{toks} \par\noindent
% Specification: Any changes to the value in \meta{register} persist
% after the end of the current group. \par\noindent
%
% Registers for \meta{count}s, \meta{dimen}s, \meta{skip}s, and \meta{muskips}s
% can all be made nonlocal with |\DeclareNonlocalTheRegister|.
%
% Bugs: Only works with |\begingroup| |\endgroup| (not with braces).  Only
%  works if the argument is a single token.
%
% These do the same thing to registers (\meta{count}s, \meta{length}s, and 
% \meta{tok}s) that |\DeclareNonlocalMacro| does to macros.
%
%
% \DescribeMacro{\DeclareNonlocalTheRegister}\DescribeMacro{\DeclareNonlocalCount}
% \DescribeMacro{\DeclareNonlocalDimen}\DescribeMacro{\DeclareNonlocalSkip}
% \DescribeMacro{\DeclareNonlocalMuskip}\DescribeMacro{\DeclareNonlocalToks}
% \noindent Usage: |\DeclareNonlocalCounts|\marg{list of counts (comma separated)} \par\noindent
% \phantom{Usage:} |\DeclareNonlocalDimens|\marg{list of dimens (comma separated)} \par\noindent
% \phantom{Usage:} |\DeclareNonlocalSkips|\marg{list of skips (comma separated)} \par\noindent
% \phantom{Usage:} |\DeclareNonlocalMuskips|\marg{list of muskips} \par\noindent
% \phantom{Usage:} |\DeclareNonlocalTokses|\marg{list of toks (comma separated)} \par\noindent
% Specification: Any changes to the value in \meta{register}s persist
% after the end of the current group. \par\noindent
%
% \DescribeMacro{\pushvalue}\DescribeMacro{\popvalue}\noindent 
% Usage: |\pushvalue|\marg{macro} \par\noindent
% \phantom{Usage:} |\popvalue|\marg{macro} \par
% \noindent Specification: The argument \marg{macro} is backed up by
%  |\pushvalue|, and the most recently backed up value is restored by
%  |\popvalue|.  The macro definitions are saved using a stack.
%
%
% \DescribeMacro{\savevalues}\DescribeMacro{\restorevalues}
% \noindent Usage: |\savevalues|\marg{list of macros (no separator)} \par\noindent
% \phantom{Usage:} |\restorevalues|\marg{list of macros (no separator)} \par\noindent
% Specification: Every token in the passed argument is backed up by
%  |\savevalues|, and the most recently backed up values are restored by
%  |\restorevalues|.
%
%
% \DescribeMacro{\pushvalues}\DescribeMacro{\popvalues}\noindent 
% Usage: |\pushvalues|\marg{list of macros (comma separated)} \par\noindent
% \phantom{Usage:} |\popvalues|\marg{list of macros (comma separated)} \par
%  \noindent Specification: Every macro in the passed argument is backed up by
%  |\pushvalues|, and the most recently backed up values are restored by
%  |\popvalues|.  The macro definitions are saved using a stack.
%
%
% \DescribeMacro{\makecommandslocal}
% \noindent Usage: |\makecommandslocal|\marg{list of macros (no separator)}\marg{code} \par\noindent
% Specification: Every token in the first argument is made local to \meta{code};
%  changes made to their definitions do not perist outside of \meta{code}.
%
% This macro is the natural opposite of |\DeclareNonlocalMacro|; it allows 
% some macros to behave as if \meta{code} was inside a group, while the rest
% of the macros behave as if they were not.
%
%
% \DescribeMacro{\ignoreglobal}\DescribeMacro{\obeyglobal}\DescribeMacro{\unignoreglobal}
% \noindent Usage: |\ignoreglobal| \par\noindent
% \noindent Usage: |\unignoreglobal| \par\noindent
% \noindent Usage: |\obeyglobal| \par\noindent
% Specification: The macro |\ignoreglobal| causes global changes, such as
% |\edef|, |\xdef|, and those prefaced by |\global|, to be local.  The macro 
% |\obeyglobal| causes these to be treated as global.  The macro 
% |\unignoreglobal| undoes the changes made by the last |\ignoreglobal|.  If
% you call |\ignoreglobal| twice, then you must call |\unignoreglobal| twice to
% allow global changes.
%
% \DescribeMacro{\makecounterslocal}
% \noindent Usage: |\makecounterslocal| \par\noindent
% Specification: The macro |\makecounterslocal| redefines the \LaTeX{} 
% \meta{counter} macros so that their changes are local, instead of global.
% At the end of the group in which |\makecounterslocal| is called, 
% \meta{counter} macros revert to being global.
%
% \StopEventually{\PrintChanges\PrintIndex}
%
% \section{Implementation}
% \subsection{Helper functions}
% The following definitions are preliminary, to allow various tricks with |\def|.
%    \begin{macrocode}
\def\@nil{\@nil\relax} % this way, I'll know if I've messed up; I'll get
% a stack overflow error.
\def\if@nil#1{\@if@nil#1\@@nil}
\def\@if@nil#1#2\@@nil{\ifx\@nil#1}
% We'll be messing with |\global|, so we better have a backup.
\let\locality@tex@global=\global
%    \end{macrocode}
%
% \begin{macro}{\locality@global@non@collision@unique@count}
% At various places, I want to have a macro associated with a certain name
% which hasn't been used before.  I use this count to number them.  I use
% a count, instead of a counter, so that I can control whether or not it's
% global.  The long name, with lots of |@|s, is to (hopefully) avoid 
% collisions.
%    \begin{macrocode}
\newcount\locality@global@non@collision@unique@count
\locality@global@non@collision@unique@count=0
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\manyaftergroup}
%
% The macro |\manyaftergroup| works by parsing it's argument one token at a
% time, and applying |\aftergroup| to each argument.  It checks for the end
% with |\@nil|.
%    \begin{macrocode}
\long\def\@manyaftergroup#1{\if@nil#1 \else \aftergroup#1 
\expandafter\@manyaftergroup\fi}
\newcommand{\manyaftergroup}[1]{\@manyaftergroup#1\@nil}
%    \end{macrocode}
% \end{macro}
%
%
% \begin{macro}{\locallydefine}
% Execute the second argument passed locally, and then preserve the definition
% of the first argument passed.
%    \begin{macrocode}
\newcommand{\locallydefine}[2]{{#2\expandafter}%
  \expandafter\def\expandafter#1\expandafter{#1}}
%    \end{macrocode}
%
% \end{macro}
%
% The |\DeclareNonlocal| macros do some fancy stuff with |\begingroup| and
% |\endgroup|, so the old definitions must be saved.
%    \begin{macrocode}
\let\locality@tex@begingroup=\begingroup
\let\locality@tex@endgroup=\endgroup
%    \end{macrocode}
% These macros are extended versions of the |\locallydefine| macro; they 
% redefine |\endgroup| to preserve definitions after the current group ends.
% 
% Because |\aftergroup| would occur before definition restoration, we patch
% |\aftergroup| so that it instead appends tokens to the end of |\endgroup|.
% This doesn't fix all use cases, but it should fix a problem with the calc
% package.
%    \begin{macrocode}
\newcount\locality@global@aftergroup@count
\locality@global@aftergroup@count=-1
\newcommand\locality@patch@aftergroup{%
  \def\aftergroup{%
    \locality@tex@global\advance\locality@global@aftergroup@count by 1
    \afterassignment\locality@aftergroup\locality@tex@global
    \expandafter\let\csname locality@nextchar\space\the
      \locality@global@aftergroup@count\endcsname=%
  }%
}
\newcommand\locality@aftergroup{%
  \expandafter\expandafter\expandafter\def
  \expandafter\expandafter\expandafter\endgroup
  \expandafter\expandafter\expandafter{\expandafter\endgroup
    \csname locality@nextchar\space\the\locality@global@aftergroup@count
    \endcsname}%
}
%    \end{macrocode}
%
%
% \begin{macro}{\DeclareNonlocalMacro}
% This macro redefines |\endgroup| to do this for macro passed to it.
%
% First, back up |\endgroup| to a new macro.
%    \begin{macrocode}
\newcommand{\DeclareNonlocalMacro}[1]{%
  \locality@patch@aftergroup % first, patch |\aftergroup|
  \expandafter\let
  \csname endgroup \the\locality@local@group@non@local@macro@count
    \endcsname=\endgroup
%    \end{macrocode}
% Redefine |\endgroup| to, in order: revert it's definition, insert code to 
% update the definition of the passed macro outside of the group, and call 
% the (reverted) version of |\endgroup|.
%    \begin{macrocode}
  \expandafter\def\expandafter\endgroup\expandafter{%
    \expandafter\expandafter\expandafter\let\expandafter
      \expandafter\expandafter\endgroup\expandafter\expandafter
      \csname endgroup \the\locality@local@group@non@local@macro@count
        \endcsname\expandafter\endgroup
    \expandafter\def\expandafter#1\expandafter{#1}}%
  \advance\locality@local@group@non@local@macro@count by 1
}%
%    \end{macrocode}
% \end{macro}
%
%    \begin{macrocode}
\newcommand\locality@declarenonlocals[2]{%
  \@for\locality@declarenonlocals@name:=#2\do{%
    \expandafter #1\expandafter{\locality@declarenonlocals@name}%
  }%
}
%    \end{macrocode}
%
% \begin{macro}{\DeclareNonlocalMacros}
%    \begin{macrocode}
\newcommand{\DeclareNonlocalMacros}[1]{\locality@declarenonlocals{\DeclareNonlocalMacro}{#1}}
%    \end{macrocode}
% \end{macro}
%
%
% \begin{macro}{\DeclareNonlocalTheRegister}
% \begin{macro}{\DeclareNonlocalCount}
% \begin{macro}{\DeclareNonlocalDimen}
% \begin{macro}{\DeclareNonlocalSkip}
% \begin{macro}{\DeclareNonlocalMuskip}
% This works the same way as as |\DeclareNonlocalMacro|, but uses |\the| instead of 
% |\def|.
%    \begin{macrocode}
\newcommand{\DeclareNonlocalTheRegister}[1]{%
  \locality@patch@aftergroup % first, patch |\aftergroup|
  \expandafter\let
  \csname endgroup \the\locality@local@group@non@local@macro@count
    \endcsname=\endgroup
  \expandafter\def\expandafter\endgroup\expandafter{%
    \expandafter\expandafter\expandafter\let
      \expandafter\expandafter\expandafter\endgroup
      \expandafter\expandafter
      \csname endgroup \the\locality@local@group@non@local@macro@count
        \endcsname\expandafter\endgroup
    \expandafter#1\expandafter=\the#1 }% Note the space.  This is to 
% prevent something like 
% |\newcount\tempc\begingroup \DeclareNonlocalCount\tempc \tempc=1\endgroup1|
% from setting |\tempc| to 11.
  \advance\locality@local@group@non@local@macro@count by 1
}%
\let\DeclareNonlocalCount=\DeclareNonlocalTheRegister
\let\DeclareNonlocalDimen=\DeclareNonlocalTheRegister
\let\DeclareNonlocalSkip=\DeclareNonlocalTheRegister
\let\DeclareNonlocalMuskip=\DeclareNonlocalTheRegister
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\DeclareNonlocalTheRegisters}
% \begin{macro}{\DeclareNonlocalCounts}
% \begin{macro}{\DeclareNonlocalDimens}
% \begin{macro}{\DeclareNonlocalSkips}
% \begin{macro}{\DeclareNonlocalMuskips}
%    \begin{macrocode}
\newcommand{\DeclareNonlocalTheRegisters}[1]{\locality@declarenonlocals{\DeclareNonlocalTheRegister}{#1}}
\let\DeclareNonlocalCounts=\DeclareNonlocalTheRegisters
\let\DeclareNonlocalDimens=\DeclareNonlocalTheRegisters
\let\DeclareNonlocalSkips=\DeclareNonlocalTheRegisters
\let\DeclareNonlocalMuskips=\DeclareNonlocalTheRegisters
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\DeclareNonlocalToks}
% This works the same way as as |\DeclareNonlocalCount|, but puts braces around
% the assigned value; |\toks0=1| fails, and should be |\toks0={1}|.
%    \begin{macrocode}
\newcommand{\DeclareNonlocalToks}[1]{%
  \locality@patch@aftergroup % first, patch |\aftergroup|
  \expandafter\let
  \csname endgroup \the\locality@local@group@non@local@macro@count
    \endcsname=\endgroup
  \expandafter\def\expandafter\endgroup\expandafter{%
    \expandafter\expandafter\expandafter\let\expandafter\expandafter
      \expandafter\endgroup\expandafter\expandafter
      \csname endgroup \the\locality@local@group@non@local@macro@count'
      \endcsname\expandafter\endgroup
    \expandafter#1\expandafter=\expandafter{\the#1}}%
  \advance\locality@local@group@non@local@macro@count by 1
}%
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\DeclareNonlocalTokses}
%    \begin{macrocode}
\newcommand{\DeclareNonlocalTokses}[1]{\locality@declarenonlocals{\DeclareNonlocalToks}{#1}}
%    \end{macrocode}
% \end{macro}
%
% I redefine |\begingroup| to reset the locality macros, so nesting works.
%    \begin{macrocode}
\newcount\locality@local@group@non@local@macro@count % Hopefully, this
% won't collide with anything.  I hope putting this out here allows
% proper nesting of groups
\def\begingroup{\locality@tex@begingroup
  \def\endgroup{\locality@tex@endgroup}% not \let, because
                     % that would break my |\aftergroup| patch
  \locality@local@group@non@local@macro@count=0
}
%    \end{macrocode}
%
%
%
% \begin{macro}{\savevalues}
% \begin{macro}{\restorevalues}
% These macros parse their arguments token by token, renaming each |macro| to 
% |@\macro backup|, or vice versa.
%    \begin{macrocode}
\def\@savevalues#1{\ifx#1\@nil \else \expandafter\let
  \csname @\string#1\space backup\endcsname=#1
  \expandafter\@savevalues\fi}
\newcommand{\savevalues}[1]{\@savevalues#1\@nil}

\def\@restorevalues#1{%
\ifx
  #1\@nil
\else
  \expandafter\let\expandafter#1\expandafter
    =\csname @\string#1\space backup\endcsname
    \expandafter
  \let\csname @\string#1\space backup\endcsname
    =\relax
  \expandafter\@restorevalues
\fi
}
\newcommand{\restorevalues}[1]{\@restorevalues#1\@nil}
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
%
% \begin{macro}{\pushvalues}
% \begin{macro}{\popvalues}
% \begin{macro}{\pushvalue}
% \begin{macro}{\popvalue}
%    \begin{macrocode}
\newcommand{\pushvalue}[1]{%
  \@ifundefined{locality\space backup\space \string#1}{}{%
    \expandafter\pushvalue\csname locality\space backup\space \string#1\endcsname%
  }%
  \expandafter\let\csname locality\space backup\space \string#1\endcsname=#1%
}
\newcommand{\pushvalues}[1]{%
  \@for\locality@pushvalues@macroname:=#1\do{%
    \expandafter\pushvalue\locality@pushvalues@macroname
  }%
}
\newcommand{\popvalue}[1]{%
  \@ifundefined{locality\space backup\space \string#1}{%
    \let#1=\relax
  }{%
    \expandafter\let\expandafter#1\expandafter=\csname locality\space backup\space \string#1\endcsname
    \expandafter\popvalue\csname locality\space backup\space \string#1\endcsname%
  }%
}
\newcommand{\popvalues}[1]{%
  \@for\locality@popvalues@macroname:=#1\do{%
    \expandafter\popvalue\locality@popvalues@macroname
  }%
}
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\makecommandslocal}
% Save the macros, run the code, then restore the values.
%    \begin{macrocode}
\newcommand{\makecommandslocal}[2]{\savevalues{#1}#2\restorevalues{#1}}
%    \end{macrocode}
% \end{macro}
%
%
% \begin{macro}{\makecounterslocal}
% To make counters local without redefining them too badly (for example, this
% should work with the |calc| package, as long as you load |calc| first),
% we disable |\global|, and set |\gdef| and |\xdef| to |\def| and |\edef|
% respectively.
%
% \begin{macro}{\ignoreglobal}
% \begin{macro}{\obeyglobal}
% \begin{macro}{\unignoreglobal}
% We save the values of |\global|, |\gdef|, |\xdef|, globally, so
% that multiple calls don't fail.
%
% We also save the value of |\@cons|, a special macro used in counters, which
% uses |\xdef| to append something to a list.  Since it must be redefined for 
% counters, I'll redefine it here to do without |\xdef| fails.
%
% For reference, the original definition of |\@cons|, from |latex.ltx|, is \\
% |\def\@cons#1#2{\begingroup\let\@elt\relax\xdef#1{#1\@elt #2}\endgroup}|.
% I try to make this forward-compatible, but if the definition of |\@cons|
% changes too badly, this'll break.
%    \begin{macrocode}
\savevalues{\global\gdef\xdef\@cons}
{\def\begingroup{\begingroup\DeclareNonlocalMacro{##1}}%
  \expandafter\expandafter\expandafter
}%
\expandafter\expandafter\expandafter\def
\expandafter\expandafter\expandafter\locality@cons
\expandafter\expandafter\expandafter#%
\expandafter\expandafter\expandafter1%
\expandafter\expandafter\expandafter#%
\expandafter\expandafter\expandafter2%
\expandafter\expandafter\expandafter{\@cons{#1}{#2}}%
\newcommand{\obeyglobal}{\restorevalues{\global\gdef\xdef\@cons}}
\newcommand{\unignoreglobal}{\popvalues{\global,\gdef,\xdef,\@cons}}
\newcommand{\ignoreglobal}{%
  \pushvalues{\global,\gdef,\xdef,\@cons}%
  \let\global=\relax \let\gdef=\def \let\xdef=\edef
  \let\@cons=\locality@cons
  \expandafter\def\expandafter\unignoreglobal\expandafter{\expandafter
  \def\expandafter\unignoreglobal\expandafter{\unignoreglobal}%
  \unignoreglobal}%
}
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% 
% Now, the actual macro.
%
% We redefine |\stepcounter|, |\addtocounter|, |\refstepcounter|, 
% |\setcounter|, |\@addtoreset|, and |\@definecounter|.
%
% Since |\newcounter| does everything with |\@addtoreset| and
% |\@definecounter|, it doesn't need and changes.
%    \begin{macrocode}
\newcommand{\makecounterslocal}{% FIX, to make more robust
  \expandafter\def\expandafter\stepcounter
    \expandafter##\expandafter1\expandafter{%
    \expandafter\ignoreglobal\stepcounter{##1}%
    \unignoreglobal
  }%
 %
  \expandafter\def\expandafter\refstepcounter
    \expandafter##\expandafter1\expandafter{%
    \expandafter\ignoreglobal\refstepcounter{##1}%
    \unignoreglobal
  }%
 %
  \expandafter\def\expandafter\setcounter
    \expandafter##\expandafter1%
    \expandafter##\expandafter2\expandafter{%
    \expandafter\ignoreglobal\setcounter{##1}{##2}%
    \unignoreglobal
  }%
 %
  \expandafter\def\expandafter\addtocounter
    \expandafter##\expandafter1%
    \expandafter##\expandafter2\expandafter{%
    \expandafter\ignoreglobal\addtocounter{##1}{##2}%
    \unignoreglobal
  }%
 %
  \expandafter\def\expandafter\@addtoreset
    \expandafter##\expandafter1%
    \expandafter##\expandafter2\expandafter{%
    \expandafter\ignoreglobal\@addtoreset{##1}{##2}%
    \unignoreglobal
  }%
 %
  \expandafter\def\expandafter\@definecounter
    \expandafter##\expandafter1\expandafter{%
    \expandafter\ignoreglobal\@definecounter{##1}%
    \unignoreglobal
  }%
  \locality@fix@for@amstext
  \locality@fix@for@calc
}
%    \end{macrocode}
%
% Following the example of the |calc| package, if the amstext package is loaded
% we must add the |\iffirstchoice@| switch as well. We patch the commands this 
% way since it's good practice when we know how many arguments they take.
%
% We use |\AtEndPreamble| to ensure that we catch the other package loads.
%    \begin{macrocode}
\AtEndPreamble{
  \@ifpackageloaded{amstext}{
    \newcommand{\locality@fix@for@amstext}{
      \expandafter\def\expandafter\stepcounter
        \expandafter##\expandafter1\expandafter{%
        \expandafter\iffirstchoice@\stepcounter{##1}\fi
      }
      \expandafter\def\expandafter\addtocounter
        \expandafter##\expandafter1%
        \expandafter##\expandafter2\expandafter{%
        \expandafter\iffirstchoice@\addtocounter{##1}{##2}\fi
      }
    }
  }{
    \let\locality@fix@for@amstext=\relax
  }
  \@ifpackageloaded{calc}{%
    \def\locality@fix@for@calc{\expandafter\def\expandafter\begingroup\expandafter{\begingroup\DeclareNonlocalTheRegister{\calc@A}}}
  }{
    \let\locality@fix@for@calc=\relax
  }
}
%    \end{macrocode}
% \end{macro}
%
%
% \Finale
\endinput