summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/source/latex/oberdiek/alphalph.dtx
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2007-09-16 00:07:34 +0000
committerKarl Berry <karl@freefriends.org>2007-09-16 00:07:34 +0000
commitd85f248e3b38ea0ecda38c5340e3cadd08d65346 (patch)
tree52e17f32b395006895b3917bc7729c7ac1514ae3 /Master/texmf-dist/source/latex/oberdiek/alphalph.dtx
parent2389552f283181e0d8c610037712ade989112da3 (diff)
oberdiek update (14sep07)
git-svn-id: svn://tug.org/texlive/trunk@4947 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/source/latex/oberdiek/alphalph.dtx')
-rw-r--r--Master/texmf-dist/source/latex/oberdiek/alphalph.dtx1602
1 files changed, 1169 insertions, 433 deletions
diff --git a/Master/texmf-dist/source/latex/oberdiek/alphalph.dtx b/Master/texmf-dist/source/latex/oberdiek/alphalph.dtx
index 7fba92f4829..3a3d117ec0b 100644
--- a/Master/texmf-dist/source/latex/oberdiek/alphalph.dtx
+++ b/Master/texmf-dist/source/latex/oberdiek/alphalph.dtx
@@ -17,7 +17,8 @@
%
% This work consists of the main source file alphalph.dtx
% and the derived files
-% alphalph.sty, alphalph.pdf, alphalph.ins, alphalph.drv.
+% alphalph.sty, alphalph.pdf, alphalph.ins, alphalph.drv,
+% alphalph-test1.tex, alphalph-test2.tex, alphalph-test3.tex.
%
% Distribution:
% CTAN:macros/latex/contrib/oberdiek/alphalph.dtx
@@ -52,6 +53,9 @@
% Installation:
% TDS:tex/generic/oberdiek/alphalph.sty
% TDS:doc/latex/oberdiek/alphalph.pdf
+% TDS:doc/latex/oberdiek/alphalph-test1.tex
+% TDS:doc/latex/oberdiek/alphalph-test2.tex
+% TDS:doc/latex/oberdiek/alphalph-test3.tex
% TDS:source/latex/oberdiek/alphalph.dtx
%
%<*ignore>
@@ -67,7 +71,7 @@
\input docstrip.tex
\Msg{************************************************************************}
\Msg{* Installation}
-\Msg{* Package: alphalph 2007/04/11 v1.5 Converting numbers to letters (HO)}
+\Msg{* Package: alphalph 2007/04/11 v2.0 Converting numbers to letters (HO)}
\Msg{************************************************************************}
\keepsilent
@@ -94,7 +98,8 @@ This Current Maintainer of this work is Heiko Oberdiek.
This work consists of the main source file alphalph.dtx
and the derived files
- alphalph.sty, alphalph.pdf, alphalph.ins, alphalph.drv.
+ alphalph.sty, alphalph.pdf, alphalph.ins, alphalph.drv,
+ alphalph-test1.tex, alphalph-test2.tex, alphalph-test3.tex.
\endpreamble
@@ -103,6 +108,10 @@ and the derived files
\file{alphalph.drv}{\from{alphalph.dtx}{driver}}%
\usedir{tex/generic/oberdiek}%
\file{alphalph.sty}{\from{alphalph.dtx}{package}}%
+ \usedir{doc/latex/oberdiek}%
+ \file{alphalph-test1.tex}{\from{alphalph.dtx}{test1}}%
+ \file{alphalph-test2.tex}{\from{alphalph.dtx}{test2,etex}}%
+ \file{alphalph-test3.tex}{\from{alphalph.dtx}{test2,noetex}}%
}
\obeyspaces
@@ -128,17 +137,42 @@ and the derived files
%<*driver>
\NeedsTeXFormat{LaTeX2e}
\ProvidesFile{alphalph.drv}%
- [2007/04/11 v1.5 Converting numbers to letters (HO)]%
+ [2007/04/11 v2.0 Converting numbers to letters (HO)]%
\documentclass{ltxdoc}
\usepackage{holtxdoc}
-\usepackage{alphalph}
+\usepackage{alphalph}[2007/04/11]
+\makeatletter
+\newalphalph{\fnsymbolwrap}[wrap]{\@fnsymbol}{}
+\newcommand*{\fnsymbolsingle}[1]{%
+ \ensuremath{%
+ \ifcase#1%
+ \or *%
+ \or \dagger
+ \or \ddagger
+ \or \mathsection
+ \or \mathparagraph
+ \else
+ \@ctrerr
+ \fi
+ }%
+}
+\makeatother
+\newalphalph{\fnsymbolmult}[mult]{\fnsymbolsingle}{}
+\usepackage{amsmath}
+\DeclareMathOperator{\opDiv}{div}
+\DeclareMathOperator{\opMod}{mod}
+\newcommand*{\Def}{%
+ \ensuremath{%
+ \mathrel{\mathop{:}}=%
+ }%
+}
\begin{document}
\DocInput{alphalph.dtx}%
\end{document}
%</driver>
% \fi
%
-% \CheckSum{406}
+% \CheckSum{1035}
%
% \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
@@ -159,100 +193,352 @@ and the derived files
% \GetFileInfo{alphalph.drv}
%
% \title{The \xpackage{alphalph} package}
-% \date{2007/04/11 v1.5}
+% \date{2007/04/11 v2.0}
% \author{Heiko Oberdiek\\\xemail{oberdiek@uni-freiburg.de}}
%
% \maketitle
%
% \begin{abstract}
-% The package provides the new expandable commands \cs{alphalph}
-% and \cs{AlphAlph}. They are like \cs{number}, but the expansion
-% consists of lowercase and uppercase letters respectively.
+% The package provides methods to represent numbers with a limited
+% set of symbols. Both \LaTeX\ and \plainTeX are supported.
% \end{abstract}
%
% \tableofcontents
%
-% \newenvironment{param}{^^A
-% \newcommand{\entry}[1]{\meta{\###1}:&}^^A
-% \begin{tabular}[t]{@{}l@{ }l@{}}^^A
-% }{^^A
-% \end{tabular}^^A
-% }
+% \section{Documentation}
%
-% \section{Usage}
-% The package \Package{alphalph} can be used with both \plainTeX\
-% and \LaTeX:
-% \begin{description}
-% \item[\plainTeX:] |\input alphalph.sty|
-% \item[\LaTeXe:] |\usepackage{alphalph}|\\
-% There aren't any options.
-% \end{description}
+% \subsection{Introduction}
+% \LaTeX\ counter can be represented in different ways
+% by using presentation commands:
+% \begin{quote}
+% \cs{arabic}, \cs{roman}, \cs{Roman},\\
+% \cs{alph}, \cs{Alph}, \cs{fnsymbol}
+% \end{quote}
+% The ranges of supported counter values are more or less
+% restricted. Only \cs{arabic} can be used with any counter
+% value \TeX\ supports.
+% \begin{quote}
+% \catcode`\|=12 %
+% \begin{tabular}{@{}l|l|l|l@{}}
+% Presentation & Supported & Ignored & Error message\\
+% command & domain & values & ``Counter too large''\\
+% \hline
+% \cs{arabic}
+% & \ttfamily -MAX..MAX & &\\
+% \cs{roman}, \cs{Roman}
+% & \ttfamily 1..MAX & \ttfamily MAX..0 &\\
+% \cs{alph}, \cs{Alph}
+% & \ttfamily 1..26 & 0 & \ttfamily MAX..-1, 27..MAX\\
+% \cs{fnsymbol}
+% & \ttfamily 1..9 & 0 & \ttfamily -MAX..-1, 10..MAX\\
+% \hline
+% \end{tabular}\\[1ex]
+% \texttt{MAX} = \texttt{2147483647}
+% \end{quote}
+% Ordinal numbers are often used in documents: numbering
+% of chapters, sections, figures, footnotes and so on.
+% The layouter chooses \cs{Alph} for chapter numbers
+% and \cs{fnsymbol} for footnotes. But what can be done
+% if there are more than 26 chapters or more than 10 footnotes?
+% This package \xpackage{alphalph} allows to define new
+% presentation commands. They rely on a existing command
+% and define presentations for values greater the limits.
+% Three different methods are provided by the package.
+% In the following use cases they are presentated.
+%
+% \subsection{Use cases}
+%
+% \subsubsection{Number system based on symbols}
+%
+% Asume you are writing a book and your lecturer demands
+% that chapter numbers must be letters. But you have already
+% 30 chapters and you have only 26 letters?
+%
+% In the decimal system the situation would be clear.
+% If you run out of digits, you are using more digits
+% to represent a number. This method can be also be used
+% for letters. After chapter 26 with |Z| we us |AA|, |AB|, |AC|, and |AD|
+% for the remaining chapters.
+%
+% Happily this package already defines this presentation command:
+%\begin{quote}
+%\begin{verbatim}
+%\usepackage{alphalph}
+%\renewcommand*{\thechapter}{%
+% \AlphAlph{\value{chapter}}%
+%}
+%\end{verbatim}
+%\end{quote}
+% \cs{AlphAlph} generates:
+% \AlphAlph{1}, \AlphAlph{2}, \AlphAlph{3}, \dots,
+% \AlphAlph{26}, \AlphAlph{27}, \AlphAlph{28}, \dots
+%
+% The other presentation command is \cs{alphalph} for lowercase letters.
+%
+% \subsubsection{Wrap symbols around}
+%
+% Nine footnote symbols are quite a few.
+% Too soon the symbols are consumed
+% and \LaTeX\ complains with the error ``Counter too large''.
+% However, it could be acceptable to start again with the symbols
+% from the beginning, especially if there are less than nine symbols
+% on a page.
+% This could be achieved by a counter reset.
+% But finding the right place can be difficult or needs manual
+% actions. Also a
+% unique counter value can be desirable (e.g. for generating
+% unique anchor/link names).
+% Package \xpackage{alphalph} allows you to define
+% a macro that implements a ``wrap around'', but letting
+% the value of the counter untouched:
+%\begin{quote}
+%\begin{verbatim}
+%\usepackage{alphalph}
+%\makeatletter
+%\newalphalph{\fnsymbolwrap}[wrap]{\@fnsymbol}{}
+%\makeatother
+%\renewcommand*{\thefootnote}{%
+% \fnsymbolwrap{\value{footnote}}%
+%}
+%\end{verbatim}
+%\end{quote}
+% \cs{fnsymbolwrap} generates:
+% \fnsymbolwrap{1}~(1), \fnsymbolwrap{2}~(2), \fnsymbolwrap{3}~(3), \dots,
+% \fnsymbolwrap{9}~(9), \fnsymbolwrap{10}~(10), \fnsymbolwrap{11}~11, \dots
%
-% \subsection{User commands}
-% \begin{description}
-% \item[\cmd{\alphalph}:]\DescribeMacro{\alphalph}
-% This works like \cmd{\number}, but the expansion consists of
-% lowercase letters.
-% \item[\cmd{\AlphAlph}:]\DescribeMacro{\AlphAlph}
-% It converts a number into uppercase letters.
-% \end{description}
-% Both commands have following properties:
-% \begin{itemize}
-% \item They are fully expandable. This means that they can safely
-% \begin{itemize}
-% \item be written to a file,
-% \item used in moving arguments (\LaTeX: they are \emph{robust}),
-% \item used in a \cmd{\csname}-\cmd{\endcsname} pair.
-% \end{itemize}
-% \item If the argument is zero or negative, the commands expand
-% to nothing like \cmd{\romannumeral}.
-% \item As argument is allowed all that can be used after a \cmd{\number}:
-% \begin{itemize}
-% \item explicite constants,
-% \item macros that expand to a number,
-% \item count registers, \LaTeX\ counter can used
-% via \cmd{\value}, e.\,g.:\\
-% |\alphalph{\value{page}}|
-% \end{itemize}
-% \end{itemize}
-%
-% The following table shows, how the conversion is made:
-% \begin{center}
-% \catcode`\|=12
-% \catcode`\+\active
-% \def+#1&{\alphalph{#1}&}%
-% \begin{tabular}{@{}l|*{14}{r@{, }}r@{}}
-% number & 1& 2&\dots& 26& 27&\dots& 52& 53&
-% \dots& 78& 79&\dots& 702& 703&\dots
-% \\\hline
-% \cmd{\alphalph}&+1&+2&\dots&+26&+27&\dots&+52&+53&
-% \dots&+78&+79&\dots&+702&+703&\dots
-% \end{tabular}
-% \end{center}
-%
-% \subsubsection{New commands like \cs{alphalph}}
-% \begin{description}
-% \item[\cmd{\newalphalph}:]\DescribeMacro{\newalphalph}
-% This macro defines a new command that acts like \cs{alphalph}.
-% The use of \eTeX is required.
-% The macro has three arguments:
-% \begin{itemize}
-% \item[\texttt{\#1}:] The command to be defined.
-% \item[\texttt{\#2}:] A macro that converts a positive number
-% to a symbol.
-% \item[\texttt{\#3}:] The number of available symbols.
-% \end{itemize}
-% \end{description}
-%
-% Example:
+% \subsubsection{Multiple symbols}
+%
+% \LaTeX's standard set of footnote symbols contains doubled
+% symbols at the higher positions. Could this principle
+% be generalized?
+% Yes, but first we need a clean footnote symbol list without
+% doubled entries, example:
+%\begin{quote}
+%\begin{verbatim}
+%\usepackage{alphalph}
+%\makeatletter
+%\newcommand*{\fnsymbolsingle}[1]{%
+% \ensuremath{%
+% \ifcase#1%
+% \or *%
+% \or \dagger
+% \or \ddagger
+% \or \mathsection
+% \or \mathparagraph
+% \else
+% \@ctrerr
+% \fi
+% }%
+%}
+%\makeatother
+%\newalphalph{\fnsymbolmult}[mult]{\fnsymbolsingle}{}
+%\renewcommand*{\thefootnote}{%
+% \fnsymbolmult{\value{footnote}}%
+%}
+%\end{verbatim}
+%\end{quote}
+% The own definition of \cs{fnsymbolsingle} has the
+% advantage that this list can easily modified.
+% Otherwise you can use \cs{@fnsymbol} directly,
+% because it uses the same first five symbols.
%\begin{quote}
%\begin{verbatim}
-%\newcommand*{\myvocals}[1]{%
-% \ifcase#1\or A\or E\or I\or O\or U\fi
+%\usepackage{alphalph}
+%\makeatletter
+%\newalphalph{\fnsymbolmult}[mult]{\@fnsymbol}{5}
+%\makeatother
+%\renewcommand*{\thefootnote}{%
+% \fnsymbolmult{\value{footnote}}%
%}
-%\newalphalph{\vocalsvocals}{\myvocals}{5}
%\end{verbatim}
%\end{quote}
+% \cs{fnsymbolmult} generates:
+% \fnsymbolmult{1}~(1), \fnsymbolmult{2}~(2), \fnsymbolmult{3}~(3),
+% \fnsymbolmult{4}~(4), \fnsymbolmult{5}~(5), \fnsymbolmult{6}~(6),
+% \dots, \fnsymbolmult{16}~16, \fnsymbolmult{17}~17, \dots
+%
+% \bigskip
+% The same method can also be used for the chapter problem
+% in the first discussed use case:
+%\begin{quote}
+%\begin{verbatim}
+%\usepackage{alphalph}
+%\makeatletter
+%\newalphalph{\AlphMult}[mult]{\@Alph}{26}
+%\makeatother
+%\renewcommand*{\chapter}{%
+% \AlphMult{\value{chapter}}%
+%}
+%\end{verbatim}
+%\end{quote}
+% \cs{AlphMult} then generates AA, BB, CC, and DD for chapters 27--30.
+%
+% \subsection{Glossary}
+%
+% \begin{description}
+% \item[Counter presentation command] is a macro that
+% expects a \LaTeX\ counter name as argument.
+% Numbers cannot be used. Examples:
+% \cs{arabic}, \cs{alph}, \cs{fnsymbol}.
+% \item[Number presentation command] is a macro that
+% expects a number as argument. A number is anything
+% that \TeX\ accepts as number including \cs{value}.
+% Examples: \cs{alphalph}, \cs{AlphAlph}, \cs{alphalph@alph}
+%
+% However, \cs{alph} or \cs{fnsymbol} are not number
+% presentation commands because they expect a counter
+% name as argument. Happily \LaTeX\ counter presentation
+% commands internally uses number presentation commands
+% with the same name, but prefixed by `@'. Thus
+% \cs{@alph}, \cs{@fnsymbol} are number presentation commands.
+% \item[Symbols provider] is a command that can be used
+% to get a list of symbols. For example, \cs{@Alph}
+% provides the 26 uppercase letters from `A' to `Z'.
+% Basically a symbol provider is a number presentation
+% command, usually with a limited range.
+% \item[Number of symbols] is the number of the
+% last symbol slot of a symbol provider. Thus \cs{@Alph}
+% generates 26 symbols, \cs{@fnsymbol} provides 9 symbols.
+% \end{description}
+%
+% \subsection{Package usage}
+%
+% The package \Package{alphalph} can be used with both \plainTeX\
+% and \LaTeX:
+% \begin{description}
+% \item[\plainTeX:] |\input alphalph.sty|
+% \item[\LaTeXe:] |\usepackage{alphalph}|\\
+% There aren't any options.
+% \end{description}
+%
+% \subsection{User commands}
+%
+% \begin{declcs}{AlphAlph} \M{number}\\
+% \cs{alphalph} \M{number}
+% \end{declcs}
+% Both macros are number presentation commands that
+% expects a number as argument. \LaTeX\ counters
+% are used with \cs{value}.
+%
+% The macros represents a number by letters.
+% First single letters |A..Z| are used, then
+% two letters |AA..ZZ|, three letters |AAA...ZZZ|, \dots
+% follow.
+%
+% Macro \cs{AlphAlph} uses uppercase letters,
+% \cs{alphalph} generates the lowercase variant.
+% \begin{quote}
+% \catcode`\|=12
+% \def\entry#1{
+% \texttt{#1}
+% & \texttt{\AlphAlph{#1}}
+% & \texttt{\alphalph{#1}}
+% }
+% \begin{tabular}{@{}l|l|l@{}}
+% \meta{number} & \verb|\AlphAlph{|\meta{number}\verb|}|
+% & \verb|\alphalph{|\meta{number}\verb|}|\\
+% \hline
+% \entry{1}\\
+% \entry{2}\\
+% \entry{26}\\
+% \entry{27}\\
+% \entry{30}\\
+% \entry{2000}\\
+% \entry{3752127}\\
+% \entry{10786572}\\
+% \entry{2147483647}\\
+% \end{tabular}
+% \end{quote}
+%
+% \begin{declcs}{newalphalph}
+% \M{cmd}
+% |[|\meta{method}|]|
+% \M{symbols provider}
+% \M{number of symbols}
+% \end{declcs}
+% Macro \cs{newalphalph} defines \meta{cmd} as new
+% number presentation command. Like \cs{newcommand} an error
+% is thrown, if macro \meta{cmd} already exists.
+%
+% The \meta{method} is one of |alph|, |wrap|, or |mult|.
+% The default is |alph|.
+%
+% As symbol provider a number presentation command
+% can be used, e.g. \cs{@fnsymbol}, \cs{@Alph}, or
+% \cs{alphalph@alph}.
+%
+% The last argument is the number of symbols.
+% If the argument is empty, then \cs{newalphalph} tries
+% to find this number itself. \LaTeX's number presentation
+% commands throw an error message, if the number is too large.
+% This error message is put in a macro \cs{@ctrerr}.
+% Thus \cs{newalphalph} calls the symbol provider and tests
+% a number by typesetting it in a temporary box. The error
+% macro \cs{@ctrerr} is catched, it proofs that the number
+% is not supported. Also if the width of the result is zero
+% the number is considered as unavailable.
+%
+% The empty argument is useful for potentially variable lists.
+% However if the end cannot be detected, then the number of
+% symbols must be given. This is also a lot faster. Therefore don't
+% let the argument empty without reason.
+%
+% \subsection{Programmer commands}
+%
+% \begin{declcs}{alphalph@Alph} \M{number}\\
+% \cs{alphalph@alph} \M{number}
+% \end{declcs}
+% They are basically the same as \cs{@Alph} and \cs{@alph}.
+% Some languages of package \xpackage{babel} redefine
+% \LaTeX's macros to include some font setup that
+% breaks expandibility. Therefore \cs{AlphAlph} and \cs{alphalph}
+% are based on \cs{alphalph@Alph} and \cs{alphalph@alph} to get
+% the letters. The behaviour of these symbol providers for numbers
+% outside the range |1..26| is undefined.
+%
+% \subsection{Design principles}
+%
+% \subsubsection{Number presentation commands}
+%
+% All number presentation commands that this package defines
+% (including \cs{alphalph} and \cs{AlphAlph}) have the following
+% properties:
+% \begin{itemize}
+% \item They are fully expandable. This means that they can safely
+% \begin{itemize}
+% \item be written to a file,
+% \item used in moving arguments (\LaTeX: they are \emph{robust}),
+% \item used in a \cmd{\csname}-\cmd{\endcsname} pair.
+% \end{itemize}
+% \item If the argument is zero or negative, the commands expand
+% to nothing like \cmd{\romannumeral}.
+% \item The argument is a \TeX\ number. Anything that would be
+% accepted by \cmd{\number} is a valid argument:
+% \begin{itemize}
+% \item explicite constants,
+% \item macros that expand to a number,
+% \item count registers, \LaTeX\ counter can used
+% via \cmd{\value}, e.\,g.:\\
+% |\alphalph{\value{page}}|
+% \item \dots
+% \end{itemize}
+% \item \eTeX's numeric expressions are supported, if \eTeX\ is
+% available. Then \cs{numexpr} is applied to the argument.
+% Package \cs{calc}'s expressions are not supported.
+% That would violate the expandibility.
+% \end{itemize}
+%
+% \subsubsection{General usability}
+%
+% \begin{description}
+% \item[\TeX\ format:]
+% The package does not depend on \LaTeX, it can also be used
+% by \plainTeX, for example.
+% \item[\eTeX:] \eTeX is supported, the macros are shorter and
+% faster. But \eTeX's extensions are not requirements.
+% Without \eTeX, just the implementation changes. The properties
+% remain unchanged.
+% \end{description}
%
% \StopEventually{
% }
@@ -319,18 +605,107 @@ and the derived files
\fi
\expandafter\x\csname ver@alphalph.sty\endcsname
\ProvidesPackage{alphalph}%
- [2007/04/11 v1.5 Converting numbers to letters (HO)]
+ [2007/04/11 v2.0 Converting numbers to letters (HO)]
% \end{macrocode}
%
-% For unique command names this package uses |aa@| as prefix
-% for internal command names. Because we need |@| as a letter
-% we save the current catcode value.
+% \subsection{Catcodes}
+%
% \begin{macrocode}
-\expandafter\edef\csname aa@atcode\endcsname{\the\catcode`\@ }
-\catcode`\@=11
+\expandafter\edef\csname AlPh@AtEnd\endcsname{%
+ \catcode64 \the\catcode64\relax
+}
+\catcode64 11 % @
+\def\TMP@EnsureCode#1#2{%
+ \edef\AlPh@AtEnd{%
+ \AlPh@AtEnd
+ \catcode#1 \the\catcode#1\relax
+ }%
+ \catcode#1 #2\relax
+}
+\TMP@EnsureCode{33}{12}% !
+\TMP@EnsureCode{39}{12}% '
+\TMP@EnsureCode{40}{12}% (
+\TMP@EnsureCode{41}{12}% )
+\TMP@EnsureCode{43}{12}% +
+\TMP@EnsureCode{44}{12}% ,
+\TMP@EnsureCode{46}{12}% .
+\TMP@EnsureCode{47}{12}% /
+\TMP@EnsureCode{59}{12}% ;
+\TMP@EnsureCode{60}{12}% <
+\TMP@EnsureCode{61}{12}% =
+\TMP@EnsureCode{62}{12}% >
+\TMP@EnsureCode{91}{12}% [
+\TMP@EnsureCode{93}{12}% ]
+\TMP@EnsureCode{96}{12}% `
+\TMP@EnsureCode{124}{12}% |
+% \end{macrocode}
+%
+% \subsection{Package loading}
+%
+% \begin{macrocode}
+\begingroup\expandafter\expandafter\expandafter\endgroup
+\expandafter\ifx\csname RequirePackage\endcsname\relax
+ \input infwarerr.sty\relax
+ \input intcalc.sty\relax
+\else
+ \RequirePackage{infwarerr}[2007/09/09]%
+ \RequirePackage{intcalc}[2007/09/09]%
+\fi
+% \end{macrocode}
+%
+% \subsection{\eTeX\ detection}
+%
+% \begin{macrocode}
+\begingroup\expandafter\expandafter\expandafter\endgroup
+\expandafter\ifx\csname numexpr\endcsname\relax
+ \catcode124=9 % '!': ignore
+ \catcode43=14 % '+': comment
+\else
+ \catcode124=14 % '!': comment
+ \catcode43=9 % '+': ignore
+\fi
% \end{macrocode}
%
% \subsection{Help macros}
+%
+% \begin{macro}{\AlPh@Error}
+% \begin{macrocode}
+\def\AlPh@Error#1{%
+ \begingroup
+ \escapechar=92 % backslash
+ \@PackageError{alphalph}{#1}\@ehc
+ \endgroup
+}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\AlPh@IfDefinable}
+% \begin{macrocode}
+\begingroup\expandafter\expandafter\expandafter\endgroup
+\expandafter\ifx\csname @ifdefinable\endcsname\relax
+ \def\AlPh@IfDefinable#1#2{%
+ \ifcase\ifx#1\@undefined\else\ifx#1\relax\else1\fi\fi0 %
+ #2%
+ \else
+ \AlPh@Error{%
+ Command \string#1 already defined%
+ }%
+ \fi
+ }%
+% \end{macrocode}
+% \end{macro}
+% \begin{macrocode}
+\else
+% \end{macrocode}
+% \begin{macro}{\AlPh@IfDefinable}
+% \begin{macrocode}
+ \let\AlPh@IfDefinable\@ifdefinable
+% \end{macrocode}
+% \end{macro}
+% \begin{macrocode}
+\fi
+% \end{macrocode}
+%
% \begin{macro}{\@ReturnAfterElseFi}
% \begin{macro}{\@ReturnAfterFi}
% The following commands moves the `then' and `else' part respectively
@@ -338,7 +713,7 @@ and the derived files
% and so a \TeX\ capacity error because of a limited input stack size.
% I use this trick in several packages, so I don't prefix these internal
% commands in order not to have the same macros with different names.
-% (It saves memory).
+% (It saves memory.)
% \begin{macrocode}
\long\def\@ReturnAfterElseFi#1\else#2\fi{\fi#1}
\long\def\@ReturnAfterFi#1\fi{\fi#1}
@@ -346,461 +721,810 @@ and the derived files
% \end{macro}
% \end{macro}
%
-% \begin{macro}{\aa@alph}
-% \begin{macro}{\aa@Alph}
-% The two commands \cmd{\aa@alph} and \cmd{\aa@Alph} convert a
-% number into a letter (lowercase and uppercase respectivly).
+% \begin{macro}{\@gobblefour}
+% \LaTeX\ defines commands for eating arguments.
+% Define \cs{@gobblefour} if it is not defined (\plainTeX).
+% \begin{macrocode}
+\expandafter\ifx\csname @gobblefour\endcsname\relax
+ \long\def\@gobblefour#1#2#3#4{}%
+\fi
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{AlPh@IfOptArg}
+% \begin{macrocode}
+\begingroup\expandafter\expandafter\expandafter\endgroup
+\expandafter\ifx\csname kernel@ifnextchar\endcsname\relax
+ \begingroup\expandafter\expandafter\expandafter\endgroup
+ \expandafter\ifx\csname @ifnextchar\endcsname\relax
+ \def\AlPh@IfOptArg#1#2{%
+ \def\AlPh@TempA{#1}%
+ \def\AlPh@TempB{#2}%
+ \futurelet\AlPh@Token\AlPh@IfOptArgNext
+ }%
+ \let\AlPh@BracketLeft=[%]
+ \def\AlPh@IfOptArgNext{%
+ \ifx\AlPh@Token\AlPh@BracketLeft
+ \expandafter\AlPh@TempA
+ \else
+ \expandafter\AlPh@TempB
+ \fi
+ }%
+ \else
+ \def\AlPh@IfOptArg{\@ifnextchar[}%]
+ \fi
+\else
+ \def\AlPh@IfOptArg{\kernel@ifnextchar[}%]
+\fi
+% \end{macrocode}
+% \end{macro}
+%
+% \subsection{Symbol provider}
+%
+% \subsubsection{Alphabet}
+%
+% The output of \cs{alphalph} and \cs{AlphAlph} should be
+% usable as part of command names (see \cs{@namedef}, \cs{csname}, \dots).
+% Unhappily some languages of package \xpackage{babel}
+% redefine \LaTeX's \cs{@alph} and \cs{@Alph} in a manner that
+% they cannot be used in expandable context any more.
+% Therefore package \xpackage{alphalph} provides its own
+% commands.
+%
+% \begin{macro}{\alphalph@Alph}
+% \begin{macro}{\alphalph@alph}
+% The two commands \cmd{\AlPh@Alph} and \cmd{\AlPh@alph} convert a
+% number into a letter (uppercase and lowercase respectivly).
% The character |@| is used as an error symbol,
% if the number isn't in the range of 1 until 26.
% Here we need no space after the number |#1|, because the error
% symbol |@| for the zero case stops scanning the number.
+% This error symbol should not appear anywhere (except for bugs).
% \begin{macrocode}
-\def\aa@alph#1{%
+\def\alphalph@Alph#1{%
\ifcase#1%
@%
- \or a\or b\or c\or d\or e\or f\or g\or h\or i\or j\or k\or l\or m%
- \or n\or o\or p\or q\or r\or s\or t\or u\or v\or w\or x\or y\or z%
+ \or A\or B\or C\or D\or E\or F\or G\or H\or I\or J\or K\or L\or M%
+ \or N\or O\or P\or Q\or R\or S\or T\or U\or V\or W\or X\or Y\or Z%
\else
+ \AlPh@ctrerr
@%
\fi
}
-\def\aa@Alph#1{%
+\def\alphalph@alph#1{%
\ifcase#1%
@%
- \or A\or B\or C\or D\or E\or F\or G\or H\or I\or J\or K\or L\or M%
- \or N\or O\or P\or Q\or R\or S\or T\or U\or V\or W\or X\or Y\or Z%
+ \or a\or b\or c\or d\or e\or f\or g\or h\or i\or j\or k\or l\or m%
+ \or n\or o\or p\or q\or r\or s\or t\or u\or v\or w\or x\or y\or z%
\else
+ \AlPh@ctrerr
@%
\fi
}
% \end{macrocode}
% \end{macro}
% \end{macro}
-%
-% \subsection{User commands}
-% \begin{macro}{\alphalph}
-% \begin{macro}{\AlphAlph}
-% The whole difference between \cmd{\alphalph} and \cmd{\AlphAlph}
-% is that the output consists of lowercase or uppercase letters.
+% \begin{macro}{\AlPh@ctrerr}
+% Macro \cs{AlPh@ctrerr} is used as hook for the algorithm
+% to get the available number of symbols.
% \begin{macrocode}
-\def\alphalph{\aa@callmake\aa@alph}
-\def\AlphAlph{\aa@callmake\aa@Alph}
+\def\AlPh@ctrerr{}
% \end{macrocode}
% \end{macro}
-% \end{macro}
%
-% \begin{macro}{\aa@callmake}
-% \cmd{\aa@callmake} converts the number in
-% the second argument |#2| into explicite decimal digits via
-% the \TeX\ primitive \cmd{\number}. (The closing curly brace stops reading
-% the number at the latest.)
+% \subsection{Finding number of symbols}
+%
+% \begin{macro}{\AlPh@GetNumberOfSymbols}
+% \noindent
+% |#1|: symbols provider
% \begin{macrocode}
-\def\aa@callmake#1#2{%
- \expandafter\aa@make\expandafter{\number#2}#1%
+\def\AlPh@GetNumberOfSymbols#1{%
+ \AlPh@TestNumber1!{#1}%
+ \ifAlPh@Unavailable
+ \def\AlPh@Number{0}%
+ \AlPh@Error{No symbols found}%
+ \else
+ \def\AlPh@Number{1}%
+ \AlPh@ExpSearch2!{#1}%
+ \fi
}
% \end{macrocode}
% \end{macro}
-%
-% \eTeX provides the new primitive \cmd{\numexpr}.
-% With this command the implementation is very simple
-% (see \ref{sec:etex}). Therefore the package provides two
-% methods: a fast and simple one that uses the \eTeX\ extension
-% and a method that is restricted to the standard \TeX\ means.
-%
-% Now we distinguish between \TeX\ and \eTeX\ by checking
-% whether \cmd{\numexpr} is defined or isn't.
-% Because the \TeX\ primitive \cmd{\csname} defines an
-% undefined command to be \cmd{\relax}, \cmd{\csname}
-% is executed in a group.
+% \begin{macro}{\ifAlPh@Unavailable}
% \begin{macrocode}
-\begingroup\expandafter\expandafter\expandafter\endgroup
-\expandafter\ifx\csname numexpr\endcsname\relax
+\newif\ifAlPh@Unavailable
+\def\AlPh@Unavailabletrue{%
+ \global\let\ifAlPh@Unavailable\iftrue
+}
+\def\AlPh@Unavailablefalse{%
+ \global\let\ifAlPh@Unavailable\iffalse
+}
% \end{macrocode}
-%
-% \subsection{\texorpdfstring{Conversion with standard \TeX\ means}{\TeX}}
-% \begin{macro}{\aa@make}
-% \cmd{\aa@make} catches the cases, if the number is zero or negative.
-% Then it expands to nothing like \cmd{\romannumeral}.
+% \end{macro}
+% \begin{macro}{\AlPh@TestNumber}
+% |#1|: number to be tested\\
+% |#2|: symbols provider
% \begin{macrocode}
- \def\aa@make#1#2{%
- \ifnum#1<1 %
- \else
- \@ReturnAfterFi{%
- \aa@process1;#1;1..#2%
- }%
+\def\AlPh@TestNumber#1!#2{%
+ \AlPh@Unavailablefalse
+ \begingroup
+ \setbox0=\hbox{%
+ \begingroup % color
+ \let\@ctrerr\AlPh@Unavailabletrue
+ \let\AlPh@ctrerr\AlPh@Unavailabletrue
+ #2{#1}%
+ \endgroup
+ }%
+ \ifdim\wd0=0pt %
+ \AlPh@Unavailabletrue
\fi
- }%
+ \endgroup
+}
% \end{macrocode}
% \end{macro}
-%
-% \begin{macro}{\aa@process}
-% \cmd{\aa@process} contains the algorithm for the conversion.
-% \TeX doesn't provide a simple method to divide or multiply
-% numbers in a fully expandable way. An expandable addition by one
-% is complicated enough. Therefore \cmd{\aa@process} uses
-% only expandible versions of additions by one. The algorithm
-% starts with one and increments it until the size of the wanted
-% number is reached. The intermediate number that is incremented
-% is present in two kinds:
-% \begin{itemize}
-% \item the normal decimal form for the \cs{ifnum}-comparison,
-% \item a digit format: the end of each digit is marked by an dot,
-% and the digits are in reserved order. An empty digit
-% ends this format. The meaning of a digit is here the
-% decimal representation of a letter, the range is
-% from 1 until 26.
-% \end{itemize}
-% Example: The aim number is 100, the intermediate number 50, so
-% following would be on the argument stack:
-% \begin{quote}
-% |50;100;24.1..\aa@alph|
-% \end{quote}
-% \cmd{\aa@process} increments the first argument |#1| (|50|),
-% and calls \cmd{\aa@alphinc} to increment the digit form
-% (|24.1..|). The middle part with the aim number |;#2;| (|;100;|)
-% will not be changed. Neither \cmd{\aa@process} nor \cmd{\aa@alphinc}
-% need the conversion command \cmd{\aa@alph} nor \cmd{\aa@Alph}.
-% This command is read by \cmd{\aa@getresult}, if the digit form is
-% ready.
-%
-% The expansion motor is \cmd{\number}. It reads and expands token
-% to get decimal numbers until a token is reached that isn't a
-% decimal digit. So the expansion doesn't stop, if \cmd{\aa@inc}
-% is ready, because \cmd{\aa@inc} produces only decimal digits.
-% \cmd{\aa@alphinc} is expanded to look for further digits.
-% Now \cmd{\aa@alphinc} makes its job and returns with its
-% argument |;#2;|. At last the first character |;| finishes \cmd{\number}.
+% \begin{macro}{\AlPh@ExpSearch}
+% |#1|: number to be tested\\
+% |#2|: symbols provider
% \begin{macrocode}
- \def\aa@process#1;#2;{%
- \ifnum#1=#2 %
- \expandafter\aa@getresult
+\def\AlPh@ExpSearch#1!#2{%
+ \let\AlPh@Next\relax
+ \AlPh@TestNumber#1!{#2}%
+ \ifAlPh@Unavailable
+ \expandafter\AlPh@BinSearch\AlPh@Number!#1!{#2}%
+ \else
+ \def\AlPh@Number{#1}%
+ \ifnum#1>1073741823 %
+ \AlPh@TestNumber2147483647!{#2}%
+ \ifAlPh@Unavailable
+ \AlPh@BinSearch#1!2147483647!{#2}%
+ \else
+ \def\AlPh@Number{0}%
+ \AlPh@Error{%
+ Maximal symbol number not found%
+ }%
+ \fi
\else
- \@ReturnAfterFi{%
- \expandafter\aa@process\number\aa@inc{#1}\aa@alphinc{;#2;}%
+ \def\AlPh@Next{%
+ \expandafter\AlPh@ExpSearch\number\intcalcShl{#1}!{#2}%
}%
\fi
- }%
+ \fi
+ \AlPh@Next
+}
% \end{macrocode}
% \end{macro}
-%
-% \subsubsection{\texorpdfstring{^^A
-% Convert the separated digits to the letter result}{^^A
-% Digits to letter result}}\label{sec:form}
-%
-% The single decimal digits of the final letter number are
-% limited by a dot and come in reverse order. The end is
-% marked by an empty digit.
-% The next token is the command to convert a digit
-% (\cmd{\aa@alph} or \cmd{\aa@Alph}), e.g.:
-% \begin{quote}
-% |11.3.1..\alph| $\Rightarrow$ |ack|
-% \end{quote}
-%
-% \begin{macro}{\aa@getresult}
-% \cmd{\aa@getresult} reads the digits |#1| and the converting
-% command |#2|. Then it
-% calls \cmd{\aa@@getresult} with its arguments.
+% \begin{macro}{\AlPh@BinSearch}
+% |#1|: available number\\
+% |#2|: unavailable number, |#2| $>$ |#1|\\
+% |#3|: symbols provider
% \begin{macrocode}
- \def\aa@getresult#1..#2{%
- \aa@@getresult!#2#1..%
- }%
+\def\AlPh@BinSearch#1!#2!#3{%
+ \expandafter\AlPh@ProcessBinSearch
+ \number\intcalcShr{\intcalcAdd{#1}{#2}}!%
+ #1!#2!{#3}%
+}
% \end{macrocode}
% \end{macro}
-%
-% \begin{macro}{\aa@@getresult}
-% In its first argument |#1| \cmd{\aa@@getresult} collects the
-% converted letters in the correct order. Character |!| is used
-% as a parameter separator. The next token |#2| is the converting
-% command (\cmd{\aa@alph} or \cmd{\aa@Alph}). The next digit |#3|
-% is read, converted, and |\aa@@getresult| is called again.
-% If the digit |#3| is empty, the end of the digit form is reached
-% and the process stops and the ready letter number is output.
+% \begin{macro}{\AlPh@ProcessBinSearch}
+% |#1|: number to be tested, |#2| $\leq$ |#1| $\leq$ |#3|\\
+% |#2|: available number\\
+% |#3|: unavailable number\\
+% |#4|: symbols provider
% \begin{macrocode}
- \def\aa@@getresult#1!#2#3.{%
- \ifx\\#3\\%
- \@ReturnAfterElseFi{#1}% ready
+\def\AlPh@ProcessBinSearch#1!#2!#3!#4{%
+ \let\AlPh@Next\relax
+ \ifnum#1>#2 %
+ \ifnum#1<#3 %
+ \AlPh@TestNumber#1!{#4}%
+ \ifAlPh@Unavailable
+ \def\AlPh@Next{%
+ \AlPh@BinSearch#2!#1!{#4}%
+ }%
+ \else
+ \def\AlPh@Next{%
+ \AlPh@BinSearch#1!#3!{#4}%
+ }%
+ \fi
\else
- \@ReturnAfterFi{%
- \expandafter\expandafter\expandafter\expandafter
- \expandafter\expandafter\expandafter
- \aa@@getresult
- \expandafter\expandafter\expandafter\expandafter
- #2{#3}#1!#2%
- }%
+ \def\AlPh@Number{#2}%
\fi
- }%
+ \else
+ \def\AlPh@Number{#2}%
+ \fi
+ \AlPh@Next
+}
% \end{macrocode}
% \end{macro}
%
-% \subsubsection{Addition by one}
-%
-% \paragraph{Expandable addition of a decimal integer.}
-% \begin{macro}{\aa@inc}
-% \cmd{\aa@inc} increments its argument |#1| by one.
-% The case, that the whole number is less than nine, is
-% specially treated because of speed. (The space
-% after |9| is neccessary.)
+% \subsection{Methods}
+%
+% The names of method macros start with \cs{AlPh@Method}.
+% These macros do the main job in converting a number to
+% its representation.
+% A method command is called with three arguments.
+% The first argument is the number of symbols. The
+% second argument is the basic macro for converting
+% a number with limited number range. The last parameter
+% is the number that needs converting.
+%
+% \subsubsection{Common methods}
+%
+% \begin{macro}{\AlPh@CheckPositive}
+% \noindent
+% |#1|: number to be checked
+% |#2|: continuation macro\\
+% |#3|: number of symbols (hidden here)\\
+% |#4|: symbol provider (hidden here)
% \begin{macrocode}
-% \aa@inc adds one to its argument #1.
- \def\aa@inc#1{%
- \ifnum#1<9 %
- \aa@nextdigit{#1}%
- \else
- \aa@reverse#1!!%
- \fi
- }%
+\def\AlPh@CheckPositive#1!#2{%
+ \ifnum#1<1 %
+ \expandafter\@gobblefour
+ \fi
+ #2{#1}%
+}
% \end{macrocode}
% \end{macro}
-% \begin{macro}{\aa@nextdigit}
-% \cmd{\aa@nextdigit} increments the digit |#1|. The result
-% is a digit again. \cmd{\aa@addone} works off the case ``9+1''.
+%
+% \subsubsection{Method `alph'}
+%
+% \begin{macro}{\AlPh@Method@alph}
+% \noindent
+% |#1|: number of symbols\\
+% |#2|: symbols provider\\
+% |#3|: number to be converted
% \begin{macrocode}
- \def\aa@nextdigit#1{\ifcase#1 1\or2\or3\or4\or5\or6\or7\or8\or9\fi}%
+\def\AlPh@Method@alph#1#2#3{%
+ \expandafter\AlPh@CheckPositive
+| \number#3!%
++ \the\numexpr#3!%
+ \AlPh@ProcessAlph
+ {#1}{#2}%
+}
% \end{macrocode}
% \end{macro}
-% \begin{macro}{\aa@reverse}
-% Because the addition starts with the lowest significant digit
-% of the number. But with the means of \TeX's macro expansion is
-% the first digit of a number available. So \cmd{\aa@reverse}
-% reverses the order of the digits and calls \cmd{\aa@addone},
-% if it is ready.
+% \begin{macro}{\AlPh@ProcessAlph}
+% |#1|: current number\\
+% |#2|: number of symbols\\
+% |#3|: symbols provider
% \begin{macrocode}
- \def\aa@reverse#1#2!#3!{%
- \ifx\\#2\\%
- \aa@addone#1#3!!%
- \else
- \@ReturnAfterFi{%
- \aa@reverse#2!#1#3!%
- }%
- \fi
- }%
+\def\AlPh@ProcessAlph#1#2#3{%
+ \ifnum#1>#2 %
+ \@ReturnAfterElseFi{%
+ \expandafter\AlPh@StepAlph\number
+ \intcalcInc{%
+ \intcalcMod{\intcalcDec{#1}}{#2}%
+ }%
+ \expandafter!\number
+ \intcalcDiv{\intcalcDec{#1}}{#2}%
+ !{#2}{#3}%
+ }%
+ \else
+ \@ReturnAfterFi{%
+ #3{#1}%
+ }%
+ \fi
+}
% \end{macrocode}
% \end{macro}
-% \begin{macro}{\aa@addone}
-% The addition is performed by the macro \cmd{\aa@addone}.
-% The digits are in reversed order. The parameter text |#1#2|
-% separates the next digit |#1| that have to be incremented.
-% Already incremented digits are stored in |#3| in reversed order
-% to take some work of \cmd{\aa@lastreverse}.
+% \begin{macro}{\AlPh@StepAlph}
+% |#1|: current last digit\\
+% |#2|: new current number\\
+% |#3|: number of symbols\\
+% |#4|: symbols provider
% \begin{macrocode}
- \def\aa@addone#1#2!#3!{%
- \ifnum#1<9 %
- \expandafter\aa@lastreverse\number\aa@nextdigit#1 #2!#3!%
- \else
- \@ReturnAfterFi{%
- \ifx\\#2\\%
- 10#3%
- \else
- \@ReturnAfterFi{%
- \aa@addone#2!0#3!%
- }%
- \fi
- }%
- \fi
- }%
+\def\AlPh@StepAlph#1!#2!#3#4{%
+ \AlPh@ProcessAlph{#2}{#3}{#4}%
+ #4{#1}%
+}
% \end{macrocode}
% \end{macro}
-% \begin{macro}{\aa@lastreverse}
-% With \cmd{\aa@reverse} the order of the digits is changed to
-% perform the addition in \cmd{\aa@addone}. Now we have to return
-% to the original order that is done by \cmd{\aa@lastreverse}.
+%
+% \subsubsection{Method `wrap'}
+%
+% \begin{macro}{\AlPh@Method@wrap}
+% \noindent
+% |#1|: number of symbols\\
+% |#2|: symbols provider\\
+% |#3|: number to be converted
% \begin{macrocode}
- \def\aa@lastreverse#1#2!#3!{%
- \ifx\\#2\\%
- #1#3%
- \else
- \@ReturnAfterFi{%
- \aa@lastreverse#2!#1#3!%
- }%
- \fi
- }%
+\def\AlPh@Method@wrap#1#2#3{%
+ \expandafter\AlPh@CheckPositive
+| \number#3!%
++ \the\numexpr#3!%
+ \AlPh@ProcessWrap
+ {#1}{#2}%
+}
% \end{macrocode}
% \end{macro}
%
-% \paragraph{Increment of the decimal digit result form.}
-% \begin{macro}{\aa@alphinc}
-% \cmd{\aa@alphinc} adds one to the intermediate number in
-% the decimal digit result form (see \ref{sec:form}).
-% Parameter |#1| consists of the tokens that come before the
-% addition result (see |;#2;| of \cmd{\aa@process}). Then
-% it is also used to store already incremented digits.
-% |#2| contains the next digit in the range of 1 until 26.
-% An empty |#2| marks the end of the number.
+% \begin{macro}{\AlPh@ProcessWrap}
+% |#1|: number to be converted\\
+% |#2|: number of symbols\\
+% |#3|: symbols provider
% \begin{macrocode}
- \def\aa@alphinc#1#2.{%
- \ifx\\#2\\%
- \@ReturnAfterElseFi{%
- #11..% ready
- }%
- \else
- \@ReturnAfterFi{%
- \ifnum#2<26 %
- \@ReturnAfterElseFi{%
- \expandafter\aa@alphinclast\expandafter
- {\number\aa@inc{#2}}{#1}%
- }%
- \else
- \@ReturnAfterFi{%
- \aa@alphinc{#11.}%
- }%
- \fi
- }%
- \fi
- }%
+\def\AlPh@ProcessWrap#1#2#3{%
+ \ifnum#1>#2 %
+ \@ReturnAfterElseFi{%
+ \expandafter\AlPh@StepWrap\number
+ \intcalcInc{\intcalcMod{\intcalcDec{#1}}{#2}}%
+ !{#3}%
+ }%
+ \else
+ \@ReturnAfterFi{%
+ #3{#1}%
+ }%
+ \fi
+}
% \end{macrocode}
% \end{macro}
-% \begin{macro}{\aa@alphinclast}
-% \cmd{\aa@alphinclast} is a help macro. Because |#2| consists of
-% several tokens (e.g. |;100;|), we cannot jump over it via
-% \cmd{\expandafter} in \cmd{\aa@alphinc}.
+% \begin{macro}{\AlPh@StepWrap}
+% |#1|: final number\\
+% |#2|: symbols provider
% \begin{macrocode}
- \def\aa@alphinclast#1#2{#2#1.}%
+\def\AlPh@StepWrap#1!#2{%
+ #2{#1}%
+}
% \end{macrocode}
% \end{macro}
%
-% \begin{macro}{\newalphalph}
+% \subsubsection{Method `mult'}
+%
+% After the number of symbols is exhausted,
+% repetitions of the symbol are used.
+% \begin{gather*}
+% x \Def \text{number to be converted}\\
+% n \Def \text{number of symbols}\\
+% r \Def \text{repetition length}\\
+% s \Def \text{symbol slot}\\
+% r = ((x - 1) \div n) + 1\\
+% s = ((x - 1) \mod n) + 1
+% \end{gather*}
+% \begin{macro}{\AlPh@Method@mult}
+% \noindent
+% |#1|: number of symbols\\
+% |#2|: symbols provider\\
+% |#3|: number to be converted
% \begin{macrocode}
- \newcommand*{\newalphalph}[3]{%
- \PackageError{alphalph}{%
- \string\newalphalph\space requires e-TeX%
- }\@ehc
+\def\AlPh@Method@mult#1#2#3{%
+ \expandafter\AlPh@CheckPositive
+| \number#3!%
++ \the\numexpr#3!%
+ \AlPh@ProcessMult
+ {#1}{#2}%
+}
% \end{macrocode}
% \end{macro}
%
-% \subsection{\texorpdfstring{Conversion with \eTeX\ features}{\eTeX}}
-% \label{sec:etex}
+% \begin{macro}{\AlPh@ProcessMult}
+% |#1|: number to be converted\\
+% |#2|: number of symbols\\
+% |#3|: symbols provider
% \begin{macrocode}
-\else
-% \end{macrocode}
-%
-% \begin{macro}{\aa@make}
-% \cmd{\aa@make} catches the cases, if the number is zero or negative.
-% Then it expands to nothing like \cmd{\romannumeral}.
-% \begin{macrocode}
- \def\aa@make#1#2{%
- \ifnum#1<1 %
- \else
- \@ReturnAfterFi{%
- \aa@eprocess#1;#2%
- }%
- \fi
- }%
+\def\AlPh@ProcessMult#1#2#3{%
+ \ifnum#1>#2 %
+ \@ReturnAfterElseFi{%
+ \expandafter\AlPh@StepMult\romannumeral
+ \intcalcInc{\intcalcDiv{\intcalcDec{#1}}{#2}}%
+ 000%
+ \expandafter!\number
+ \intcalcInc{\intcalcMod{\intcalcDec{#1}}{#2}}%
+ !{#3}%
+ }%
+ \else
+ \@ReturnAfterFi{%
+ #3{#1}%
+ }%
+ \fi
+}
% \end{macrocode}
% \end{macro}
-%
-% \begin{macro}{\aa@eprocess}
-% The first argument |#1| contains the number that have to be
-% converted yet, the next argument |#2| the command for making
-% the conversion of a digit (\cmd{\aa@alph} or \cmd{\aa@Alph}).
-% The number is divided by 26 to get the rest. Command
-% |#2| converts the rest to a letter that is put after the arguments
-% of the next call of \cmd{\aa@eprocess}.
-%
-% The only feature of \eTeX\ we use the new primitive \cmd{\numexpr}.
-% It provides expandible mathematical calculations.
+% \begin{macro}{\AlPh@StepMult}
+% |#1#2|: repetitions coded as list of character `m'\\
+% |#3|: symbol slot\\
+% |#4|: symbols provider
% \begin{macrocode}
- \def\aa@eprocess#1;#2{%
- \ifnum#1<27 %
- \@ReturnAfterElseFi{%
- #2{#1}%
- }%
- \else
- \@ReturnAfterFi{%
- \expandafter\aa@eprocess\number\numexpr(#1-14)/26%
- \expandafter\expandafter\expandafter;%
- \expandafter\expandafter\expandafter#2%
- #2{\numexpr#1-((#1-14)/26)*26}%
- }%
- \fi
- }%
+\def\AlPh@StepMult#1#2!#3!#4{%
+ \ifx\\#2\\%
+ \else
+ \@ReturnAfterFi{%
+ \AlPh@StepMult#2!#3!{#4}%
+ }%
+ \fi
+ #4{#3}%
+}
% \end{macrocode}
% \end{macro}
%
-% \subsection{Generic version}
+% \subsection{User interface}
%
-% \begin{macro}{\aa@gen@callmake}
-% See macro \cs{aa@callmake}. Argument |#3| holds the
-% number of available symbols.
+% \begin{macro}{\newalphalph}
+% Macro \cs{newalphalph} had three arguments in versions below 2.0.
+% For the new method argument we use an optional argument an first
+% position.\\
+% |#1|: cmd\\
+% |[#2]|: method name: |alph| (default), |wrap|, |mult|\\ % hash-ok
+% |#3|: symbols provider\\
+% |#4|: number of symbols
% \begin{macrocode}
- \def\aa@gen@callmake#1#2#3{%
- \expandafter\aa@gen@make\expandafter{\number#3}#1{#2}%
+\AlPh@IfDefinable\newalphalph{%
+ \def\newalphalph#1{%
+ \AlPh@IfOptArg{%
+ \AlPh@newalphalph{#1}%
+ }{%
+ \AlPh@newalphalph{#1}[alph]%
+ }%
}%
+}
% \end{macrocode}
% \end{macro}
-% \begin{macro}{\aa@gen@make}
-% See macro \cs{aa@make}. Argument |#3| holds the number of
-% available symbols.
+% \begin{macro}{\AlPh@newalphalph}
+% |#1|: cmd
+% |#2|: method name\\
+% |#3|: symbols provider\\
+% |#4|: number of symbols
% \begin{macrocode}
- \def\aa@gen@make#1#2#3{%
- \ifnum#1<1 %
+\def\AlPh@newalphalph#1[#2]#3#4{%
+ \begingroup\expandafter\expandafter\expandafter\endgroup
+ \expandafter\ifx\csname AlPh@Method@#2\endcsname\relax
+ \AlPh@Error{%
+ Unknown method %
+| `#2'%
++ `\detokenize{#2}'%
+ }%
+ \else
+ \ifx\\#4\\%
+ \AlPh@GetNumberOfSymbols{#3}%
+ \ifcase\AlPh@Number
+ \else
+ \begingroup
+ \escapechar=92 % backslash
+ \@PackageInfo{alphalph}{%
+ Number of symbols for \string#1 is \AlPh@Number
+ }%
+ \endgroup
+ \expandafter\AlPh@NewAlphAlph
+ \csname AlPh@Method@#2\expandafter\endcsname
+ \AlPh@Number!{#1}{#3}%
+ \fi
\else
- \@ReturnAfterFi{%
- \aa@gen@eprocess{#3}#1;#2%
- }%
+ \expandafter\AlPh@NewAlphAlph
+ \csname AlPh@Method@#2\expandafter\endcsname
+| \number#4!%
++ \the\numexpr#4!%
+ {#1}{#3}%
\fi
- }%
+ \fi
+}%
% \end{macrocode}
% \end{macro}
-% \begin{macro}{\aa@gen@eprocess}
-% See macro \cs{aa@eprocess}. Argument |#1| holds the number of
-% available symbols.
+% \begin{macro}{\AlPh@NewAlphAlph}
+% |#1|: method macro\\
+% |#2|: number of symbols\\
+% |#3|: cmd\\
+% |#4|: symbols provider
% \begin{macrocode}
- \def\aa@gen@eprocess#1#2;#3{%
- \ifnum#2>#1 %
- \@ReturnAfterElseFi{%
- \expandafter\aa@gen@eprocess\expandafter{%
- \number#1\expandafter
- }%
- \number\numexpr(#2-(\aa@half{#1}+1))/#1%
- \expandafter\expandafter\expandafter;%
- \expandafter\expandafter\expandafter#3%
- #3{\numexpr#2-((#2-(\aa@half{#1}+1))/#1)*#1\relax}%
- }%
+\def\AlPh@NewAlphAlph#1#2!#3#4{%
+ \AlPh@IfDefinable#3{%
+ \ifnum#2>0 %
+ \def#3{#1{#2}{#4}}%
\else
- \@ReturnAfterFi{%
- #3{#2}%
- }%
+ \AlPh@Error{%
+ Definition of \string#3 failed,\MessageBreak
+ because number of symbols (#2) is not positive%
+ }%
\fi
}%
+}
% \end{macrocode}
% \end{macro}
-% \begin{macro}{\aa@half}
-% Macro \cs{aa@half} implements integer division by two
-% without rounding.
+%
+% \begin{macro}{\AlphAlph}
% \begin{macrocode}
- \def\aa@half#1{%
- \number\dimexpr.5\dimexpr #1sp\relax\relax
- }%
+\newalphalph\AlphAlph\alphalph@Alph{26}
% \end{macrocode}
% \end{macro}
-% \begin{macro}{\newalphalph}
-% New macros are defined by \cs{newalphalph} that act like
-% \cs{alphalph}. The macro to be defined is |#1|. Argument |#2|
-% contains the macro that converts a number to a symbol and
-% argument |#3| holds the number of available symbols.
+% \begin{macro}{\alphalph}
% \begin{macrocode}
- \newcommand*{\newalphalph}[3]{%
- \newcommand*{#1}{}%
- \edef#1{%
- \noexpand\aa@gen@callmake\noexpand#2{\number\numexpr#3}%
- }%
- }%
+\newalphalph\alphalph\alphalph@alph{26}
% \end{macrocode}
% \end{macro}
%
-% \subsection{End\texorpdfstring{ of package}{}}
-% Now we can terminate the differentiation between \TeX\ and \eTeX.
% \begin{macrocode}
-\fi
+\AlPh@AtEnd
+%</package>
% \end{macrocode}
%
-% At the end the catcode of the character |@| is restored.
+% \section{Test}
+%
+% \subsection{Catcode checks for loading}
+%
% \begin{macrocode}
-\catcode`\@=\aa@atcode
+%<*test1>
% \end{macrocode}
% \begin{macrocode}
-%</package>
+\catcode`\@=11 %
+\def\RestoreCatcodes{}
+\count@=0 %
+\loop
+ \edef\RestoreCatcodes{%
+ \RestoreCatcodes
+ \catcode\the\count@=\the\catcode\count@\relax
+ }%
+\ifnum\count@<255 %
+ \advance\count@\@ne
+\repeat
+
+\def\RangeCatcodeInvalid#1#2{%
+ \count@=#1\relax
+ \loop
+ \catcode\count@=15 %
+ \ifnum\count@<#2\relax
+ \advance\count@\@ne
+ \repeat
+}
+\def\Test{%
+ \RangeCatcodeInvalid{0}{47}%
+ \RangeCatcodeInvalid{58}{64}%
+ \RangeCatcodeInvalid{91}{96}%
+ \RangeCatcodeInvalid{123}{255}%
+ \catcode`\@=12 %
+ \catcode`\\=0 %
+ \catcode`\{=1 %
+ \catcode`\}=2 %
+ \catcode`\#=6 %
+ \catcode`\[=12 %
+ \catcode`\]=12 %
+ \catcode`\%=14 %
+ \catcode`\ =10 %
+ \catcode13=5 %
+ \input alphalph.sty\relax
+ \RestoreCatcodes
+}
+\Test
+\csname @@end\endcsname
+\end
+% \end{macrocode}
+% \begin{macrocode}
+%</test1>
% \end{macrocode}
+%
+% \section{Macro tests}
+%
+% \begin{macrocode}
+%<*test2>
+\NeedsTeXFormat{LaTeX2e}
+\nofiles
+\documentclass{article}
+%<*noetex>
+\makeatletter
+\let\saved@numexpr\numexpr
+\newcommand*{\DisableNumexpr}{%
+ \let\numexpr\@undefined
+}
+\newcommand*{\RestoreNumexpr}{%
+ \let\numexpr\saved@numexpr
+}
+\DisableNumexpr
+%</noetex>
+\usepackage{alphalph}[2007/04/11]
+%<noetex>\RestoreNumexpr
+\usepackage{qstest}
+\IncludeTests{*}
+\LogTests{log}{*}{*}
+
+\newcommand*{\TestCmd}[3]{%
+ \setbox0=\hbox{%
+%<noetex> \DisableNumexpr
+ \edef\TestString{#1{#2}}%
+ \expandafter\Expect\expandafter{\TestString}{#3}%
+ \edef\TestString{#1{#2} }%
+ \expandafter\Expect\expandafter{\TestString}{#3 }%
+ }%
+ \Expect*{\the\wd0}{0.0pt}%
+}
+
+\makeatletter
+\newalphalph\LaTeXAlphAlph\@Alph{26}
+\newalphalph\LaTeXalphalph\@alph{26}
+\newalphalph\AlphWrap[wrap]\alphalph@Alph{26}
+\newalphalph\alphwrap[wrap]\alphalph@alph{26}
+\newalphalph\LaTeXAlphWrap[wrap]\@Alph{26}
+\newalphalph\LaTeXalphwrap[wrap]\@alph{26}
+\def\LastSymbol#1{%
+ \ifx\\#1\\%
+ \else
+ \@LastSymbol#1\@nil
+ \fi
+}
+\def\@LastSymbol#1#2\@nil{%
+ \ifx\\#2\\%
+ #1%
+ \else
+ \@LastSymbol#2\@nil
+ \fi
+}
+\makeatother
+\newcommand*{\TestAlph}[2]{%
+ \uppercase{\TestCallCmd\AlphAlph{#2}}{#1}%
+ \lowercase{\TestCallCmd\alphalph{#2}}{#1}%
+ \uppercase{\TestCallCmd\LaTeXAlphAlph{#2}}{#1}%
+ \lowercase{\TestCallCmd\LaTeXalphalph{#2}}{#1}%
+ \edef\WrapString{\LastSymbol{#2}}%
+ \expandafter\TestAlphWrap\expandafter{\WrapString}{#1}%
+}
+\newcommand*{\TestAlphWrap}[2]{%
+ \uppercase{\TestCallCmd\AlphWrap{#1}}{#2}%
+ \lowercase{\TestCallCmd\alphwrap{#1}}{#2}%
+ \uppercase{\TestCallCmd\LaTeXAlphWrap{#1}}{#2}%
+ \lowercase{\TestCallCmd\LaTeXalphwrap{#1}}{#2}%
+}
+\newcommand*{\TestCallCmd}[3]{%
+ \TestCmd#1{#3}{#2}%
+}
+\begin{qstest}{AlphSymbols}{alphalph, AlphAlph, symbols}
+ \TestAlph{1}{a}%
+ \TestAlph{2}{b}%
+ \TestAlph{3}{c}%
+ \TestAlph{4}{d}%
+ \TestAlph{5}{e}%
+ \TestAlph{6}{f}%
+ \TestAlph{7}{g}%
+ \TestAlph{8}{h}%
+ \TestAlph{9}{i}%
+ \TestAlph{10}{j}%
+ \TestAlph{11}{k}%
+ \TestAlph{12}{l}%
+ \TestAlph{13}{m}%
+ \TestAlph{14}{n}%
+ \TestAlph{15}{o}%
+ \TestAlph{16}{p}%
+ \TestAlph{17}{q}%
+ \TestAlph{18}{r}%
+ \TestAlph{19}{s}%
+ \TestAlph{20}{t}%
+ \TestAlph{21}{u}%
+ \TestAlph{22}{v}%
+ \TestAlph{23}{w}%
+ \TestAlph{24}{x}%
+ \TestAlph{25}{y}%
+ \TestAlph{26}{z}%
+\end{qstest}
+\begin{qstest}{AlphRange}{alphalph, range}
+ \TestAlph{0}{}%
+ \TestAlph{-1}{}%
+ \TestAlph{-2147483647}{}%
+ \TestAlph{27}{aa}%
+ \TestAlph{28}{ab}%
+ \TestAlph{52}{az}%
+ \TestAlph{53}{ba}%
+ \TestAlph{78}{bz}%
+ \TestAlph{79}{ca}%
+ \TestAlph{702}{zz}%
+ \TestAlph{703}{aaa}%
+ \TestAlph{2147483647}{fxshrxw}%
+\end{qstest}
+
+\makeatletter
+\newcommand*{\myvocals}[1]{%
+ \ifcase#1X\or A\or E\or I\or O\or U\else Y\fi
+}
+\makeatother
+\newalphalph\vocalsvocals\myvocals{5}
+\newcommand*{\TestVocals}{%
+ \TestCmd\vocalsvocals
+}
+\begin{qstest}{vocals}{vocals}
+ \TestVocals{0}{}%
+ \TestVocals{1}{A}%
+ \TestVocals{2}{E}%
+ \TestVocals{3}{I}%
+ \TestVocals{4}{O}%
+ \TestVocals{5}{U}%
+ \TestVocals{6}{AA}%
+ \TestVocals{7}{AE}%
+ \TestVocals{8}{AI}%
+ \TestVocals{9}{AO}%
+ \TestVocals{10}{AU}%
+ \TestVocals{11}{EA}%
+ \TestVocals{24}{OO}%
+ \TestVocals{25}{OU}%
+ \TestVocals{26}{UA}%
+ \TestVocals{29}{UO}%
+ \TestVocals{30}{UU}%
+ \TestVocals{31}{AAA}%
+ \TestVocals{155}{UUU}%
+ \TestVocals{156}{AAAA}%
+ \TestVocals{2147483647}{AIIOOEEIOIIUOE}%
+\end{qstest}
+
+\makeatletter
+\newalphalph\AlphMult[mult]{\alphalph@Alph}{26}
+\newalphalph\alphmult[mult]{\alphalph@alph}{26}
+\newalphalph\LaTeXAlphMult[mult]{\@Alph}{26}
+\newalphalph\LaTeXalphmult[mult]{\@alph}{26}
+\makeatother
+\newcommand*{\TestMult}[2]{%
+ \uppercase{\TestCallCmd\AlphMult{#2}}{#1}%
+ \lowercase{\TestCallCmd\alphmult{#2}}{#1}%
+ \uppercase{\TestCallCmd\LaTeXAlphMult{#2}}{#1}%
+ \lowercase{\TestCallCmd\LaTeXalphmult{#2}}{#1}%
+}
+\begin{qstest}{mult}{mult}
+ \TestMult{0}{}%
+ \TestMult{-1}{}%
+ \TestMult{-2147483647}{}%
+ \TestMult{1}{a}%
+ \TestMult{2}{b}%
+ \TestMult{26}{z}%
+ \TestMult{27}{aa}%
+ \TestMult{28}{bb}%
+ \TestMult{52}{zz}%
+ \TestMult{53}{aaa}%
+ \TestMult{54}{bbb}%
+ \TestMult{259}{yyyyyyyyyy}%
+ \TestMult{260}{zzzzzzzzzz}%
+ \TestMult{261}{aaaaaaaaaaa}%
+ \TestMult{262}{bbbbbbbbbbb}%
+\end{qstest}
+
+\def\myvocalsB#1{%
+ \ifcase#1\or A\or E\or I\or O\or U\fi
+}
+\begin{qstest}{symbolnum}{symbolnum}
+ \makeatletter
+ \def\Test#1#2{%
+ \let\TestCmd\relax
+ \newalphalph\TestCmd{#1}{}%
+ \Expect*{\AlPh@Number}{#2}%
+ }%
+ \Test\@alph{26}%
+ \Test\@Alph{26}%
+ \Test\@fnsymbol{9}%
+ \Test\myvocalsB{5}%
+ \Test\alphalph@alph{26}%
+ \Test\alphalph@Alph{26}%
+\end{qstest}
+
+\begin{qstest}{list}{list}
+ \makeatletter
+ \def\catch#1\relax{%
+ \def\FoundList{\catch#1}%
+ }%
+ \def\Test[#1]#2#3#4{%
+ \let\testcmd\relax
+ \newalphalph\testcmd[{#1}]{\catch}{#2}%
+ \testcmd{#3}|\relax
+ \expandafter\Expect\expandafter{\FoundList}{#4|}%
+ %
+ \let\SavedCatch\catch
+ \def\catch{\noexpand\catch\noexpand\foo}%
+ \edef\Result{#4|}%
+ \@onelevel@sanitize\Result
+ \let\catch\SavedCatch
+ \let\testcmd\relax
+ \newalphalph\testcmd[{#1}]{\catch\foo}{#2}%
+ \testcmd{#3}|\relax
+ \@onelevel@sanitize\FoundList
+ \Expect*{\FoundList}*{\Result}%
+ }%
+ \Test[alph]{26}{3}{\catch{3}}%
+ \Test[alph]{26}{12}{\catch{12}}%
+ \Test[alph]{26}{27}{\catch{1}\catch{1}}%
+ \Test[alph]{26}{78}{\catch{2}\catch{26}}%
+ \Test[wrap]{26}{7}{\catch{7}}%
+ \Test[wrap]{26}{14}{\catch{14}}%
+ \Test[wrap]{26}{80}{\catch{2}}%
+ \Test[wrap]{26}{700}{\catch{24}}%
+ \Test[mult]{26}{4}{\catch{4}}%
+ \Test[mult]{26}{17}{\catch{17}}%
+ \Test[mult]{26}{54}{\catch{2}\catch{2}\catch{2}}%
+\end{qstest}
+
+\begin{document}
+\end{document}
+%</test2>
+% \end{macrocode}
+%
% \section{Installation}
%
% \subsection{Download}
@@ -862,6 +1586,9 @@ and the derived files
% \begin{tabular}{@{}>{\ttfamily}l@{ $\rightarrow$ }>{\ttfamily}l@{}}
% alphalph.sty & tex/generic/oberdiek/alphalph.sty\\
% alphalph.pdf & doc/latex/oberdiek/alphalph.pdf\\
+% alphalph-test1.tex & doc/latex/oberdiek/alphalph-test1.tex\\
+% alphalph-test2.tex & doc/latex/oberdiek/alphalph-test2.tex\\
+% alphalph-test3.tex & doc/latex/oberdiek/alphalph-test3.tex\\
% alphalph.dtx & source/latex/oberdiek/alphalph.dtx\\
% \end{tabular}^^A
% }^^A
@@ -1034,6 +1761,15 @@ and the derived files
% \item
% Line ends sanitized.
% \end{Version}
+% \begin{Version}{2007/09/09 v2.0}
+% \item
+% New implementation that uses package \cs{intcalc}.
+% This removes the dependency on \eTeX.
+% \item
+% \cs{newalphalph} is extended to support new methods `wrap' and 'multi'.
+% \item
+% Documentation rewritten.
+% \end{Version}
% \end{History}
%
% \PrintIndex