From e0c6872cf40896c7be36b11dcc744620f10adf1d Mon Sep 17 00:00:00 2001 From: Norbert Preining Date: Mon, 2 Sep 2019 13:46:59 +0900 Subject: Initial commit --- macros/latex/contrib/sauerj/README | 65 ++ macros/latex/contrib/sauerj/collect.dtx | 815 ++++++++++++++++++ macros/latex/contrib/sauerj/collect.ins | 19 + macros/latex/contrib/sauerj/collect.pdf | Bin 0 -> 174985 bytes macros/latex/contrib/sauerj/metainfo.dtx | 1242 +++++++++++++++++++++++++++ macros/latex/contrib/sauerj/metainfo.ins | 19 + macros/latex/contrib/sauerj/metainfo.pdf | Bin 0 -> 190365 bytes macros/latex/contrib/sauerj/optparams.dtx | 327 +++++++ macros/latex/contrib/sauerj/optparams.ins | 19 + macros/latex/contrib/sauerj/optparams.pdf | Bin 0 -> 141610 bytes macros/latex/contrib/sauerj/parcolumns.dtx | 1090 +++++++++++++++++++++++ macros/latex/contrib/sauerj/parcolumns.ins | 19 + macros/latex/contrib/sauerj/parcolumns.pdf | Bin 0 -> 198902 bytes macros/latex/contrib/sauerj/processkv.dtx | 199 +++++ macros/latex/contrib/sauerj/processkv.ins | 19 + macros/latex/contrib/sauerj/processkv.pdf | Bin 0 -> 126376 bytes macros/latex/contrib/sauerj/zahl2string.dtx | 1044 ++++++++++++++++++++++ macros/latex/contrib/sauerj/zahl2string.ins | 19 + macros/latex/contrib/sauerj/zahl2string.pdf | Bin 0 -> 199022 bytes 19 files changed, 4896 insertions(+) create mode 100644 macros/latex/contrib/sauerj/README create mode 100644 macros/latex/contrib/sauerj/collect.dtx create mode 100644 macros/latex/contrib/sauerj/collect.ins create mode 100644 macros/latex/contrib/sauerj/collect.pdf create mode 100644 macros/latex/contrib/sauerj/metainfo.dtx create mode 100644 macros/latex/contrib/sauerj/metainfo.ins create mode 100644 macros/latex/contrib/sauerj/metainfo.pdf create mode 100644 macros/latex/contrib/sauerj/optparams.dtx create mode 100644 macros/latex/contrib/sauerj/optparams.ins create mode 100644 macros/latex/contrib/sauerj/optparams.pdf create mode 100644 macros/latex/contrib/sauerj/parcolumns.dtx create mode 100644 macros/latex/contrib/sauerj/parcolumns.ins create mode 100644 macros/latex/contrib/sauerj/parcolumns.pdf create mode 100644 macros/latex/contrib/sauerj/processkv.dtx create mode 100644 macros/latex/contrib/sauerj/processkv.ins create mode 100644 macros/latex/contrib/sauerj/processkv.pdf create mode 100644 macros/latex/contrib/sauerj/zahl2string.dtx create mode 100644 macros/latex/contrib/sauerj/zahl2string.ins create mode 100644 macros/latex/contrib/sauerj/zahl2string.pdf (limited to 'macros/latex/contrib/sauerj') diff --git a/macros/latex/contrib/sauerj/README b/macros/latex/contrib/sauerj/README new file mode 100644 index 0000000000..31b87d15f6 --- /dev/null +++ b/macros/latex/contrib/sauerj/README @@ -0,0 +1,65 @@ +README +------ + +These are a few LaTeX2e-packages for a variety of tasks: + +- collect provides several environment to collect text in a macro + or a file for later use. + + Current version: 0.9 + + +- metainfo provides a macro for only typesetting specially formatted + comments of a document. + + Current version: 0.9.1 + + +- optparams provides a small macro for creating macros with multiple + optional parameters. + + Current version: 0.9 + + +- parcolumns provides an environment for typesetting text in two or + more columns in parallel. + + Requires the processkv-package (below). + + Current version: 1.2 + + +- processkv provides macros for processing of key-value-lists by + calling a user-defined macro for each key-value-pair. + + Requires the keyval-package dated 1999/03/16 or later. + + Current version: 1.0.1 + + +- zahl2string provides macros for formatting numbers as german words, + i.e. `1' gets formatted as `eins'. + + Current version: 1.2.1 + + +Each package consists of an .ins-file containing the driver for +installation, a .dtx-file containing the macros and documentation and +a .pdf containing the typeset documentation. + +To install, run LaTeX on the .ins-file, then copy the resulting +.sty-file somewhere LaTeX can find it. To typeset the documentation, +run LaTeX on the .dtx-file, run MakeIndex using gind.ist as the index +style file and then run LaTeX again. + + + +All packages may be distributed and/or modified under the conditions +of the LaTeX Project Public License (lppl), 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. diff --git a/macros/latex/contrib/sauerj/collect.dtx b/macros/latex/contrib/sauerj/collect.dtx new file mode 100644 index 0000000000..05a8f50c76 --- /dev/null +++ b/macros/latex/contrib/sauerj/collect.dtx @@ -0,0 +1,815 @@ +% \iffalse meta-comment +% Line endings: UNIX +% Tab size: 4 +% +% Copyright 2004 Jonathan Sauer +% +% This work 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 Jonathan Sauer +% (). +% +% This work consists of the files collect.dtx and collect.ins +% and the derived file collect.sty. +% +% \fi +% +% \iffalse +% +%<*driver> +\documentclass{ltxdoc} +\usepackage{collect} +\EnableCrossrefs +\CodelineIndex +\RecordChanges +% Modification of verbatim for tabs in listings +\makeatletter +{\catcode`\ =\active% +\catcode`\^^I=\active% +\gdef\@vobeyspaces{% +\catcode`\ \active\let \@xobeysp% +\catcode`\^^I\active\def^^I{~~}% +}}% +\makeatother +\begin{document} + \DocInput{\jobname.dtx} +\end{document} +% +% +%\NeedsTeXFormat{LaTeX2e} +%\ProvidesPackage{collect} +% [2004/09/12 v0.9 collect the contents of an environment] +% +% \fi +% +% \CheckSum{256} +% \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 \~} +% +% +% \DoNotIndex{\@currenvir,\@ehc,\@ifundefined,\@input} +% \DoNotIndex{\@tempa,\@tempb,\bgroup,\catcode,\closeout,\csname} +% \DoNotIndex{\def,\edef,\egroup,\else,\end,\endcsname,\expandafter} +% \DoNotIndex{\fi,\futurelet,\gdef,\global,\ifx,\immediate,\jobname,\let,\long} +% \DoNotIndex{\meaning,\newcommand,\newenvironment,\newif,\newwrite} +% \DoNotIndex{\openout,\PackageError,\par,\strip@prefix,\the,\toks@} +% \DoNotIndex{\write} +% +% \GetFileInfo{\jobname.sty} +% +% \title{The \textsf{collect} package\thanks{This document +% corresponds to \textsf{\filename}~\fileversion, dated \filedate.}} +% +% \author{Jonathan Sauer \\ \texttt{jonathan.sauer@gmx.de}} +% +% \date{\filedate} +% +% \maketitle +% +% \begin{abstract} +% This file describes the \textsf{collect} package that +% makes it possible to collect text for later use. +% +% \end{abstract} +% +% \tableofcontents +% +% \section{Introduction} +% +% Suppose you are writing the specification of a programming language. +% Then you will surely insert definitions of the grammar (i.e. using +% the \textsf{syntax} package). Most likely you will insert the +% grammar for i.e. loops, conditions et cetera in the appropriate +% chapter, but for easy implementation of a parser, you will want to +% include the complete grammar as an appendix, so that one does not +% have to collect the complete grammar from the bits in each chapter. +% +% Of course you could do this by hand using the copy-and-paste +% facility of your text editor. But this is cumbersome and errorprone +% if you modify the grammar afterwards, i.e. for a second version. +% +% This package provides the |collect| environment that typesets +% its contents and collects it for later use as well. +% +% In other situations you will want to save the contents of an +% environment in a macro. Then the |collectinmacro| environment +% should do the trick. +% +% +% +% \section{Usage} +% +% \paragraph{General note} If an environment exists in a normal and a +% starred form (i.e. |collect| and |collect*|), then the former does +% not typeset the environment contents, while the latter typesets it. +% Note, too, that the normal and the starred version of an environment +% often have a different number of parameters. +% +% \paragraph{Stripping of spaces} All environments strip any leading +% space before the start of the text and any trailing space after the +% end of the text. Trailing |\par|s (i.e. resulting from a blank line +% at the end of the environment) are \emph{not} removed. +% +% +% +% +% \subsection{\texttt{collect}} +% +% You can define several \emph{collections}. Each collection can be +% used independently to collect text across the document. You define a +% collection using |\definecollection|, use it in the |collect| and +% |collect*| environment and typeset it using |\includecollection|. +% +% \paragraph{Note} The name of the collection is used as the suffix of +% the file that stores the collection (the complete name is +% \meta{jobname}|.|\meta{name)}. So you should not name a collection +% |tex|, |log|, |dvi|, |pdf| and so on. +% +% \paragraph{Note} You can only include a collection after completely +% collecting it. If you include it and continue to collect afterwards, +% the collection will be cleared after its inclusion. +% +% This can be used to recycle a collection: Use it in the first part +% of your document to collect text, typeset this text using +% |\includecollection| and then reuse the collection in the second +% part of your document to collect new text which will finally be +% typeset using |\includecollection| a second time. +% +% +% \DescribeMacro{\definecollection} Usage: |\definecollection| +% \marg{name}. +% +% Defines a collection of the name \meta{name}. +% +% +% \DescribeEnv{collect*} Usage: |\begin{collect*}| +% \marg{name} \marg{before} \marg{after} \marg{beforecol} +% \marg{aftercol} \ldots\ |\end{collect*}|. +% +% Collects the text inside the environment in the collection +% \meta{name}. Then typesets the text. \meta{name} must have been +% defined using |\definecollection|. +% +% \meta{before} and \meta{after} are tokens inserted before and after +% the environment contents in the collection as well as the typeset +% text. +% +% \meta{beforecol} and \meta{aftercol} are tokens inserted before and +% after the environment contents only in the collection. This can be +% used to insert a section heading (\meta{beforecol}) and a backref to +% the section where the text has been collected (\meta{aftercol}). +% +% \paragraph{Note} The |collect*| environment uses a temporary file +% \meta{jobname}|.tmp| to temporarily store the environment contents +% and include it afterwards.\footnote{This way, catcode changes inside +% the environment are honored.} +% +% +% \DescribeEnv{collect} Usage: |\begin{collect}| \marg{name} +% \marg{beforecol} \marg{aftercol} \ldots\ |\end{collect}|. +% +% Collects the text inside the environment in the collection +% \meta{name}. \emph{Does not} typeset the text (therefore, the two +% parameters \meta{before} and \meta{after} are missing); except for +% that, this environment is identical to |collect*|. +% +% +% \DescribeMacro{\includecollection} Usage: |\includecollection| +% \marg{name}. Includes the collection \meta{name}. Afterwards, the +% collection is reset. +% +% You can include the collection \emph{before} it is actually +% collected in the same way you can include a table of contents at the +% beginning of your document. Simply say |\includecollection| and then +% use the |collect*| or |collect| environment to collect text. Then +% run \LaTeX\ on your file \emph{twice}. (the first time to collect +% the text, the second time to put it in the document using +% |\includecollection|) +% +% +% +% \subsection{Other environments} +% +% \DescribeEnv{collectinmacro} Usage: |\begin{collectinmacro}| +% \marg{macro} \marg{before} \marg{after} \ldots\ +% |\end{collectinmacro}|. +% +% Collects the contents of an environment inside a macro \meta{macro} +% without typesetting it. If \meta{macro} has been defined prior to +% using this environment, its previous meaning is lost. The new +% definition is global. +% +% \meta{before} and \meta{after} are tokens inserted before and after +% the environment contents in the macro. +% +% \paragraph{Important note} This environment differs slightly from +% |collect| and |collect*|: Some macros, i.e. |\verb|, do not work +% correctly when \meta{macro} is used later on.\footnote{As the +% catcodes have already been set when collecting the contents and +% cannot be changed afterwards, at least not without e\TeX.} +% +% +% +% +% \section{Examples} +% +% \subsection{\texttt{collect}} +% +% \begin{verbatim} +% \begin{collect*}{tst}{Before\par}{\par After}{Before file\par}{\par After file} +% This is a test +% \end{collect*} +% \end{verbatim} +% +% \noindent This results in the following text typeset directly: +% +% \begin{verbatim} +% Before +% This is a test +% After +% \end{verbatim} +% +% \noindent And following text is typeset when the collection |tst| is +% included using |\includecollection{tst}|: +% +% \begin{verbatim} +% Before file +% Before +% This is a test +% After +% After file +% \end{verbatim} +% +% +% +% +% \subsection{Other environments} +% +% \begin{verbatim} +% \begin{collectinmacro}{\collectedtext}{Before\par}{\par After} +% This is a test +% \end{collectinmacro} +% \end{verbatim} +% +% \noindent This results in no text typeset directly and the following +% text stored in the macro |\collectedtext|: +% +% \begin{verbatim} +% Before\par This is a test\par After +% \end{verbatim} +% +% +% +% +% \section{Creating your own environment} +% +% You can create your own environment based on any of the environments +% in this package, i.e. to create a |grammarpart| environment to +% typeset part of a grammar. +% +% You can for example say: +% +% \begin{verbatim} +% \definecollection{gra} +% +% \newenvironment{grammarpart}[1]{% +% \@nameuse{collect*}{gra}{% +% \emph{Start of grammar `#1'}\par% +% }{% +% \par\emph{End of grammar}\par% +% }{% +% \subsection{#1}% +% }{% +% \par See some section in the text. +% }% +% }{% +% \@nameuse{endcollect*}% +% } +% \end{verbatim} +% +% \noindent This will create a |grammarpart| environment with one +% parameter, the part of the grammar defined. (i.e. `Identifiers') At +% the start of the environment the text `\emph{Start of grammar +% \meta{part}}' will be typeset, followed by the grammar (the contents +% of the environment), and finally a line `\emph{End of grammar}' will +% be added. +% +% When including the collected grammar parts using +% |\includecollection| each grammar part will be prefixed by a +% subsection heading bearing the grammar part as its title and +% suffixed by `See some section in the text.' (this could be extended +% to include a backref using |\ref|\meta{label}) +% +% \paragraph{Note} If you use any of the environments inside a custom +% environment to afterwards collect text with this custom environment +% (as in the example of the |grammarpart| environment above), you +% \emph{must not} begin and end it using |\begin| and |\end|, or the +% environment contents will not be collected correctly. You must use +% |\@nameuse{|\meta{environment}|}| and +% |\@nameuse{end|\meta{environment}|}| as in the example above, or, if +% the environment is not starred, |\|\meta{environment} and +% |\end|\meta{environment}. +% +% \paragraph{Note} You still can use the environments of this package +% inside other environments (i.e. a |itemize| environment) without any +% problems. +% +% +% +% +% \section{Notes} +% +% \begin{itemize} +% \item If you use any of the environments inside your own +% environment, note that the end of the environment is +% executed, but not included in the collected text! (that's +% why the the environments |collect*| and |collectinmacro| +% have two parameters for including text before and after +% the environment, \meta{before} and \meta{after}). +% +% \end{itemize} +% +% +% +% +% \StopEventually{} +% +% \section{Implementation} +% +% \subsection{Main environments and macros} +% +% \subsubsection{\texttt{collect}} +% +% \begin{macro}{\definecollection} +% +% Usage: |\definecollection| \marg{name} +% +% Defines a collection \meta{name}. +% +% This macro allocates a |\newwrite| |CE@@|\meta{name}|@out| and +% defines a |\newif| |CE@@|\meta{name}|open|. +% +% \begin{macrocode} +\newcommand{\definecollection}[1]{% + \@ifundefined{CE@@#1@out}{% + \expandafter\newwrite\csname CE@@#1@out\endcsname% + \expandafter\newif\csname ifCE@@#1@open\endcsname% + \csname CE@@#1@openfalse\endcsname% + }{% + \PackageError{collect}{Collection `#1' has already % + been defined}{\@ehc}% + }% +} +% \end{macrocode} +% \end{macro} +% +% +% \begin{environment}{collect*} +% +% Usage: |\begin{collect*}| \marg{name} \marg{before} +% \marg{after} \marg{beforecol} \marg{aftercol} \ldots\ +% |\end{collect*}|. +% +% \begin{macrocode} +\newenvironment{collect*}[5]{% + \global\toks@{}% + \def\CE@file{#1}% + \def\CE@preenv{#2}% + \def\CE@postenv{#3}% + \def\CE@prefileenv{#4}% + \def\CE@postfileenv{#5}% + \CE@get@env@body@start% +}{% +% \end{macrocode} +% +% What are we doing? We make sure the collection is open, then we save +% \meta{beforecol}, \meta{before}, the collected environment contents, +% \meta{after} and \meta{aftercol} in the collection file. +% +% \begin{macrocode} + \CE@ensure@opened{\CE@file}% + \edef\@tempa{\csname CE@@\CE@file @out\endcsname}% + \immediate\write\@tempa{\CE@meaning\CE@prefileenv}% + \immediate\write\@tempa{\CE@meaning\CE@preenv}% + \immediate\write\@tempa{\the\toks@}% + \immediate\write\@tempa{\CE@meaning\CE@postenv}% + \immediate\write\@tempa{\CE@meaning\CE@postfileenv}% +% \end{macrocode} +% +% Now we repeat the same thing, but with the temporary file and +% writing only \meta{before}, the collected environment contents and +% \meta{after}. Then we include the temporary file. +% +% Why so complicated, as we have the contents of the environment in +% |\toks@|? Because the catcodes might not be correct, i.e. if |\verb| +% is used inside the environment. So we have to read the environment +% contents again, which without e\TeX\ is only possible using a +% temporary file. +% +% \begin{macrocode} + \immediate\openout\CE@tmp@out=\jobname.tmp% + \immediate\write\CE@tmp@out{\CE@meaning\CE@preenv}% + \immediate\write\CE@tmp@out{\the\toks@}% + \immediate\write\CE@tmp@out{\CE@meaning\CE@postenv}% + \immediate\closeout\CE@tmp@out% + \@input{\jobname.tmp}% + \par% +} +% \end{macrocode} +% \end{environment} +% +% +% \begin{environment}{collect} +% +% Usage: |\begin{collect}| \marg{name} \marg{beforecol} +% \marg{aftercol} \ldots\ |\end{collect}|. +% +% \begin{macrocode} +\newenvironment{collect}[3]{% + \global\toks@{}% + \def\CE@file{#1}% + \def\CE@prefileenv{#2}% + \def\CE@postfileenv{#3}% + \CE@get@env@body@start% +}{% +% \end{macrocode} +% +% As this environment, contrary to |collect*|, does not typeset its +% contents, we only write to the collection file: +% +% \begin{macrocode} + \CE@ensure@opened{\CE@file}% + \edef\@tempa{\csname CE@@\CE@file @out\endcsname}% + \immediate\write\@tempa{\CE@meaning\CE@prefileenv}% + \immediate\write\@tempa{\the\toks@}% + \immediate\write\@tempa{\CE@meaning\CE@postfileenv}% +} +% \end{macrocode} +% \end{environment} +% +% +% \begin{macro}{\includecollection} +% +% Usage: |\includecollection| \marg{name}. +% +% Includes the collection \meta{name} which must have been defined +% previously using |\definecollection|. Afterwards, the collection is +% cleared. +% +% \begin{macrocode} +\newcommand{\includecollection}[1]{% + \CE@ensure@closed{#1}% + \@input{\jobname.#1}% +} +% \end{macrocode} +% \end{macro} +% +% +% +% \subsubsection{Other environments} +% +% \begin{environment}{collectinmacro} +% +% Usage: |\begin{collectinmacro}| \marg{macro} \marg{before} +% \marg{after} \ldots\ |\end{collectinmacro}|. +% +% Collects the contents of an environment inside a macro. +% +% \begin{macrocode} +\newenvironment{collectinmacro}[3]{% + \def\CE@destmacro{#1}% + \def\CE@postenv{#3}% +% \end{macrocode} +% +% We initialize the result with \meta{before}: +% +% \begin{macrocode} + \toks@{#2}% + \CE@get@env@body@start% +}{% +% \end{macrocode} +% +% We add \meta{after}: +% +% \begin{macrocode} + \toks@\expandafter\expandafter\expandafter{% + \expandafter\the\expandafter\toks@\CE@postenv}% +% \end{macrocode} +% +% Finally we globally define \meta{macro} to contain the collected +% contents: +% +% \begin{macrocode} + \expandafter\expandafter\expandafter% + \gdef\expandafter\CE@destmacro\expandafter{\the\toks@}% + \toks@{}% +} +% \end{macrocode} +% \end{environment} +% +% +% +% +% \subsection{Internal environments and macros} +% +% We allocate a new |\newwrite| for the processing of a temporary +% file: +% +% \begin{macrocode} +\newwrite\CE@tmp@out +% \end{macrocode} +% +% +% \begin{macro}{\CE@get@env@body@start} +% +% Starts the collecting of the contents of an environment. (the +% environment starts immediately after the macro) +% +% \begin{macrocode} +\def\CE@get@env@body@start{% + \let\@tempa\CE@get@env@body% +% \end{macrocode} +% +% We may have to gobble leading spaces, therefore we check the first +% character in the environment: +% +% \begin{macrocode} + \futurelet\@tempb\CE@get@env@body@start@% +} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\CE@get@env@body@start@} +% +% Support macro for |\CE@get@env@body@start|. Checks if the next token +% is a space, then calls |\CE@get@env@body@start@@|. Otherwise, the +% collecting of the environment contents is started. +% +% \begin{macrocode} +\def\CE@get@env@body@start@{% +% \end{macrocode} +% +% |\@sptoken| contains a single space and is defined in +% \textsf{ltdefns.dtx}: +% +% \begin{macrocode} + \ifx\@tempb\@sptoken% + \expandafter\CE@get@env@body@start@@% + \else% + \expandafter\CE@get@env@body% + \fi% +} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\CE@get@env@body@start@@} +% +% Support macro for |\CE@get@env@body@start@|. Gobbles up any space +% following the macro, then start the collecting of the environment +% contents using |\CE@get@env@body|. +% +% \begin{macrocode} +\def\CE@get@env@body@start@@{% + \afterassignment\CE@get@env@body% + \let\@tempb= % +} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\CE@get@env@body} +% +% Usage: |\CE@get@env@body| \marg{body} |\end| \marg{envname}. +% +% To ensure proper initialization, this macro should not be called +% directly; instead |\CE@get@env@body@start| should be called. +% +% First we change the catcode of |Q| to 3 (math switch) in order to +% have a really unique character for parameter matching later +% on.\footnote{Taken from `Around the bend 15'} We do this in a group +% in order to easily restore the catcode later on and make all macro +% definitions global: +% +% \begin{macrocode} +\bgroup +\catcode`\Q=3 +% \end{macrocode} +% +% Now we begin the macro: +% +% \begin{macrocode} +\long\gdef\CE@get@env@body#1\end#2{% +% \end{macrocode} +% +% Right at the beginning of the macro, we are at an |\end| (and |#1| +% contains the contents prior to it). We check if it ends the current +% environment (|#2| contains the name of the environment ended): +% +% \begin{macrocode} + \def\@tempb{#2}% + \ifx\@tempb\@currenvir% +% \end{macrocode} +% +% \paragraph{Yes, it ends the current environment.} We add the +% contents to |\toks@| and are done. But we do not add the contents +% directly as there may be a trailing space left (multiple spaces have +% been collapsed into one space by \TeX). So we call +% |\CE@get@env@body@| using delimited parameters (note that |Q| has +% catcode 3, therefore a normal |Q| is not matched). +% +% What exactly is going on here? Suppose we have the text +% +% \begin{verbatim} +% Hello World_ +% \end{verbatim} +% % +% \noindent (the |_| denotes the trailing space). Then +% |\CE@get@env@body@| is called like this: +% +% \begin{verbatim} +% \CE@get@env@body@Hello World Q Q +% \end{verbatim} +% % +% \noindent |\CE@get@env@body@| matches the parameters like this: |#1| +% is `Hello World'; leaving |_Q| (added by the call from +% |\CE@get@env@body|) in the input. |\CE@get@env@body@| then calls +% |\CE@get@env@body@@| using |#1| and |Q|, resulting in the call: +% +% \begin{verbatim} +% \CE@get@env@body@@Hello WorldQ Q +% \end{verbatim} +% % +% \noindent |\CE@get@env@body@@| matches its parameter like this: |#1| +% is `Hello World' again, and |#2| is the second |Q|. +% +% But what happened to the space between the two |Q|s? As |#2| is not +% a delimited parameter, \TeX\ skips spaces after matching the first +% |Q| until it reaches the second |Q|, thus gobbling up the space +% inbetween.\footnote{c.f. \TeX book chapter 20.} +% +% \addvspace{\baselineskip}\noindent Now suppose we have the text +% \begin{verbatim} +% Hello World +% \end{verbatim} +% % +% \noindent without any trailing space. Then |\CE@get@env@body@| is +% called like this: +% +% \begin{verbatim} +% \CE@get@env@body@Hello WorldQ Q +% \end{verbatim} +% % +% \noindent |\CE@get@env@body@| matches its parameters like this: |#1| +% is `Hello WorldQ'. |\CE@get@env@body@| then calls +% |\CE@get@env@body@@| using |#1| and |Q|, resulting in the call: +% +% \begin{verbatim} +% \CE@get@env@body@@Hello WorldQQ +% \end{verbatim} +% % +% \noindent |\CE@get@env@body@@| matches its parameter like this: |#1| +% is `Hello World' without the trailing `Q', and |#2| is the second +% |Q|. The only difference to the situation described above is the +% missing space between the two |Q|s. +% +% Remember that the `Q' is always `Q' with catcode 3, thus no `Q' in +% the environment contents is matched. +% +% \begin{macrocode} + \CE@get@env@body@#1Q Q% + \def\@tempa{\end{#2}}% + \else +% \end{macrocode} +% +% \paragraph{No, it ends another environment.} We add the contents as +% well as the |\end|\meta{environment} to |\toks@|. Then we continue +% collecting: +% +% \begin{macrocode} + \toks@\expandafter{\the\toks@#1\end{#2}}% + \fi% + \@tempa% +} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\CE@get@env@body@} +% +% Support macro for |\CE@get@env@body|. See |\CE@get@env@body| for +% explanations. +% +% \begin{macrocode} +\long\gdef\CE@get@env@body@#1 Q{% + \CE@get@env@body@@#1Q% +} +% \end{macrocode} +% \end{macro} +% + +% \begin{macro}{\CE@get@env@body@@} +% +% Support macro for |\CE@get@env@body@|. See |\CE@get@env@body| for +% explanations. +% +% \begin{macrocode} +\long\gdef\CE@get@env@body@@#1Q#2{% + \toks@\expandafter{\the\toks@#1}% +} +% \end{macrocode} +% \end{macro} +% +% Finally we end the group, thus restoring the catcode of |Q|: +% +% \begin{macrocode} +\egroup +% \end{macrocode} +% +% +% \begin{macro}{\CE@meaning} +% +% Usage: |\CE@meaning| \marg{macro}. +% +% Expands to the meaning of \meta{macro}. +% +% \begin{macrocode} +\long\def\CE@meaning#1{% + \expandafter\strip@prefix\meaning#1% +} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\CE@ensure@opened} +% +% Usage: |\CE@ensure@opened| \marg{name}. +% +% Ensures that the file for collection \meta{name} is opened. +% +% \begin{macrocode} +\def\CE@ensure@opened#1{% + \@ifundefined{ifCE@@#1@open}{% + \PackageError{collect}{Collection `#1' has not been defined}{\@ehc}% + }{% + \csname ifCE@@#1@open\endcsname\else% + \expandafter\immediate\expandafter\openout% + \csname CE@@#1@out\endcsname=\jobname.#1% + \expandafter\global\csname CE@@#1@opentrue\endcsname% + \fi% + }% +} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\CE@ensure@closed} +% +% Usage: |\CE@ensure@closed| \marg{name}. +% +% Ensures that the file for collection \meta{name} is closed. +% +% \begin{macrocode} +\def\CE@ensure@closed#1{% + \@ifundefined{ifCE@@#1@open}{% + \PackageError{collect}{Collection `#1' has not been defined}{\@ehc}% + }{% + \csname ifCE@@#1@open\endcsname% + \expandafter\immediate\expandafter\closeout% + \csname CE@@#1@out\endcsname% + \expandafter\global\csname CE@@#1@openfalse\endcsname% + \fi% + }% +} +% \end{macrocode} +% \end{macro} +% +% +% \Finale +% \PrintChanges +% \PrintIndex +\endinput \ No newline at end of file diff --git a/macros/latex/contrib/sauerj/collect.ins b/macros/latex/contrib/sauerj/collect.ins new file mode 100644 index 0000000000..a03684bd8a --- /dev/null +++ b/macros/latex/contrib/sauerj/collect.ins @@ -0,0 +1,19 @@ +\input docstrip +\keepsilent +\askforoverwritefalse + +\preamble +\endpreamble +\generate{% + \file{\jobname.sty}{\from{\jobname.dtx}{package}} +} + +\Msg{***************************************************************} +\Msg{*} +\Msg{* \space To finish the installation you have to copy the files} +\Msg{*} +\Msg{* \space *.sty into a directory searched by TeX} +\Msg{*} +\Msg{***************************************************************} + +\endbatchfile \ No newline at end of file diff --git a/macros/latex/contrib/sauerj/collect.pdf b/macros/latex/contrib/sauerj/collect.pdf new file mode 100644 index 0000000000..e812f19e0f Binary files /dev/null and b/macros/latex/contrib/sauerj/collect.pdf differ diff --git a/macros/latex/contrib/sauerj/metainfo.dtx b/macros/latex/contrib/sauerj/metainfo.dtx new file mode 100644 index 0000000000..b4941dbffd --- /dev/null +++ b/macros/latex/contrib/sauerj/metainfo.dtx @@ -0,0 +1,1242 @@ +% \iffalse meta-comment +% Line endings: UNIX +% Tab size: 4 +% +% Copyright 2004 Jonathan Sauer +% +% This work 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 Jonathan Sauer +% (). +% +% This work consists of the files metainfo.dtx and metainfo.ins +% and the derived file metainfo.sty. +% +% \fi +% +% \iffalse +% +%<*driver> +\documentclass{ltxdoc} +\usepackage{metainfo} +\EnableCrossrefs +\CodelineIndex +\RecordChanges +% Modification of verbatim for tabs in listings +\makeatletter +{\catcode`\ =\active% +\catcode`\^^I=\active% +\gdef\@vobeyspaces{% +\catcode`\ \active\let \@xobeysp% +\catcode`\^^I\active\def^^I{~~}% +}}% +\makeatother +\begin{document} + \DocInput{\jobname.dtx} +\end{document} +% +% +%\NeedsTeXFormat{LaTeX2e} +%\ProvidesPackage{metainfo} +% [2004/11/25 v0.9.1 typeset document metainfo] +% +% \fi +% +% \CheckSum{386} +% \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 \~} +% +% \DoNotIndex{\@@input,\|} +% \DoNotIndex{\@ifundefined,\@ehc,\@empty,\@gobbletwo,\@nil} +% \DoNotIndex{\@startsection,\@tempa,\active,\baselineskip} +% \DoNotIndex{\begin,\bfseries,\bgroup,\catcode,\DeclareOption} +% \DoNotIndex{\def,\egroup,\else,\end,\endinput,\expandafter} +% \DoNotIndex{\fi,\futurelet,\gdef,\ifmmode,\ifcat,\ifx} +% \DoNotIndex{\index,\item,\let,\long,\newcommand,\newif} +% \DoNotIndex{\noexpand,\noindent,\normalfont,\normalsize} +% \DoNotIndex{\PackageError,\par,\ProcessOptions,\relax,\space} +% \DoNotIndex{\string,\textbf,\z@} +% +% \GetFileInfo{\jobname.sty} +% +% \title{The \textsf{metainfo} package\thanks{This document +% corresponds to \textsf{\filename}~\fileversion, dated \filedate.}} +% +% \author{Jonathan Sauer \\ \texttt{jonathan.sauer@gmx.de}} +% +% \date{\filedate} +% +% \maketitle +% +% \begin{abstract} +% This file describes the \textsf{metainfo} package that typesets only +% special comments of a \TeX\ file. +% +% \end{abstract} +% +% \tableofcontents +% +% \section{Introduction} +% +% Suppose you write a text and include some annotations for yourself +% that are not printed, i.e. an explanation of a pun or a short +% summary of the current chapter in order to be able to later create a +% summary of the whole text. Then it would be nice to be able to +% extract these annotations and typeset them separately. This package +% provides the macro |\typesetmetainfo| to typeset only these +% annotations (herein called `metainfo', as they are information about +% the information contained in the text). +% +% +% +% +% \section{Macros} +% +% \DescribeMacro{\typesetmetainfo} Usage: |\typesetmetainfo| +% \marg{file}. +% +% Typesets the metainfo of the \TeX\ file \meta{file}. Anything not a +% metainfo---text, preamble---is skipped. +% +% +% +% +% \section{Formatting} +% +% \subsection{Metainfo after a heading} +% +% Any comments following a line with a heading are considered a +% metainfo and are typeset as if they were normal text. The first line +% that does not begin with a percent sign finishes the metainfo. +% +% A heading is started by a macro defined in |\\mi@@MIbeginnings|. +% Normally this macro contains |\chapter|, |\section|, |\subsection|, +% and |\subsubsection|, but you can of course redefine it. +% +% The heading itself is typeset as well, before the metainfo, +% resulting all metainfo being typeset using the outline of the normal +% document. Note that when writing a heading, some restriction apply: +% +% \begin{enumerate} +% \item The heading macro must be at the beginning of the line. +% +% \item Any parameters of the macro must be on the same line. +% (parameters split over several lines might work, but they +% are not guaranteed to) +% +% \end{enumerate} +% +% +% +% +% \subsection{Local metainfo} +% +% There is another way to include metainfo in a document, that is as a +% \emph{local metainfo}. A local metainfo is a metainfo not following +% a heading; instead they can appear anywhere in the text. They start +% with a double percent sign at the beginning of the line (|%%|); the +% line itself is then typeset as a metainfo as well as all the +% following lines beginning with a |%| (just as a metainfo following a +% heading). The first line that does not begin with a percent sign +% finishes the local metainfo. +% +% You can format a local metainfo using three macros. (see section +% \ref{sec:ExLoMI} on page \pageref{sec:ExLoMI} for an example how to +% customize them.) +% +% \begin{enumerate} +% \item |\mi@@firstlocalMItext|: The contents of this macro is +% inserted before the first local metainfo of a chapter. +% +% \item |\mi@@lastlocalMItext|: The contents of this macro is +% inserted after the last local metainfo of a chapter. +% +% \item |\mi@@everylocalMItext|: The contents of this macro is +% inserted before every local metainfo. +% +% \end{enumerate} +% +% \paragraph{Note} If you change these macros in your document +% preamble or your main document opposed to a package file, you must +% surround them with |\makeatletter| and |\makeatother|, as shown in +% the example below. +% +% +% +% +% \section{Package options}\label{sec:Options} +% +% The following package options exist: +% +% \begin{description} +% \item[compactheadings] Changes the section headings to be more +% compact in order to save some space. +% +% \item[indexshorthand] Provides shorthands for indexing. +% |^|\marg{text} indexes and typesets \meta{text}, |^^|\marg{text} +% only indexes it.\footnote{These shorthands have been inspired by +% Donald E. Knuth's own index macros used for the \TeX book.} +% For indexing, the standard index macro |\index| is used. +% +% These macros only work in text mode; in math mode, |^| is a +% superscript as predefined in \LaTeX. +% +% \item[listlocalmetainfo] Changes the macros |\mi@@firstlocalMItext|, +% |\mi@@lastlocalMItext| and |\mi@@everylocalMItext| (described in +% the section above) to |itemize| the local metainfo. +% \end{description} +% +% +% +% +% \section{Driver files} +% +% In order to typeset only the metainfo of a document, a special +% driver file is needed. This driver loads the packages necessary for +% typesetting the metainfo (at least the package \textsf{metainfo}) +% and inputs the document to be typeset using |\typesetmetainfo|. +% +% \paragraph{Note} No package of the document processed using +% |\typesetmetainfo| is loaded, as the |\usepackage| macros are +% skipped. The same is true for any definitions in the document +% preamble or elsewhere: They are skipped, so if the metainfo relies +% on these definitions, they have to be included in the driver as +% well. +% +% +% +% +% \section{Examples} +% +% \subsection{Example driver file} +% +% The following driver file typesets the metainfo of the \TeX\ file +% `example.tex' using compact headings: +% +% \begin{verbatim} +% \documentclass{book} +% \usepackage[compactheadings]{metainfo} +% +% \begin{document} +% \typesetmetainfo{example} +% \end{document} +% \end{verbatim} +% +% +% +% +% \subsection{Example document} +% +% If we save the following file as `example.tex' and process it using +% the driver file in the example above \ldots +% +% \begin{verbatim} +% \documentclass{minimal} +% \usepackage{testpackage} +% +% \begin{document} +% +% \chapter{Chapter 1} +% % Metainfo for chapter `Chapter 1' +% +% \section{Section 1} +% % Metainfo for section `Section 1' +% +% This is some text. +% +% \chapter{Chapter 2} +% \section{Section 2} +% % Metainfo for section `Section 2' +% +% This is some more text. +% +% %% Local metainfo. This metainfo is a bit longer, but only +% % a little bit. +% +% \section{Section 3} +% % Metainfo for section `Section 3' +% \end{document} +% \end{verbatim} +% +% \ldots\ this results in:\footnote{Approximately, as the real +% formatting will differ slightly from the text typeset here.} +% +% \addvspace{\baselineskip} +% \textbf{Chapter 1}\par +% Metainfo for chapter `Chapter 1' +% +% \addvspace{\baselineskip} +% \textbf{Section 1}\par +% Metainfo for section `Section 1' +% +% \addvspace{\baselineskip} +% \textbf{Chapter 2}\par +% \textbf{Section 2}\par +% Metainfo for section `Section 2' +% +% \addvspace{\baselineskip} +% Annotations:\par +% Local metainfo. This metainfo is a bit longer, but only a little +% bit. +% +% \addvspace{\baselineskip} +% \textbf{Section 3}\par +% Metainfo for section `Section 3' +% +% +% +% +% \subsection{Example local metainfo formatting}\label{sec:ExLoMI} +% +% The following macros prefix local metainfo with `Annotations:' in +% bold typeface and typesets the local metainfo in an |itemize| +% environment:\footnote{Similar to the package option +% \texttt{listlocalmetainfo}, described in section \ref{sec:Options} +% on page \pageref{sec:Options} does.} +% +% \begin{verbatim} +% \makeatletter +% \def\mi@@firstlocalMItext{% +% \addvspace{\baselineskip}% +% \noindent\textbf{Annotations:}% +% \begin{itemize}% +% } +% \def\mi@@lastlocalMItext{% +% \end{itemize}% +% } +% \def\mi@@everylocalMItext{% +% \item\relax% +% } +% \makeatother +% \end{verbatim} +% +% +% +% +% \section{Notes/Limitations} +% +% \begin{itemize} +% \item Any text or macros on the same line as a heading are +% processed as well, immediately after the heading. Thus +% you can type |\section{foo}\label{sec:foo}| and refer +% to this section inside a metainfo using the label +% |sec:foo|. +% +% \item The document included using |\typesetmetainfo| must +% be a valid \LaTeX\ document insofar as that it must +% contain a |document| environment, because |\end{document}| +% serves as the ending delimiter for typesetting the +% metainfo. +% +% That also means that any metainfo following |\end{document}| +% is \emph{not} typeset. +% +% \end{itemize} +% +% +% +% +% \StopEventually{} +% +% \section{Implementation} +% +% \subsection{Main environments and macros} +% +% \begin{macro}{\typesetmetainfo} +% +% Usage: |\typesetmetainfo| \marg{file}. +% +% Typesets the metainfo of a document. +% +% \begin{macrocode} +\newcommand{\typesetmetainfo}[1]{% + \bgroup% + \mi@activenewline% + \mi@emptyactivepercent% + \mi@otherbraces% + \ifmi@indexmacros\mi@activehat\fi% +% \end{macrocode} +% +% We provide support for the standard \LaTeX\ |verbatim| environment: +% +% \begin{macrocode} + \let\mi@old@verbatim\@verbatim% + \def\@verbatim{% + \mi@old@verbatim% + \mi@verbatimnewline% + }% +% \end{macrocode} +% +% We use the original \TeX\ definition of |\input| (saved by \LaTeX\ +% in |\@@input|), because we must continue with our special processing +% immediately after \meta{file} has been opened. This is a job for the +% original \TeX\ |\input|, as it simply switches the input stream to +% \meta{file} and expands to nothing. +% +% The |\relax| delimits the filename. +% +% \begin{macrocode} + \expandafter\mi@skiplines\@@input#1\relax% + \egroup% +} +% \end{macrocode} +% \end{macro} +% +% +% +% +% \subsection{Package customization} +% +% \begin{macro}{\mi@@MIbeginnings} +% +% Stores all the macros that can begin a metainfo. +% +% \begin{macrocode} +\def\mi@@MIbeginnings{\chapter\section\subsection\subsubsection} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\mi@@firstlocalMItext} +% +% Stores the text inserted before the first local metainfo. +% +% \begin{macrocode} +\def\mi@@firstlocalMItext{\textbf{Annotations:}\par\noindent} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\mi@@lastlocalMItext} +% +% Stores the text inserted after the last local metainfo. +% +% \begin{macrocode} +\def\mi@@lastlocalMItext{} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\mi@@everylocalMItext} +% +% Stores the text inserted before every local metainfo. +% +% \begin{macrocode} +\def\mi@@everylocalMItext{} +% \end{macrocode} +% \end{macro} +% +% +% +% +% \subsection{Package options} +% +% \subsubsection{Headings} +% +% We provide the possibility of changing the headings to a more +% compact formatting: +% +% \begin{macrocode} +\DeclareOption{compactheadings}{% + \@ifundefined{thechapter}{}{% + \def\chapter{\@startsection{chapter}{0}{\z@}{-2\baselineskip}% + {\baselineskip}{\normalfont\normalsize\bfseries}}% + }% + \def\section{\@startsection{section}{1}{\z@}{-2\baselineskip}% + {\baselineskip}{\normalfont\normalsize\bfseries}}% + \def\subsection{\@startsection{subsection}{2}{\z@}{-2\baselineskip}% + {\baselineskip}{\normalfont\normalsize\bfseries}}% + \def\subsubsection{\@startsection{subsubsection}{3}{\z@}% + {-2\baselineskip}{\baselineskip}% + {\normalfont\normalsize\bfseries}}% +} +% \end{macrocode} +% +% +% +% +% \subsubsection{Index shorthand} +% +% \begin{macro}{\ifmi@indexmacros} +% +% |true|, if index shorthands specified using the package option +% |indexshorthand| are used, otherwise |false|: +% +% \begin{macrocode} +\newif\ifmi@indexmacros +\mi@indexmacrosfalse +% \end{macrocode} +% \end{macro} +% +% We provide the possibility of using the shorthand |^| for an index +% entry that is typeset, and |^^| for an index entry that is not +% typeset: +% +% \begin{macrocode} +\DeclareOption{indexshorthand}{% + \mi@indexmacrostrue% +% \end{macrocode} +% +% +% \begin{macro}{\mi@hat} +% +% We save the original meaning of |^|. We do not simply use |^| in the +% |\mi@hat|\ldots-macros, because then we would assume that |^| is not +% already an active character before our catcode change (which we will +% make in |\typesetmetainfo|). Normally, |^| has catcode 7 +% (superscript), but if is was active (i.e. because of another package +% changing |^|), we would store an active |^| in the definition of the +% |\mi@hat|\ldots-macros. When later used this |^| would point to our +% macro |\mi@hat|, resulting in an endless loop. So we save the +% original meaning of |^| instead using |\let|, which, if |^| is +% active, would save the macro |^| would have been |\let| to. +% +% \begin{macrocode} + \let\mi@@@hat^% +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\mi@hat} +% +% Main macro for indexing and first step in deciding how to index: +% +% \begin{itemize} +% \item Math mode: Expand to the original definition of |^|. +% +% \item Otherwise: Check the next token using |\mi@hat@|. +% +% \end{itemize} +% +% \begin{macrocode} + \def\mi@hat{% + \ifmmode% + \expandafter\mi@@@hat% + \else% + \expandafter\futurelet\expandafter\@tempa\expandafter\mi@hat@% + \fi% + } +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\mi@hat@} +% +% Second step in deciding how to index. We know that we are not in +% math mode. The token following the hat has been prefetched and +% stored in |\@tempa|. (it has not been read yet) +% +% \begin{itemize} +% \item A second hat (|^|): Check the next token using |\mi@hat@twohats|. +% +% \item Opening brace: Typeset the index word and index it using +% it |\mi@indextypeset|. +% +% \item Otherwise: Display an error, as |^^| must be followed by +% a parameter in braces. +% +% \end{itemize} +% +% \begin{macrocode} + \def\mi@hat@{% + \ifx\@tempa\mi@hat% + \expandafter\mi@hat@twohats% + \else\ifx\@tempa\bgroup% + \expandafter\expandafter\expandafter\mi@indextypeset% + \else% + \mi@hat@errbrace% + \fi\fi% + } +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\mi@hat@twohats} +% +% First step in deciding how to index a word not typeset. We know we +% have two hats in a row (|^^|), but the second hat is not read yet +% (only prefetched using |\futurelet|). Therefore we gobble it using +% |#1|. +% +% \begin{macrocode} + \def\mi@hat@twohats#1{% + \futurelet\@tempa\mi@hat@twohats@% + } +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\mi@hat@twohats} +% +% Second step in deciding how to index a word not typeset. We know we +% have two hats in a row, both read. The token following the two hats +% has been prefetched and stored in |\@tempa|. +% +% Note that we could skip this step and simpy expand to |\index|, +% letting |\index| take care that a proper parameter follows. +% +% \begin{macrocode} + \def\mi@hat@twohats@{% + \ifx\@tempa\bgroup% + \expandafter\index% + \else% + \mi@hat@errbrace% + \fi% + } +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\mi@indextypeset} +% +% Usage: |\mi@indextypeset| \marg{word}. Typesets \meta{word} and +% indexes it using |\index|. +% +% \begin{macrocode} + \def\mi@indextypeset#1{% + #1\index{#1}% + } +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\mi@hat@errbrace} +% +% Error handling when a |^| or |^^| is not followed by a left brace. +% +% \begin{macrocode} + \def\mi@hat@errbrace{% + \PackageError{metainfo}{`\string^' or `\string^\string^' not % + followed by a left brace}\@ehc% + } +% \end{macrocode} +% \end{macro} +% +% +% End of |\DeclareOption{index}|: +% +% \begin{macrocode} +} +% \end{macrocode} +% +% +% +% +% \subsubsection{Other options} +% +% \begin{macrocode} +\DeclareOption{listlocalmetainfo}{% + \def\mi@@firstlocalMItext{% + \begin{itemize}% + }% + \def\mi@@lastlocalMItext{% + \end{itemize}% + }% + \def\mi@@everylocalMItext{% + \item\relax% + }% +} +% \end{macrocode} +% +% +% +% +% \begin{macrocode} +\ProcessOptions\relax +% \end{macrocode} +% +% +% +% +% \subsection{Internal environments and macros} +% +% \subsubsection{General definitions and flags} +% +% \paragraph{Strategy for dealing with catcode changes} At the +% beginning of the processing, the catcodes are changed as follows: +% +% \begin{tabular}{cl} +% |^^M| & 13 (active), set in |\mi@activenewline| \\ +% |%| & 13, set in |\mi@emptyactivepercent| \\ +% |{| & 12 (other), set in |\mi@otherbraces| \\ +% |}| & 12, set in |\mi@otherbraces| \\ +% |^| & 13, optionally set in |\mi@activehat| \\ +% \end{tabular} +% +% If any macro changes the catcodes of these characters, it must reset +% them to these values after processing. If any macro needs the braces +% |{| and |}| for parameter grouping, it should use the macro +% |\mi@normalbraces| to change the catcodes accordingly. +% +% +% \begin{macro}{\ifmi@firstlocalMI} +% +% |true| if this is the first local metainfo, otherwise |false|. Used +% to insert |\mi@@firstlocalMItext| and |\mi@@lastlocalMItext|. +% +% \begin{macrocode} +\newif\ifmi@firstlocalMI +\mi@firstlocalMItrue +% \end{macrocode} +% \end{macro} +% +% +% +% +% \subsubsection{Modes} +% +% Three modes of processing exist: +% +% \begin{description} +% \item[Skipping text] Text is skipped line after line. If two +% percent signs are found at the beginning of a new line, +% a local metainfo is begun and the mode changed to +% `Typesetting a metainfo'. +% +% Main macro: |\mi@skiplines|. +% +% \item[Beginning metainfo] The appropriate heading is typeset +% and the remaining line of text skipped. The mode is then +% changed to `Typesetting a metainfo'. +% +% Main macro: |\mi@checkbeginMI|. +% +% \item[Typesetting a metainfo] The text is typeset. If a line does +% not start with a percent sign, the metainfo is done. The +% mode is then changed to `Skipping text'. +% +% Main macro: |\mi@typesetMI|. +% +% \end{description} +% +% +% \begin{macro}{\mi@skiplines} +% +% Main macro. Skips lines and checks the first token of a line (stored +% in |#1|) for two special cases: +% +% \begin{enumerate} +% \item A percent sign |%|: We check if it starts a local metainfo +% using |\mi@checkbeginlocalMI|. +% +% \item A control sequence: We check if it starts a new metainfo +% using |\mi@checkbeginMI|. +% +% \end{enumerate} +% +% \begin{macrocode} +\def\mi@skiplines#1{% + \ifx#1\mi@percentempty% +% \end{macrocode} +% +% A percent sign: We check if it starts a local metainfo. +% +% \begin{macrocode} + \expandafter\mi@checkbeginlocalMI% + \else\ifcat\noexpand#1\relax% +% \end{macrocode} +% +% A control sequence: We check if it starts a new metainfo. +% +% \begin{macrocode} + \expandafter\expandafter\expandafter\mi@checkbeginMI% + \else% +% \end{macrocode} +% +% Anything else: We skip it and the remaining line of text. Note that +% it could be a line ending (|^^M|), so it may be possible that we +% gobble only |#1|, which will be re-inserted into the stream below. +% That way we do not have to check if |#1| is a line ending. +% +% \begin{macrocode} + \expandafter\expandafter\expandafter\mi@gobbletolineend% + \fi\fi% +% \end{macrocode} +% +% We always insert the first token of a line back into the stream, +% even though it is not necessary for |\mi@checkbeginlocalMI|. But as +% normally most of the lines of a text will be skipped, we optimize +% for this case. +% +% \begin{macrocode} + #1% +} +% \end{macrocode} +% \end{macro} +% +% +% The following macros require |^^M| to be active: +% +% \begin{macrocode} +\bgroup +\catcode`\^^M=\active% +% \end{macrocode} +% +% +% \begin{macro}{\mi@typesetMI} +% +% Prepares the typesetting of a metainfo. +% +% \begin{macrocode} +\gdef\mi@typesetMI{% + \mi@normalbraces% +% \end{macrocode} +% +% Every CR we check if the next line continues the metainfo +% using |\mi@typesetMI@checkend|. +% +% \begin{macrocode} + \let^^M\mi@typesetMI@checkend% +% \end{macrocode} +% +% Now we start typesetting the text. We let \TeX\ take completely +% control instead of reading one line after the other; we will regain +% control at the end of each line using our redefinition of |^^M|. +% +% \begin{macrocode} + \ignorespaces% +} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\mi@typesetMI@checkend} +% +% Called at a carriage return. If the token after the CR is equals to +% |\mi@percentempty|, the next line starts with a |%|, thus continuing +% the metainfo. Otherwise, the metainfo is finished. +% +% \begin{macrocode} +\long\gdef\mi@typesetMI@checkend#1{% + \ifx#1\mi@percentempty% +% \end{macrocode} +% +% The next line continues the comment. We check for an empty line: +% +% \begin{macrocode} + \expandafter\mi@typesetMI@checkend@% + \else% +% \end{macrocode} +% +% The next line finishes the comment: +% +% \begin{macrocode} + \mi@otherbraces% + \let^^M\@empty% + \expandafter\mi@skiplines\expandafter#1% + \fi% +} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\mi@typesetMI@checkend@} +% +% Checks if a |^^M| (CR) follows immediately after the |%|. Then we +% insert a |\par|. Note that any spaces between the |%| and the CR +% are automatically skipped by using a non-delimited parameter. +% +% \begin{macrocode} +\long\gdef\mi@typesetMI@checkend@#1{% + \ifx#1\mi@typesetMI@checkend% + \par\expandafter\mi@typesetMI@checkend% + \else% +% \end{macrocode} +% +% We assume the line is |% |\meta{text} instead of |%|\meta{text}, +% thus we insert back a space that was skipped before: +% +% \begin{macrocode} + \space% + \expandafter#1% + \fi% +} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\mi@checkbeginMI} +% +% Usage: |\mi@checkbeginMI|\meta{cs}. +% +% First step in the check for the begin of a metainfo: Checks if +% \meta{cs} is a control sequence that can begin a metainfo. +% +% \begin{macrocode} +\gdef\mi@checkbeginMI#1{% +% \end{macrocode} +% +% Handle |\end|: +% +% \begin{macrocode} + \ifx#1\end% + \expandafter\mi@checkdocumentend% + \else% +% \end{macrocode} +% +% We check if \meta{cs} is a relevant control sequence. (these are +% stored in |\mi@@MIbeginnings|) Then we use |\mi@checkbeginMI@| to +% evaluate the result: +% +% \begin{macrocode} + \def\@tempa##1#1##2\@nil{\mi@checkbeginMI@{##2}#1}% + \expandafter\expandafter\expandafter\@tempa% + \expandafter\mi@@MIbeginnings\expandafter#1% + \expandafter\@nil% + \fi% +} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\mi@checkbeginMI@} +% +% Support macro for |\mi@checkbeginMI|. Checks if |#2| is a relevant +% control sequence by checking if |#1| is empty (|false|) or not +% (|true|). +% +% \begin{macrocode} +\gdef\mi@checkbeginMI@#1#2{% + \ifx^^M#1^^M% +% \end{macrocode} +% +% Not a relevant control sequence: Skip till the end of the line. +% +% \begin{macrocode} + \expandafter\mi@gobbletolineend% + \else% +% \end{macrocode} +% +% A relevant control sequence. If there has been any local metainfo +% before this macro, we finish it by inserting |\mi@@lastlocalMItext|: +% +% \begin{macrocode} + \ifmi@firstlocalMI\else\mi@@lastlocalMItext\fi% +% \end{macrocode} +% +% We restore all character catcodes except for |^^M|, which we use to +% continue processing after the control sequence in question has been +% executed: (this is the reason a heading must appear on a single +% line, as otherweise |^^M| is executed more than once) +% +% \begin{macrocode} + \let^^M\mi@checkbeginMI@@% + \mi@normalbraces% + \mi@normalpercent% +% \end{macrocode} +% +% In any case, a local metainfo following this macro is the first, so +% we set the flag accordingly: +% +% \begin{macrocode} + \mi@firstlocalMItrue% + \expandafter#2% + \fi% +} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\mi@checkbeginMI@@} +% +% Support macro for |\mi@checkbeginMI@|. Is called via |^^M| at the end +% of a line. +% +% \begin{macrocode} +\gdef\mi@checkbeginMI@@{% + \let^^M\@empty% + \mi@otherbraces% + \mi@emptyactivepercent% + \mi@checkbeginMI@@@% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macrocode} +\egroup +% \end{macrocode} +% +% +% \begin{macro}{\mi@checkbeginMI@@@} +% +% Support macro for |\mi@checkbeginMI| and the second step in the +% check for the begin of a metainfo: Checks if the line after the +% control sequence begins with a percent sign. +% +% \begin{macrocode} +\def\mi@checkbeginMI@@@#1{% + \ifx#1\mi@percentempty% +% \end{macrocode} +% +% A percent sign: It starts a metainfo. Change to metainfo. +% +% \begin{macrocode} + \par% + \expandafter\mi@typesetMI% + \else% +% \end{macrocode} +% +% Anything else: No metainfo follows. Ignore it. +% +% \begin{macrocode} + \expandafter\mi@skiplines\expandafter#1% + \fi% +} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\mi@checkbeginlocalMI} +% +% Usage: |\mi@checkbeginlocalMI|\meta{dummy}\meta{next token}. +% +% \meta{dummy} is the result of an optimization of |\mi@skiplines|. +% (see above) +% +% \begin{macrocode} +\def\mi@checkbeginlocalMI#1#2{% + \ifx#2\mi@percentempty% +% \end{macrocode} +% +% A percent sign: It starts a local metainfo. Change to metainfo. +% +% \begin{macrocode} + \par% + \ifmi@firstlocalMI\mi@@firstlocalMItext\fi% + \mi@@everylocalMItext% +% \end{macrocode} +% +% We have begun to typeset the local metainfo, therefore we take note +% that any local metainfo following this one is not the first. +% +% \begin{macrocode} + \mi@firstlocalMIfalse% + \expandafter\mi@typesetMI% + \else% +% \end{macrocode} +% +% Anything else: No, it is just a simple comment. Ignore it. +% +% \begin{macrocode} + \expandafter\mi@gobbletolineend\expandafter#2% + \fi% +} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\mi@checkdocumentend} +% +% Checks if the |\end| just read ends the |document| environment. +% +% \begin{macrocode} +\def\mi@checkdocumentend{% +% \end{macrocode} +% +% We change the catcodes of braces back to normal in order to get the +% name of the environment as the only parameter of |\mi@checkdocumentend@| +% and not only the opening brace. +% +% \begin{macrocode} + \mi@normalbraces% + \mi@checkdocumentend@% +} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\mi@checkdocumentend@} +% +% Support macro for |\mi@checkdocumentend|. +% +% \begin{macrocode} +\def\mi@checkdocumentend@#1{% + \def\@tempa{#1}% + \ifx\@tempa\mi@textdocument% +% \end{macrocode} +% +% If there has been any local metainfo before this macro, we finish it +% by inserting |\mi@@lastlocalMItext|: +% +% \begin{macrocode} + \ifmi@firstlocalMI\else\mi@@lastlocalMItext\fi% + \expandafter\mi@gobbletolineend@any\expandafter\endinput% + \else% +% \end{macrocode} +% +% As are not done yet, we better set the catcode of braces to +% `letter': +% +% \begin{macrocode} + \mi@otherbraces% + \expandafter\mi@skiplines% + \fi% +} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\mi@textdocument} +% +% The text `document' for |\mi@checkdocumentend|. +% +% \begin{macrocode} +\def\mi@textdocument{document} +% \end{macrocode} +% \end{macro} +% +% +% +% \begin{macro}{\mi@percentempty} +% +% \begin{macrocode} +\def\mi@percentempty{\@empty} +% \end{macrocode} +% \end{macro} +% +% +% +% +% \subsubsection{Gobbling text} +% +% \begin{macrocode} +\bgroup +\catcode`\^^M=\active% +% \end{macrocode} +% +% +% \begin{macro}{\mi@gobbletolineend} +% +% Gobbles up any text till the end of the line. Continues with +% |\mi@skiplines|. (specialization of |\mi@gobbletolineend@any|) +% +% \begin{macrocode} +\gdef\mi@gobbletolineend{% + \mi@gobbletolineend@any\mi@skiplines% +} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\mi@gobbletolineend@any} +% +% Usage: |\mi@gobbletolineend@any| \marg{macro}. +% +% Gobbles up any text till the end of the line. Continues with +% \meta{macro}. The macro is |long| in case the line (stored in |#2|) +% contains a |\par|. +% +% \begin{macrocode} +\long\gdef\mi@gobbletolineend@any#1#2^^M{% + #1% +} +\egroup +% \end{macrocode} +% \end{macro} +% +% +% +% \subsubsection{Catcode changes} +% +% We define the macros for changing catcodes: +% +% \begin{macro}{\mi@activenewline} +% \begin{macro}{\mi@verbatimnewline} +% \begin{macro}{\mi@emptyactivepercent} +% \begin{macro}{\mi@activehat} +% +% \begin{macrocode} +\bgroup +% \end{macrocode} +% +% We use \verb+|+ as the comment character as we make |%| active: +% +% \begin{macrocode} +\catcode`\|=14 % +\catcode`\^^M=\active% +\catcode`\%=\active| +\gdef\mi@activenewline{| + \catcode`\^^M=\active| + \let^^M\@empty| +}| +\gdef\mi@verbatimnewline{| + \catcode`\^^M=\active| + \def^^M{\par\@gobbletwo}| +}| +\gdef\mi@emptyactivepercent{| + \catcode`\%=\active| + \let%\mi@percentempty| +}| +\catcode`\^=\active| +\gdef\mi@activehat{| + \catcode`\^\active| + \let^\mi@hat| +}| +\egroup +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% +% \begin{macro}{\mi@normalpercent} +% +% \begin{macrocode} +\def\mi@normalpercent{% + \catcode`\%=14 % +} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\mi@otherbraces} +% +% \begin{macrocode} +\def\mi@otherbraces{% + \catcode`\{=12 % + \catcode`\}=12 % +} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\mi@normalbraces} +% +% \begin{macrocode} +\def\mi@normalbraces{% + \catcode`\{=1 % + \catcode`\}=2 % +} +% \end{macrocode} +% \end{macro} +% +% +% +% \Finale +% \PrintChanges +% \PrintIndex +\endinput \ No newline at end of file diff --git a/macros/latex/contrib/sauerj/metainfo.ins b/macros/latex/contrib/sauerj/metainfo.ins new file mode 100644 index 0000000000..a03684bd8a --- /dev/null +++ b/macros/latex/contrib/sauerj/metainfo.ins @@ -0,0 +1,19 @@ +\input docstrip +\keepsilent +\askforoverwritefalse + +\preamble +\endpreamble +\generate{% + \file{\jobname.sty}{\from{\jobname.dtx}{package}} +} + +\Msg{***************************************************************} +\Msg{*} +\Msg{* \space To finish the installation you have to copy the files} +\Msg{*} +\Msg{* \space *.sty into a directory searched by TeX} +\Msg{*} +\Msg{***************************************************************} + +\endbatchfile \ No newline at end of file diff --git a/macros/latex/contrib/sauerj/metainfo.pdf b/macros/latex/contrib/sauerj/metainfo.pdf new file mode 100644 index 0000000000..6fd43c7090 Binary files /dev/null and b/macros/latex/contrib/sauerj/metainfo.pdf differ diff --git a/macros/latex/contrib/sauerj/optparams.dtx b/macros/latex/contrib/sauerj/optparams.dtx new file mode 100644 index 0000000000..99c4880441 --- /dev/null +++ b/macros/latex/contrib/sauerj/optparams.dtx @@ -0,0 +1,327 @@ +% \iffalse meta-comment +% Line endings: UNIX +% Tab size: 4 +% +% Copyright 2004 Jonathan Sauer +% +% This work 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 Jonathan Sauer +% (). +% +% This work consists of the files optparams.dtx and optparams.ins +% and the derived file optparams.sty. +% +% \fi +% +% \iffalse +% +%<*driver> +\documentclass{ltxdoc} +\usepackage{optparams} +\EnableCrossrefs +\CodelineIndex +\RecordChanges +% Modification of verbatim for tabs in listings +\makeatletter +{\catcode`\ =\active% +\catcode`\^^I=\active% +\gdef\@vobeyspaces{% +\catcode`\ \active\let \@xobeysp% +\catcode`\^^I\active\def^^I{~~}% +}}% +\makeatother +\begin{document} + \DocInput{\jobname.dtx} +\end{document} +% +% +%\NeedsTeXFormat{LaTeX2e} +%\ProvidesPackage{optparams} +% [2004/08/14 v0.9 multiple optional parameters in macros] +% +% \fi +% +% \CheckSum{12} +% \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 \~} +% +% \DoNotIndex{\@ifnextchar,\@nil,\def,\newcommand} +% +% \GetFileInfo{\jobname.sty} +% +% \title{The \textsf{optparams} package\thanks{This document +% corresponds to \textsf{\filename}~\fileversion, dated \filedate. The +% package is based on David Kastrup's macros for `Around the Bend +% 21'.}} +% +% \author{Jonathan Sauer \\ \texttt{jonathan.sauer@gmx.de}} +% +% \date{\filedate} +% +% \maketitle +% +% \begin{abstract} +% This file describes the \textsf{optparams} package that provides a +% small macro for creating macros with multiple optional parameters. +% +% \end{abstract} +% +% \tableofcontents +% +% +% +% \section{Introduction} +% +% The \LaTeX\ macro |\newcommand| is used to define macros that may +% have one optional parameter (the first one). However, there is no +% easy way of defining macros having several optional parameters. This +% package provides the macro |\optparams| to simplify the creation of +% macros with multiple optional parameters (or optional parameters +% only). +% +% +% +% \section{Examples} +% +% \subsection{Example one} +% +% \begin{verbatim} +% \long\def\test@[#1][#2][#3][#4]{% +% (#1) (#2) (#3) (#4) +% } +% +% \newcommand{\test}{% +% \optparams{\test@}{[one][two][three][four]}% +% } +% \end{verbatim} +% You have now defined a macro |\test| that takes up to four optional +% parameters (|#1| to |#4|). You can call this macro as: +% +% \begin{itemize} +% \item |\test[this]|, resulting in |(this) (two) (three) (four)|. +% +% \item |\test[this][is]|, resulting in |(this) (is) (three) (four)|. +% +% \item |\test[this][is][a]|, resulting in |(this) (is) (a) (four)|. +% +% \item |\test[this][is][a][test]|, resulting in |(this) (is) (a) (test)|. +% +% \end{itemize} +% You see that the default parameters defined in |\test| are replaced +% one by one by the parameters given when |\test| is called. +% +% +% +% \subsection{Example two} +% +% \begin{verbatim} +% \long\def\test@[#1][#2][#3][#4]#5{% +% (#1) (#2) (#3) (#4) !#5! +% } +% +% \newcommand{\test}{% +% \optparams{\test@}{[one][two][three][four]}% +% } +% \end{verbatim} +% You have now defined a macro |\test| that takes up to four optional +% parameters (|#1| to |#4|) and one mandatory parameter (|#5)|. You +% can call this macro as: +% +% \begin{itemize} +% \item |\test[this]{foo}|, resulting in +% |(this) (two) (three) (four) !foo!|. +% +% \item |\test[this][is]{foo}|, resulting in +% |(this) (is) (three) (four) !foo!|. +% +% \item |\test[this][is][a]{foo}|, resulting in +% |(this) (is) (a) (four) !foo!|. +% +% \item |\test[this][is][a][test]{foo}|, resulting in +% |(this) (is) (a) (test) !foo!|. +% +% \end{itemize} +% +% +% +% \section{Description of the macros} +% +% \DescribeMacro{\optparams} Usage: |\optparams| \marg{macro} +% \marg{default parameters}. +% +% This macro reads any optional parameters from the input and finally +% calls your macro with the optional parameters as well as the +% remaining default parameters. +% +% Each default parameter must have the form |[|\meta{value}|]|. As all +% default parameters are passed as one parameter to |\optparams|, they +% must be enclosed in braces (|{|\meta{default parameters}|}|). +% +% The macro that is finally called must have as many optional +% parameters as have been defined in the call of |\optparams|; their +% form must be |[|\meta{parameter}|]|, where \meta{parameter} is a +% number beginning with one and ending with nine.\footnote{This is a +% general restriction of \TeX: A macro cannot have more than nine +% parameters.} The parameter numbers must be numbered consecutively, +% i.e. |[#1][#2][#3]| instead of |[#1][#2][#4]|. +% +% Because of this special way of declaring macro parameters, you +% cannot use |\newcommand| but have to use the \TeX\ primitiv |\def|. +% As |\def|, contrary to |\newcommand|, does not warn you when you +% overwrite an already existing macro, you first should define the +% macro as a dummy using |\newcommand| and then correctly using +% |\def|, i.e.: +% +% \begin{verbatim} +% \newcommand{\test@}{} +% \long\def\test@[#1][#2][#3][#4]{% +% +% } +% \end{verbatim} +% This way you do not accidentally overwrite an existing macro. +% +% What does the |\long| do? In \TeX, in order to quicker capture +% errors such as missing right braces |}|, parameters of macros +% defined using |\def| cannot contain a |\par|, or \TeX\ will complain +% (`runaway argument?'). This makes it easier for the user to spot +% mistakes, as in that case \TeX\ will stop processing immediately at +% the end of the current paragraph and not continue until i.e. the end +% of the file before realizing that a macro parameter has not been +% closed via |}|. +% +% But there is a way to make the usage of |\par| as a macro parameter +% possible: Using |\long| in front of the |\def|. In \LaTeX, +% |\newcommand| defines macros as |\long| by default, and its variant +% |\newcommand*| defines macros restricted to `short' parameters. So +% as demonstrated in the examples, you should either use |\newcommand| +% and |\long\def| together or |\newcommand*| and |\def| in order to +% make your macros behave correctly. +% +% +% +% \section{Notes} +% +% \begin{itemize} +% \item If you use the notation used in the examples above, +% \meta{macroname} for the main macro and +% \meta{macroname}|@| for the macro finally called by +% |\optparams|, and if you define these macros not in a +% package or class, but in your document preamble, you have +% to enclose the definitions in |\makeatletter| \ldots\ +% |\makeatother|, otherwise you cannot use |@| in macro +% names. +% +% \item If you define a macro having only optional parameters (as +% in the first example above), you have to make sure the +% macro is not called in a context where a |[| follows not +% as a parameter, but simply as an opening bracket, i.e. +% |\test[foo] [as a side note| \ldots, where the call of +% |\test| should have only |[foo]| as its only +% parameter. In this case |\optparams| will think that +% another optional parameter follows, resulting in chaos. +% +% To prevent this from happening, insert a |\relax| after +% the last optional parameter of the macro call, i.e. +% |\test[foo]\relax [as a side note| \ldots\ Then +% |\optparams| will stop looking for more optional +% parameters. +% +% \end{itemize} +% +% \StopEventually{} +% +% +% +% \section{Implementation} +% +% \subsection{Main macros} +% +% \begin{macro}{\optparams} +% +% Calls |#1| using a variable number of parameters. Default parameters +% are provided in |#2| in the form |[|\meta{param one}|]| |[|\meta{param +% two}|]| \ldots +% +% \begin{macrocode} +\newcommand{\optparams}[2]{% + \optparams@{#1}{}{#2}% +} +% \end{macrocode} +% \end{macro} +% +% +% +% \subsection{Internal macros} +% +% \begin{macro}{\optparams@} +% +% Checks if the next character from the input is a |[|. If true calls +% |\optparams@@|, as there are still optional parameters left. Otherwise +% calls \meta{macro} with \meta{parameters read} and \meta{remaining +% default parameters}. +% +% Usage: |\optparams@| \marg{macro} \marg{parameters read} +% \marg{remaining default parameters}. +% +% \begin{macrocode} +\def\optparams@#1#2#3{% + \@ifnextchar[{% + \optparams@@{#1}{#2}#3\@nil% + }{% + #1#2#3% + }% +} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\optparams@@} +% +% Reads the next optional parameter from the input (as |#5| or +% \meta{new parameter}). Then gobbles up the corresponding default +% parameter (as |#3| or \meta{default for parameter read}, appends the +% parameter read to \meta{parameters read} and calls |\optparams@| +% again to check for more optional parameters. +% +% Usage: |\optparams@@| \marg{macro} \marg{parameters read} +% \marg{default for parameter read} \marg{remaining default +% parameters} \marg{new parameter}. +% +% \begin{macrocode} +\def\optparams@@#1#2[#3]#4\@nil[#5]{% + \optparams@{#1}{#2[#5]}{#4}% +} +% \end{macrocode} +% \end{macro} +% +% Now this is quite a coincidence: Thirteen lines of code, and this +% package was begun on Friday, 13th \ldots +% +% \Finale +% \PrintChanges +% \PrintIndex +\endinput \ No newline at end of file diff --git a/macros/latex/contrib/sauerj/optparams.ins b/macros/latex/contrib/sauerj/optparams.ins new file mode 100644 index 0000000000..a03684bd8a --- /dev/null +++ b/macros/latex/contrib/sauerj/optparams.ins @@ -0,0 +1,19 @@ +\input docstrip +\keepsilent +\askforoverwritefalse + +\preamble +\endpreamble +\generate{% + \file{\jobname.sty}{\from{\jobname.dtx}{package}} +} + +\Msg{***************************************************************} +\Msg{*} +\Msg{* \space To finish the installation you have to copy the files} +\Msg{*} +\Msg{* \space *.sty into a directory searched by TeX} +\Msg{*} +\Msg{***************************************************************} + +\endbatchfile \ No newline at end of file diff --git a/macros/latex/contrib/sauerj/optparams.pdf b/macros/latex/contrib/sauerj/optparams.pdf new file mode 100644 index 0000000000..e3ed25d776 Binary files /dev/null and b/macros/latex/contrib/sauerj/optparams.pdf differ diff --git a/macros/latex/contrib/sauerj/parcolumns.dtx b/macros/latex/contrib/sauerj/parcolumns.dtx new file mode 100644 index 0000000000..f898e43aae --- /dev/null +++ b/macros/latex/contrib/sauerj/parcolumns.dtx @@ -0,0 +1,1090 @@ +% \iffalse meta-comment +% Line endings: UNIX +% Tab size: 4 +% +% Copyright 2004 Jonathan Sauer +% +% This work 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 Jonathan Sauer +% (). +% +% This work consists of the files parcolumns.dtx and parcolumns.ins +% and the derived file parcolumns.sty. +% +% \fi +% +% \iffalse +% +%<*driver> +\documentclass{ltxdoc} +\usepackage{parcolumns} +\EnableCrossrefs +\CodelineIndex +\RecordChanges +% Modification of verbatim for tabs in listings +\makeatletter +{\catcode`\ =\active% +\catcode`\^^I=\active% +\gdef\@vobeyspaces{% +\catcode`\ \active\let \@xobeysp% +\catcode`\^^I\active\def^^I{~~}% +}}% +\makeatother +\begin{document} + \DocInput{\jobname.dtx} +\end{document} +% +% +%\NeedsTeXFormat{LaTeX2e} +%\ProvidesPackage{parcolumns} +% [2004/11/25 v1.2 Typeset multiple parallel columns] +%\RequirePackage{processkv}[2004/08/05] +% +% \fi +% +% \CheckSum{368} +% \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 \~} +% +% \DoNotIndex{\@clubpenalty,\@doendpe,\@ehc,\@ifundefined,\@M,\@ne} +% \DoNotIndex{\@one,\@nobreakfalse,\@plus,\@tempa,\@tempb,\@tempboxa} +% \DoNotIndex{\@tempcnta,\@tempdima,\@tempdimb,\@tempdimc} +% \DoNotIndex{\@tempswafalse,\@testopt,\advance,\afterassignment} +% \DoNotIndex{\box,\brokenpenalty,\clubpenalty,\count@,\csname} +% \DoNotIndex{\def,\define@key,\displaywidowpenalty,\divide,\dp,\edef} +% \DoNotIndex{\else,\endcsname,\endgraf,\everypar,\expandafter} +% \DoNotIndex{\fi,\global,\hbadness,\hb@xt@,\hfill,\hsize,\hskip} +% \DoNotIndex{\if@tempswa,\ifnum,\ifvoid,\ifx,\interlinepenalty} +% \DoNotIndex{\lastbox,\leavevmode,\let,\linewidth,\long,\loop} +% \DoNotIndex{\m@ne,\multiply,\newbox,\newcommand,\newcount} +% \DoNotIndex{\newdimen,\newenvironment,\newif,\newtoks} +% \DoNotIndex{\number,\PackageError,\PackageInfo,\processkeyvalues} +% \DoNotIndex{\relax,\repeat,\setbox,\setkeys,\space,\spaceskip} +% \DoNotIndex{\splittopsep,\splittopskip,\strut,\strutbox,\the} +% \DoNotIndex{\toks@,\tolerance,\unvbox,\vbadness,\vbox,\vfuzz} +% \DoNotIndex{\vrule,\vsplit,\widowpenalty,\z@,\z@skip,\\} +% +% \GetFileInfo{\jobname.sty} +% +% \title{The \textsf{parcolumns} package\thanks{This document +% corresponds to \textsf{\filename}~\fileversion, dated \filedate.}} +% +% \author{Jonathan Sauer \\ \texttt{jonathan.sauer@gmx.de}} +% +% \date{\filedate} +% +% \maketitle +% +% \begin{abstract} +% This file describes the \textsf{parcolumns} package that provides an +% environment for typesetting text in two or more columns columns in +% parallel. +% +% \end{abstract} +% +% \tableofcontents +% +% \section{Introduction} +% +% Sometimes it is necessary to typeset text in two or more columns in +% parallel, i.e. when typesetting a text in its original language and +% in its translation(s). This package provides the \verb|parcolumns| +% environment for typesetting text in several columns, where the text +% of all columns is aligned vertically. +% +% Text in the |parcolums| environment is typeset in chunks, where the +% chunks of one row are aligned vertically. A chunk consists of one or +% more paragraphs of text, including \TeX\ macros. +% +% +% \section{Usage}\label{sec:Usage} +% +% \DescribeEnv{parcolumns} Usage: |parcolumns| \oarg{options} +% \marg{number of colums}. +% +% Inside the |parcolumns| environment text can be typeset in two or +% more columns in parallel via the |\parchunk| macro. Normal text can +% also be included. +% +% The \verb|parcolumns| environment takes an optional parameter that +% specifies the options for the environment using the \textsf{keyval} +% and \textsf{processkv} packages. The following options exist: +% +% \begin{description} +% \item[\emph{colwidths}] Sets the widths of the columns. The +% widths are specified as key-values, +% \meta{columnnumber}=\meta{width}. +% Columns start at `1'. Note that in +% order to be ignored by the +% \textsf{keyval} package, the complete +% value has to be surrounded by braces, +% i.e. `|colwidths={1=2cm,3=5cm,4=2cm}|' +% to set the first column to a width of +% 2~cm, the third to 5~cm and the fourth +% to 2~cm. (the second column is +% calculated) +% +% Columns not set this way will be +% distributed evenly across the remaining +% horizontal space of the page. +% +% \item[distance] Sets the distance between two columns. +% If omitted set to \verb|2em|. +% +% \item[rulebetween] (Flag)\footnote{Meaning that if you +% just say \texttt{rulebetween}, you set the +% flag, as well as when you say +% \texttt{rulebetween=true}. Saying +% \texttt{rulebetween=false} clears the flag, +% even though this does not make much sense, +% as it is the default.} +% Typeset a vertical bar between two +% columns. +% +% |false| if omitted. +% +% \item[nofirstindent] (Flag) Suppress the indentation of the first +% paragraph in the environment. +% +% |false| if omitted. +% +% \item[sloppy] (Flag) Typeset text in the columns in a +% more sloppy way, preventing overfull +% hboxes at the cost of larger +% interword spacing. +% +% |false| if omitted. +% +% \item[sloppyspaces] (Flag) Makes spaces in the columns +% stretchable, preventing overfull +% hboxes at the cost of even larger +% interword spacing that |sloppy|. +% +% |false| if omitted. +% +% \end{description} +% +% +% \DescribeMacro{\colchunk} Usage: |\colchunk| \oarg{column} +% \marg{chunk}. +% +% The macro |\colchunk| sets a chunk of text for the next column. You +% don't have to set chunks for all columns; the colums not set remain +% empty. However, the columns are filled from left to right, so if a +% column inbetween should remain empty, you must say |\colchunk{}| or +% specify the column to set using the optional parameter (columns +% start at 1): |\colchunk[2]{|\ldots|}| sets the text of the second +% column. Following calls to |\colchunk| without optional parameter +% fill the third, fourth et cetera column. +% +% After a call to |\colplacechunks|, the column number is reset to +% one. +% +% +% +% \DescribeMacro{\colplacechunks} Usage: |\colplacechunks|. +% +% The macro |\colplacechunks| places the chunks added with |\colchunk| +% on the page. If there are no chunks to place, it does nothing. +% +% +% +% \section{Examples} +% +% Two columns, option |rulebetween=true| (which is the same as +% just saying |rulebetween|): +% +% \addvspace{\baselineskip} +% \begin{parcolumns}[rulebetween=true]{2} +% \colchunk{Erwarten Sie von mir, dass ich rede? -- Nein, Mister +% Bond, ich erwarte von Ihnen, dass Sie sterben!} +% +% \colchunk{Do you expect me to talk? -- No, Mister Bond, I expect you +% to die!} +% +% \colplacechunks +% +% \colchunk{Erwarten Sie von mir, dass ich rede? -- Nein, Mister +% Bond, ich erwarte von Ihnen, dass Sie sterben!} +% +% \colchunk{Do you expect me to talk? -- No, Mister Bond, I expect you +% to die!} +% +% \colplacechunks +% +% \end{parcolumns} +% \addvspace{\baselineskip} +% As the german text is slightly longer, let's make the left column +% alittle bit larger using |colwidths={1=.55\linewidth}|: +% +% \addvspace{\baselineskip} +% \begin{parcolumns}[rulebetween=true,colwidths={1=.55\linewidth}]{2} +% \colchunk{Erwarten Sie von mir, dass ich rede? -- Nein, Mister +% Bond, ich erwarte von Ihnen, dass Sie sterben!} +% +% \colchunk{Do you expect me to talk? -- No, Mister Bond, I expect you +% to die!} +% +% \colplacechunks +% +% \colchunk{Erwarten Sie von mir, dass ich rede? -- Nein, Mister +% Bond, ich erwarte von Ihnen, dass Sie sterben!} +% +% \colchunk{Do you expect me to talk? -- No, Mister Bond, I expect you +% to die!} +% +% \colplacechunks +% +% \end{parcolumns} +% \addvspace{\baselineskip} +% Three columns, option |nofirstindent=true|: +% +% \addvspace{\baselineskip} +% \begin{parcolumns}[nofirstindent]{3} +% \colchunk{This is just a short english text, just long enough to fill +% a few lines.} +% +% \colchunk{Dies ist nur ein kurzer deutscher Text, gerade lang genug, +% um ein paar Zeilen zu fuellen.} +% +% \colchunk{This is another short english text, as my french is not +% that good anymore.} +% +% \colplacechunks +% +% \end{parcolumns} +% \addvspace{\baselineskip} +% There was an overfull |\hbox| in the previous text. Let's +% try that again with the option |sloppy|: +% +% \addvspace{\baselineskip} +% \begin{parcolumns}[nofirstindent,sloppy]{3} +% \colchunk{This is just a short english text, just long enough to fill +% a few lines.} +% +% \colchunk{Dies ist nur ein kurzer deutscher Text, gerade lang genug, +% um ein paar Zeilen zu fuellen.} +% +% \colchunk{This is another short english text, as my french is not +% that good anymore.} +% +% \colplacechunks +% +% \end{parcolumns} +% \addvspace{\baselineskip} +% No overfull hbox this time, but the spacing in the first column +% is not optimal. You just have to pick what's better. Or you could +% try the interword spacing provided by the \textsf{soul} package. +% +% \addvspace{\baselineskip}\noindent Maybe we do not want to fill the +% first column, but do not want to type |\colchunk{}| either. Then we +% can say |\colchunk[2]| to directly start with the second column +% (note that we are using the option |sloppy|, too): +% +% \addvspace{\baselineskip} +% \begin{parcolumns}[nofirstindent,sloppy]{3} +% \colchunk[2]{This is just a short english text, just long enough to fill +% a few lines.} +% +% \colchunk{Dies ist nur ein kurzer deutscher Text, gerade lang genug, +% um ein paar Zeilen zu fuellen.} +% +% \colplacechunks +% +% \end{parcolumns} +% \addvspace{\baselineskip} +% Note that \texttt{parcolumns} does not insert vertical space +% before or after the environment! In these examples, the space has +% manually been added with |\addvspace|. +% +% +% +% \section{Notes}\label{sec:Notes} +% +% \begin{itemize} +% \item The columns will always fill the complete width of the +% page by stretching or shrinking the space between the columns. +% That means that if the total width of all columns is set +% to about half the page width, the space between the columns +% will take up the rest, ignoring whatever was set with the +% key |distance|.\footnote{The key \texttt{distance} is only +% used for calculating the width of the columns and is ignored +% afterwards.} +% +% \item Footnotes are not set in columns. +% +% \item \textsf{parcolumns} does not work very well with displayed +% formula. The best way to typeset a |displaymath| et.al. +% environment is to include it in separate |\colchunk| +% commands, i.e. (assuming two columns and the same formula +% in both): +% +% \begin{verbatim} +% ... some text placed using \colchunk ... +% \colchunk{ % Left column +% \begin{displaymath} +% x^2 + y^2 = z^2 +% \end{displaymath} +% } +% \colchunk{ % Right column +% \begin{displaymath} +% x^2 + y^2 = z^2 +% \end{displaymath} +% } +% \colplacechunks +% ... some more text placed using \colchunk ... +% \end{verbatim} +% +% \end{itemize} +% +% +% +% \StopEventually{} +% +% \section{Implementation} +% +% \subsection{Allocation} +% +% The current column (starting with one): +% +% \begin{macrocode} +\newcount\pc@columnctr +% \end{macrocode} +% +% The total number of columns in the current |parcolums| environment. +% +% \begin{macrocode} +\newcount\pc@columncount +% \end{macrocode} +% +% Place a vertical rule between two columns? +% +% \begin{macrocode} +\newif\ifpc@rulebetween +% \end{macrocode} +% +% Stores |\everypar| for use in |\parparagraphs|. +% +% \begin{macrocode} +\newtoks\pc@everypar +% \end{macrocode} +% +% Note that additional allocations are performed later on-demand in +% |\pc@alloccolumns|. +% +% +% +% \subsection{\textsf{keyvalue} keys} +% +% \begin{macro}{\pc@boolkey} +% +% Sets an \verb|if|-condition in \marg{\#1} to the value passed as +% \marg{\#2}. If \verb|#2| is \verb|false|, set \verb|if#1| to +% \verb|false|, else (any other value) to \verb|true|. +% +% Usage: |\pc@boolkey| \marg{ifcondition} \marg{value} +% +% \begin{macrocode} +\def\pc@boolkey#1#2{% + \edef\@tempa{#2}% + \edef\@tempb{false}% + \ifx\@tempa\@tempb% + \csname #1false\endcsname% + \else% + \csname #1true\endcsname% + \fi% +} +% \end{macrocode} +% \end{macro} +% +% +% Define the keys for the options of |parcolumns|. +% +% \begin{macrocode} +\define@key{parcolumns}{distance}{% + \@tempdimc#1\relax% +} +\define@key{parcolumns}{rulebetween}[true]{% + \pc@boolkey{pc@rulebetween}{#1}% +} +\define@key{parcolumns}{nofirstindent}[true]{% + \pc@boolkey{@tempswa}{#1}% +% \end{macrocode} +% +% If the indentation of the first line of the first paragraph should +% be suppressed, change |\pc@everypar| accordingly. The token register +% is reset after the placing of the first row of chunks in +% |\colplacechunks|. +% +% What exactly are we doing? First we assign box 0 the contents of +% |\lastbox|. At the beginning of a paragraph |\lastbox| contains +% the glue inserted for the indentation of the first line. By +% assigning this box to box 0, we remove the indentation. We do +% this in a group as not to change the contents of box 0. +% +% Afterwards we set |\everypar| to nothing. This is necessary because +% we only want to suppress the indentation for the first paragraph of +% the |parcolumns| environment, not every paragraph. We set +% |\everypar| and not |\pc@everypar| to nothing, because +% |\pc@everypar| is only a temporary storage that will be assigned to +% |\everypar| when used. +% +% \begin{macrocode} + \if@tempswa\pc@everypar{{\setbox\z@\lastbox}\everypar{}}\fi% +} +\define@key{parcolumns}{sloppy}[true]{% + \pc@boolkey{@tempswa}{#1}% +% \end{macrocode} +% +% If sloppy typesetting is asked for, we set |\hbadness| and +% |\tolerance| to 10000, so that \TeX\ breaks lines whenever possible, +% even if this means high interword spacing. +% +% \begin{macrocode} + \if@tempswa% + \hbadness\@M% + \tolerance\@M% + \fi% +} +\define@key{parcolumns}{sloppyspaces}[true]{% + \pc@boolkey{@tempswa}{#1}% +% \end{macrocode} +% +% If sloppy spaces are asked for, we make the space stretchable: +% +% \begin{macrocode} + \if@tempswa% + \spaceskip.3333em\@plus1em % + \fi% +} +% \end{macrocode} +% +% +% We save the key-value-list containing widths of the columns in +% |\toks@| for later use in |\pc@setcolumnwidths|. +% +% \begin{macrocode} +\define@key{parcolumns}{colwidths}{% + \toks@{#1}% +} +% \end{macrocode} +% +% +% \subsection{Main environments and macros} +% +% \begin{environment}{parcolumns} +% +% Environment for a number of columns of text set in parallel (see +% section \ref{sec:Usage} on page \pageref{sec:Usage} for the possible +% options) +% +% Usage: |\begin{parcolumns}| \oarg{options} \marg{number of columns} +% \ldots\ |\end{parcolums}| +% +% \begin{macrocode} +\newenvironment{parcolumns}[2][]{% + \pc@rulebetweenfalse% +% \end{macrocode} +% +% |\if@tempswa| is |true|, if the indentation of the first line +% should be suppressed, otherwise |false|. Default is |false|: +% +% \begin{macrocode} + \@tempswafalse% +% \end{macrocode} +% +% |\@tempdimc| contains the space between two columns. Default +% is |2em|: +% +% \begin{macrocode} + \@tempdimc2em\relax% +% \end{macrocode} +% +% We set the options: +% +% \begin{macrocode} + \toks@{}% + \setkeys{parcolumns}{#1}% +% \end{macrocode} +% +% We store the total number of columns and reset the counter for +% the current column: +% +% \begin{macrocode} + \pc@columncount#2 % + \pc@columnctr\z@% +% \end{macrocode} +% +% We allocate the columns and set their widths: +% +% \begin{macrocode} + \pc@alloccolumns% + \pc@setcolumnwidths% +% \end{macrocode} +% +% We switch to vertical mode: +% +% \begin{macrocode} + \endgraf% +% \end{macrocode} +% +% As we are changing |\everypar|, we need to make sure that the most +% important flag is reset, which normally happens in the |\everypar| +% of a |\section|-command: |\if@nobreak|. (otherwise the next section +% is typeset directly after the text of the previous section instead +% of leaving some space)\footnote{I discovered this the hard way, +% spending one or two hours wondering why the spacing between two +% sections was much too small.} +% +% \begin{macrocode} + \@nobreakfalse% +% \end{macrocode} +% +% We reset |\everypar|, as it is of no use for us and can only screw +% up things badly: +% +% \begin{macrocode} + \global\everypar{}% +}{% +% \end{macrocode} +% +% At the end of the |parcolumns|-environment \ldots\ just in case, we +% place the last chunks, if not already done so: +% +% \begin{macrocode} + \colplacechunks% + \endgraf% +% \end{macrocode} +% +% We reset |\clubpenalty| globally to its normal value (the |\global| +% makes sure that if |\everypar| should have reset |\clubpenalty|, it +% is reset now). +% +% \begin{macrocode} + \global\clubpenalty\@clubpenalty% +% \end{macrocode} +% +% We suppress the indentation of the next paragraph immediately +% following the environment: +% +% \begin{macrocode} + \@doendpe% +} +% \end{macrocode} +% \end{environment} +% +% +% \begin{macro}{\colchunk} +% +% Sets the text for the next chunk of the next column. +% +% Usage: |\colchunk| \oarg{column} \marg{chunk}. (note that the |{| +% and |}| are \emph{not} optional, even if the chunk consists of only +% one token!) +% +% We need two macros for handling the optional parameter +% \meta{column}, |\colchunk| and |\colchunk@|. First we define +% |\colchunk|: +% +% \changes{1.1}{2004/08/22}{Optional parameter added.} +% +% \begin{macrocode} +\newcommand{\colchunk}{\@testopt\colchunk@{}}% +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\colchunk@} +% +% What are we doing now? By suffixing the last (optional) parameter by +% |#|, we tell \TeX\ that the last parameter of |\colchunk| is to be +% delimited by a right brace |{|, or \TeX\ will complain with a more +% comprehensible message that without the |#|: `Use of |\colchunk| +% doesn't match its definition.' instead of `Missing |{| inserted.' +% +% \changes{1.0.1}{2004/08/10}{Parameter added.} +% \changes{1.1}{2004/08/22}{Optional parameter added.} +% +% \begin{macrocode} +\long\def\colchunk@[#1]#{% +% \end{macrocode} +% +% We check if the optional parameter is not empty. Then we use it as +% the column number, otherwise we simply pick the next column: +% +% \begin{macrocode} + \ifx\\#1\\% + \advance\pc@columnctr\@ne% + \else% + \pc@columnctr#1\relax% + \fi% +% \end{macrocode} +% +% If we try to add a column past the last one, we display an error +% message: +% +% \begin{macrocode} + \ifnum\pc@columnctr>\pc@columncount% + \PackageError{parcolumns}{The column \number\pc@columnctr\space% + is too large}{Only \number\pc@columncount\space columns are% + \space allowed.} +% \end{macrocode} +% +% As we cannot simply skip the chunk (we could gobble what follows +% after the macro, but this would require a lot of jumping, and just +% for handling a small mistake \ldots), we simply set the last column: +% +% \changes{1.0.1}{2004/08/10}{Error handling somewhat improved.} +% +% \begin{macrocode} + \pc@columnctr\pc@columncount% + \fi% +% \end{macrocode} +% +% We zero the |\clubpenalty| that could have been changed, i.e. by +% |\everypar| of a |\section|-command: |\section| changes the +% clubpenalty to prevent a break between the first two lines of the +% paragraph following immediately after the section; as we split off +% line after line when typesetting the two columns, this would make +% splitting of a single line impossible (|\vsplit| uses the same logic +% as page-breaking), thus resulting in a lot of overfull vboxes and +% weird spacing inbetween, as \emph{two} lines would be split off. +% +% We do this every time we add chunks just in case some macro in the +% chunks has changed |\clubpenalty|. Note that we cannot prevent a +% macro in the text of the chunk to change the +% |\clubpenalty|.\footnote{Well we could, by redefining the +% clubpenalty to be a macro that simply throws its parameter away, and +% using some tricks to make this macro behave like a register, +% therefore completely ignoring any change of the clubpenalty.} But if +% it is changed, at least it will not stay changed (though the typeset +% columns will still look bad). +% +% \changes{1.0.1}{2004/08/09}{clubpenalty is always reset before +% adding chunks} +% +% \begin{macrocode} + \clubpenalty\z@% +% \end{macrocode} +% +% The same goes for the other penalties \TeX\ will insert between two +% lines, as we absolutely, positively \emph{must} be able to break +% between any two lines:\footnote{C.f. chapter 14 of the \TeX book} +% +% \changes{1.2}{2004/11/25}{other penalties added} +% +% \begin{macrocode} + \interlinepenalty\z@% + \displaywidowpenalty\z@% + \widowpenalty\z@% + \brokenpenalty\z@% +% \end{macrocode} +% +% We set |\everypar| to our self-defined |\pc@everypar| to suppress +% the indentation of the first paragraph if so desired: +% +% \begin{macrocode} + \everypar\expandafter{\the\pc@everypar}% +% \end{macrocode} +% +% After the next assignment, insert the width of the column: +% +% \begin{macrocode} + \afterassignment\pc@setcolumnwidth% +% \end{macrocode} +% +% We typeset the chunk's text into the box |\pc@column@|\meta{column +% counter}. The text of the chunk follows the macro, meaning that the +% last line looks like this: |\vbox{|\meta{chunk text}|}|. +% +% But what about the width of the box? |\hsize| must be set in the +% vbox in order to make it the correct width! We achieve this using +% the |\afterassignment| above: After the assignment of the chunk's +% text to the box, we are inside the box, therefore the contents of +% |\pc@setcolumnwidth| is inserted at the very beginning of the vbox, +% setting the correct width. +% +% Why don't we simply make |\colchunk| take one parameter that +% contains the text of the chunk? Because in that case, macros that +% change catcodes like |\verb| would be prohibited, which would +% restrict this package somewhat. Also it would be slower and would +% use more memory. +% +% \begin{macrocode} + \expandafter\setbox\csname pc@column@\number\pc@columnctr\endcsname% + \vbox% +} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\colplacechunks} +% +% Places all chunks set with |\colchunk|. +% +% \begin{macrocode} +\newcommand{\colplacechunks}{% +% \end{macrocode} +% +% If there are any chunks to place: +% +% \begin{macrocode} + \ifnum\pc@columnctr>\z@% +% \end{macrocode} +% +% We place them: +% +% \begin{macrocode} + \pc@placeboxes% +% \end{macrocode} +% +% We reset the column counter: +% +% \begin{macrocode} + \pc@columnctr\z@% +% \end{macrocode} +% +% We clear |\pc@everypar|, because we only want to suppress the +% indentation of the first paragraph of each column at the very top of +% the |parcolumns| environment, not of the first paragraph of every +% call to |\colchunk|. +% +% \begin{macrocode} + \pc@everypar{}% + \fi% +} +% \end{macrocode} +% \end{macro} +% +% +% +% +% \subsection{Internal environments and macros} +% +% \begin{macro}{\pc@placeboxes} +% +% Places the prepared boxes (containing the chunks) on the page. +% +% \begin{macrocode} +\def\pc@placeboxes{% +% \end{macrocode} +% +% We assume we don't have to perform another line (|\@tempa| contains +% what we have to to after we are finished with this macro). The +% assignment is global because later on when changing |\@tempa| we are +% in a group: +% +% \begin{macrocode} + \global\let\@tempa\relax% + \count@\z@% +% \end{macrocode} +% +% We create a hbox. Inside a hbox, vboxes are put horizontally +% next to each other and are aligned on their baseline: +% +% \begin{macrocode} + \hb@xt@\linewidth{% +% \end{macrocode} +% +% Before doing any work, we change a few parameters: +% +% \changes{1.2}{2004/11/22}{moved parameter changes from begin of +% environment} +% +% We prevent warnings of overfull and underfull vboxes as they can +% happen, but we do not really care (happens when we |\vsplit| the top +% off the chunks, this is okay): +% +% \changes{1.2}{2004/11/22}{vfuzz increased to prevent warnings with +% math} +% +% \changes{1.2}{2004/11/22}{vbadness set} +% +% \begin{macrocode} + \vfuzz30ex % + \vbadness\@M% +% \end{macrocode} +% +% We prevent vertical glue to be insert when |vsplit|ting a vbox +% (otherwise it screws up the spacing). +% +% \begin{macrocode} + \splittopskip\z@skip% +% \end{macrocode} +% +% Now we loop over all the prepared boxes. We can use |\loop| here as +% we are in a group (begun by |\hbox|). Otherwise we would have to +% open a group manually or loop manually, as to not screw up a |\loop| +% outside the macro: +% +% \begin{macrocode} + \loop\ifnum\count@<\pc@columncount% + \advance\count@\@ne% +% \end{macrocode} +% +% If the box |\pc@column@|\meta{counter} is empty, we simply insert a +% hskip the width of the box (saved in +% |\pc@column@width@|\meta{counter}): +% +% \begin{macrocode} + \expandafter\ifvoid\csname pc@column@\number\count@% + \endcsname% + \hskip\csname pc@column@width@\number\count@\endcsname% + \else% +% \end{macrocode} +% +% Otherwise we |\vsplit| the first line of the box (at the same time +% removing it from |\pc@column@|\meta{counter}) and save it in +% |\@tempboxa|. Then, we strip this resulting box of its enclosing +% vbox and put it into another vbox, which we put into the hbox begun +% a few lines ago. +% +% Why is this so complicated? To ensure that proper vertical glue is +% inserted (otherwise the spacing between the lines would be wrong). +% +% \begin{macrocode} + \expandafter\setbox\expandafter\@tempboxa\expandafter% + \vsplit\csname pc@column@\number\count@\endcsname% + to \dp\strutbox% + \vbox{\unvbox\@tempboxa}% + \fi% +% \end{macrocode} +% +% If the remaining box is not empty, we have to perform at least +% another line: +% +% \begin{macrocode} + \expandafter\ifvoid\csname pc@column@\number\count@% + \endcsname\else% + \global\let\@tempa\pc@placeboxes% + \fi% +% \end{macrocode} +% +% If this is not the last column, we put a strut into the hbox to +% ensure propery vertical spacing: +% +% \begin{macrocode} + \ifnum\count@<\pc@columncount% + \strut% +% \end{macrocode} +% +% If a vertical line should be placed between two columns, we insert +% it now, centering it between two |\hfill|s. Otherwise, we simply +% insert a |\hfill| that stretches as much as possible, pushing the +% right column to the right margin. (see also section \ref{sec:Notes} +% on page \pageref{sec:Notes}) +% +% \begin{macrocode} + \hfill% + \ifpc@rulebetween% + \vrule% + \hfill% + \fi% + \fi% + \repeat% + }% +% \end{macrocode} +% +% If necessary, we perform another line: +% +% \begin{macrocode} + \@tempa% +} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\pc@alloccolumns} +% +% Allocates a number of |\box|es, named |\pc@column@1|, |\pc@column@2| +% et cetera, if not already allocated. +% +% Also allocates a number of |\dimen|s, named |\pc@column@width@1| et +% cetera. +% +% If the |\box|es and |\dimen|s are already allocated, they are +% cleared (|\box|es) or set to zero (|\dimen|s). +% +% \begin{macrocode} +\def\pc@alloccolumns{% + \count@\z@% + \loop\ifnum\count@<\pc@columncount% + \advance\count@\@ne% + \@ifundefined{pc@column@\number\count@}{% + \expandafter\newbox\csname pc@column@\number\count@% + \endcsname% + \expandafter\newdimen\csname pc@column@width@\number% + \count@\endcsname% + }{% + \setbox0\box\csname pc@column@\number\count@\endcsname% + \csname pc@column@width@\number\count@\endcsname\z@% + }% + \repeat% +} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\pc@setcolumnwidths} +% +% Sets the widths of all columns. The defined widths have been +% temporarily stored in |\toks@|. |\@tempdimc| contains the space +% between two columns. +% +% \begin{macrocode} +\def\pc@setcolumnwidths{% + \expandafter\processkeyvalues\expandafter{\the\toks@}% + \pc@setsinglecolwidth% +% \end{macrocode} +% +% |\@tempdima| will contain the total width of all columns that have a +% known width (read: have had their width set via the parameter +% |colwidths|) +% +% \begin{macrocode} + \@tempdima\z@% +% \end{macrocode} +% +% |\@tempcnta| will contain the count of columns that an unknown width +% (read: have had their width \emph{not} set via the parameter +% |colwidths|, thus now having a width of zero points, as the widths +% of all columns have been reset in |\pc@alloccolumns|): +% +% \begin{macrocode} + \@tempcnta\z@% +% \end{macrocode} +% +% We calculate the total width of all columns known. We count how many +% columns have an unknown width: +% +% \begin{macrocode} + \count@\z@% + \loop\ifnum\count@<\pc@columncount% + \advance\count@\@ne% + \@tempdimb\csname pc@column@width@\number\count@\endcsname% + \advance\@tempdima\@tempdimb% + \ifnum\@tempdimb=\z@% + \advance\@tempcnta\@ne% + \else% + \PackageInfo{parcolumns}{Width of column \number\count@% + \space set to \the\@tempdimb} + \fi% + \repeat% +% \end{macrocode} +% +% If at least one column has an unknown width: +% +% \begin{macrocode} + \ifnum\@tempcnta>\z@% +% \end{macrocode} +% +% |\@tempdimc| contains the distance between columns. We calculate the +% space left for the columns with an unknown width. +% +% |\@tempdimb| will contain the sum of the space between all the +% columns \ldots +% +% \begin{macrocode} + \@tempdimb\@tempdimc% + \multiply\@tempdimb\pc@columncount% + \advance\@tempdimb-\@tempdimc% +% \end{macrocode} +% +% \ldots\ plus the sum of the width of all columns with a known width: +% +% \begin{macrocode} + \advance\@tempdimb\@tempdima% +% \end{macrocode} +% +% |\@tempdima| will contain the space for each column with an unknown +% width: +% +% \begin{macrocode} + \@tempdima\linewidth% + \advance\@tempdima-\@tempdimb% + \divide\@tempdima\@tempcnta% +% \end{macrocode} +% +% We set the widths of the colums with an unknown width: +% +% \begin{macrocode} + \count@\z@% + \loop\ifnum\count@<\pc@columncount% + \advance\count@\@ne% + \ifnum\csname pc@column@width@\number\count@\endcsname=\z@% + \csname pc@column@width@\number\count@\endcsname\@tempdima% + \PackageInfo{parcolumns}{Width of column \number\count@% + \space calculated as \the\@tempdima} + \fi% + \repeat% + \fi% +} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\pc@setsinglecolwidth} +% +% Usage: |\pc@setsinglecolwidth| \marg{column} \marg{width}. +% +% Sets the width of the column \meta{column} to the width +% \meta{width}. Displays an error message if the column is not valid. +% +% \begin{macrocode} +\def\pc@setsinglecolwidth#1#2{% + \@ifundefined{pc@column@width@\number#1}{ + \PackageError{parcolumns}{`#1' is not a valid column number!}% + {\@ehc}% + }{% + \csname pc@column@width@\number#1\endcsname=#2\relax% + }% +} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\pc@setcolumnwidth} +% +% Sets |\hsize| to the width of a column (stored in +% |\pc@column@width@|\meta{pc@columnctr}) and enters horizonal mode. +% +% \changes{1.2}{2004/11/22}{linewidth set, too} +% +% \begin{macrocode} +\def\pc@setcolumnwidth{% + \hsize\csname pc@column@width@\number\pc@columnctr\endcsname% + \linewidth\hsize% + \leavevmode% +} +% \end{macrocode} +% \end{macro} +% +% +% \Finale +% \PrintChanges +% \PrintIndex +\endinput \ No newline at end of file diff --git a/macros/latex/contrib/sauerj/parcolumns.ins b/macros/latex/contrib/sauerj/parcolumns.ins new file mode 100644 index 0000000000..a03684bd8a --- /dev/null +++ b/macros/latex/contrib/sauerj/parcolumns.ins @@ -0,0 +1,19 @@ +\input docstrip +\keepsilent +\askforoverwritefalse + +\preamble +\endpreamble +\generate{% + \file{\jobname.sty}{\from{\jobname.dtx}{package}} +} + +\Msg{***************************************************************} +\Msg{*} +\Msg{* \space To finish the installation you have to copy the files} +\Msg{*} +\Msg{* \space *.sty into a directory searched by TeX} +\Msg{*} +\Msg{***************************************************************} + +\endbatchfile \ No newline at end of file diff --git a/macros/latex/contrib/sauerj/parcolumns.pdf b/macros/latex/contrib/sauerj/parcolumns.pdf new file mode 100644 index 0000000000..c500dd4c2b Binary files /dev/null and b/macros/latex/contrib/sauerj/parcolumns.pdf differ diff --git a/macros/latex/contrib/sauerj/processkv.dtx b/macros/latex/contrib/sauerj/processkv.dtx new file mode 100644 index 0000000000..520853917f --- /dev/null +++ b/macros/latex/contrib/sauerj/processkv.dtx @@ -0,0 +1,199 @@ +% \iffalse meta-comment +% Line endings: UNIX +% Tab size: 4 +% +% Copyright 2004 Jonathan Sauer +% +% This work 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 Jonathan Sauer +% (). +% +% This work consists of the files processkv.dtx and processkv.ins and +% the derived file processkv.sty. +% +% This work is based on the package keyval. +% +% \fi +% +% \iffalse +% +%<*driver> +\documentclass{ltxdoc} +\IfFileExists{processkv.sty}{\usepackage{processkv}}{} +\EnableCrossrefs +\CodelineIndex +\RecordChanges +% Modification of verbatim for tabs in listings +\makeatletter +{\catcode`\ =\active% +\catcode`\^^I=\active% +\gdef\@vobeyspaces{% +\catcode`\ \active\let \@xobeysp% +\catcode`\^^I\active\def^^I{~~}% +}}% +\makeatother +\begin{document} + \DocInput{\jobname.dtx} +\end{document} +% +% +%\NeedsTeXFormat{LaTeX2e} +%\ProvidesPackage{processkv} +% [2004/08/09 v1.0.1 process key=value lists] +%\RequirePackage{keyval}[1999/03/16] +% +% \fi +% +% \CheckSum{41} +% \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 \~} +% +% \DoNotIndex{\@empty,\@tempa,\@tempb,\def,\else,\empty,\expandafter} +% \DoNotIndex{\fi,\ifx,\relax} +% +% \changes{1.0.1}{2004/08/09}{Mangled macronames corrected.} +% +% \GetFileInfo{\jobname.sty} +% +% \title{The \textsf{processkv} package\thanks{This document +% corresponds to \textsf{\filename}~\fileversion, dated \filedate.}} +% +% \author{Jonathan Sauer \\ \texttt{jonathan.sauer@gmx.de}} +% +% \date{\filedate} +% +% \maketitle +% +% \begin{abstract} +% This file describes the \textsf{processkv} package that provides +% macros for processing of key-value-lists by calling a user-defined +% macro for each key-value-pair. +% +% \end{abstract} +% +% \tableofcontents +% +% \section{Introduction} +% +% The \textsf{keyval} package provides the possibility of specifying +% macro arguments as |key=value|, where |key| is one of previously +% defined keys. Sometimes it is necessary not to have to define the +% keys in advance, but to specify arbitrary keys which are then +% processed. +% +% This package provides the macro |\processkeyvalues| that calls a +% user-defined macro for each key-value-pair. +% +% This package makes use of some internal macros of the package +% \textsf{keyval}. I hope this will not break someday \ldots +% +% +% \section{Using the package} +% +% \DescribeMacro{\processkeyvalues} Usage: |\processkeyvalues| +% \marg{keyvalue-list} \marg{macro}. +% +% The main macro of this package. It calls \meta{macro} for each +% key-value-pair in \meta{keyvalue-list}. Macros in the list are not +% expanded. +% +% \meta{macro} can be any macro with two parameters, i.e: +% +% \begin{verbatim} +% \def\testmacro#1#2{% +% \message{Key = `#1', value = `#2'}% +% } +% \end{verbatim} +% Or +% +% \begin{verbatim} +% \newcommand{\testmacro}[2]{% +% \message{Key = `#1', value = `#2'}% +% } +% \end{verbatim} +% +% +% \StopEventually{} +% +% \section{Implementation} +% +% \subsection{Main macros} +% +% \begin{macro}{\processkeyvalues} +% +% Usage: |\processkeyvalues| \marg{keyvalue-list} \marg{macro}. +% +% Calls \meta{macro} for each key-value-pair in the list. \meta{macro} +% must have two parameters, \meta{key} and \meta{value}. +% +% \begin{macrocode} +\def\processkeyvalues#1#2{% + \def\PKV@process{#2}% + \PKV@do#1,\relax,% +} +% \end{macrocode} +% \end{macro} +% +% +% \subsection{Internal macros} +% +% \begin{macro}{\PKV@do} +% +% Processes the list. +% +% \begin{macrocode} +\def\PKV@do#1,{% + \ifx\relax#1\empty\else% + \PKV@split#1==\relax% + \expandafter\PKV@do\fi% +} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\PKV@split} +% +% Processes a key-value-pair of the list. Uses some macros of the +% \textsf{keyval} package. +% +% \begin{macrocode} +\def\PKV@split#1=#2=#3\relax{% + \KV@@sp@def\@tempa{#1}% + \ifx\@tempa\@empty\else% + \KV@@sp@def\@tempb{#2}% + \expandafter\expandafter\expandafter\PKV@process% + \expandafter\expandafter\expandafter{\expandafter\@tempa% + \expandafter}\expandafter{\@tempb}% + \fi% +} +% \end{macrocode} +% \end{macro} +% +% \Finale +% \PrintChanges +% \PrintIndex +\endinput \ No newline at end of file diff --git a/macros/latex/contrib/sauerj/processkv.ins b/macros/latex/contrib/sauerj/processkv.ins new file mode 100644 index 0000000000..a03684bd8a --- /dev/null +++ b/macros/latex/contrib/sauerj/processkv.ins @@ -0,0 +1,19 @@ +\input docstrip +\keepsilent +\askforoverwritefalse + +\preamble +\endpreamble +\generate{% + \file{\jobname.sty}{\from{\jobname.dtx}{package}} +} + +\Msg{***************************************************************} +\Msg{*} +\Msg{* \space To finish the installation you have to copy the files} +\Msg{*} +\Msg{* \space *.sty into a directory searched by TeX} +\Msg{*} +\Msg{***************************************************************} + +\endbatchfile \ No newline at end of file diff --git a/macros/latex/contrib/sauerj/processkv.pdf b/macros/latex/contrib/sauerj/processkv.pdf new file mode 100644 index 0000000000..c85bb6b52a Binary files /dev/null and b/macros/latex/contrib/sauerj/processkv.pdf differ diff --git a/macros/latex/contrib/sauerj/zahl2string.dtx b/macros/latex/contrib/sauerj/zahl2string.dtx new file mode 100644 index 0000000000..c332c1d087 --- /dev/null +++ b/macros/latex/contrib/sauerj/zahl2string.dtx @@ -0,0 +1,1044 @@ +% \iffalse meta-comment +% Line endings: UNIX +% Tab size: 4 +% +% Copyright 2004 Jonathan Sauer +% +% This work 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 Jonathan Sauer +% (). +% +% This work consists of the files zahl2string.dtx and zahl2string.ins +% and the derived file zahl2string.sty. +% +% \fi +% +% \iffalse +% +%<*driver> +\documentclass{ltxdoc} +\usepackage{zahl2string} +\EnableCrossrefs +\CodelineIndex +\RecordChanges +% Modification of verbatim for tabs in listings +\makeatletter +{\catcode`\ =\active% +\catcode`\^^I=\active% +\gdef\@vobeyspaces{% +\catcode`\ \active\let \@xobeysp% +\catcode`\^^I\active\def^^I{~~}% +}}% +\makeatother +\begin{document} + \DocInput{\jobname.dtx} +\end{document} +% +% +%\NeedsTeXFormat{LaTeX2e} +%\ProvidesPackage{zahl2string} +% [2004/11/25 v1.2.1 format a number as german words] +% +% \fi +% +% \CheckSum{331} +% \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 \~} +% +% \DoNotIndex{\",\@empty,\@M,\@m,\@tempa,\csname,\DeclareOption} +% \DoNotIndex{\DeclareRobustCommand,\def} +% \DoNotIndex{\else,\endcsname,\expandafter,\fi,\if,\ifcase} +% \DoNotIndex{\ifnum,\let,\MakeUppercase,\newcommand,\number,\or} +% \DoNotIndex{\PackageError,\PackageWarning,\ProcessOptions} +% \DoNotIndex{\protected@edef,\relax,\space,\ss,\string,\z@} +% \DoNotIndex{\@ne,\@nil,\-} +% +% \GetFileInfo{\jobname.sty} +% +% \changes{1.1}{2004/08/08}{Range expanded to 999,999,999.} +% \changes{1.2.1}{2004/10/20}{@Numstring and @Ordstring made robust.} +% +% \title{The \textsf{zahl2string} package\thanks{This document +% corresponds to \textsf{\filename}~\fileversion, dated \filedate.}} +% +% \author{Jonathan Sauer \\ \texttt{jonathan.sauer@gmx.de}} +% +% \date{\filedate} +% +% \maketitle +% +% \begin{abstract} +% This file describes the \textsf{zahl2string} package that provides +% macros for formatting numbers as german words, i.e. `1' gets +% formatted as `eins'. +% +% \end{abstract} +% +% \tableofcontents +% +% \section{Introduction} +% +% Sometimes, for example when formatting a chapter title, you do not +% want to say `Kapitel 1' (`Chapter 1') but `Kapitel eins' (`Chapter +% one') or `Erstes Kapitel' (`First chapter'). This package provides +% macros to format a \LaTeX-counter or more generally speaking a +% number as a german word. +% +% +% \section{Description of the macros} +% +% All macros format numbers in the range 0 to 999,999,999. Larger +% numbers are formatted as an arabic number, smaller numbers are +% formatted as zero. This can be changed using the package options +% described on page \pageref{sec:Options}. +% +% \subsection{\LaTeX\ macros} +% +% The four macros |\numstring|, |\Numstring|, |\ordstring| and +% |\Ordstring| are macros taking a \LaTeX-counter as their only +% argument. +% +% \DescribeMacro{\numstring} Usage: |\numstring| \marg{LaTeX counter}. +% +% Formats a \LaTeX\ counter in the range of 0 to 999,999,999 as a +% word. +% +% \DescribeMacro{\Numstring} Usage: |\Numstring| \marg{LaTeX counter}. +% +% Formats a \LaTeX\ counter in the range of 0 to 999,999,999 as words, +% where the first letter is a capital letter. +% +% \DescribeMacro{\ordstring} Usage: |\ordstring| \marg{LaTeX counter}. +% +% Formats a \LaTeX\ counter in the range of 0 to 999,999,999 as an ordinal +% word. +% +% \DescribeMacro{\Ordstring} Usage: |\Ordstring| \marg{LaTeX counter}. +% +% Formats a \LaTeX\ counter in the range of 0 to 999,999,999 as an ordinal +% word, where the first letter is a capital letter. +% +% +% +% \subsection{General macros} +% +% The four macros |\@numstring|, |\@Numstring|, |\@ordstring| and +% |\@Ordstring| as well as their aliases |\numstr|, |\Numstr|, +% |\ordstr| and |\Ordstr| are macros taking a number or a \TeX\ count +% register as their only argument. +% +% \DescribeMacro{\@numstring} \DescribeMacro{\numstr} Usage: +% |\@numstring| \marg{number} / |\numstr| \marg{number}. +% +% Formats a number or a \TeX\ count register in the range of 0 to +% 999,999,999 as words. +% +% \DescribeMacro{\@Numstring} \DescribeMacro{\Numstr} Usage: +% |\@Numstring| \marg{number} / |\Numstr| \marg{number}. +% +% Formats a number or a \TeX\ count register in the range of 0 to +% 999,999,999 as words, where the first letter is a capital letter. +% +% \DescribeMacro{\@ordstring} \DescribeMacro{\ordstr} Usage: +% |\@ordstring| \marg{number} / |\ordstr| \marg{number}. +% +% Formats a number or a \TeX\ count register in the range of 0 to +% 999,999,999 as an ordinal word. +% +% \DescribeMacro{\@Ordstring} \DescribeMacro{\Ordstr} Usage: +% |\@Ordstring| \marg{number} / |\Ordstr| \marg{number}. +% +% Formats a number or a \TeX\ count register in the range of 0 to +% 999,999,999 as an ordinal word, where the first letter is a capital +% letter. +% +% ^^A For debugging discretionary hyphens: +% ^^A\def\-{.\discretionary{}{}{}} +% +% +% +% \section{Examples} +% +% \newcommand{\zahlexamples}[1]{ +% 0 $\Longrightarrow$ #1{0} +% +% 7 $\Longrightarrow$ #1{7} +% +% 13 $\Longrightarrow$ #1{13} +% +% 23 $\Longrightarrow$ #1{23} +% +% 42 $\Longrightarrow$ #1{42} +% +% 99 $\Longrightarrow$ #1{99} +% +% 127 $\Longrightarrow$ #1{127} +% +% 999 $\Longrightarrow$ #1{999} +% +% 1000 $\Longrightarrow$ #1{1000} +% +% 1001 $\Longrightarrow$ #1{1001} +% +% 2004 $\Longrightarrow$ #1{2004} +% +% 2017 $\Longrightarrow$ #1{2017} +% +% 2029 $\Longrightarrow$ #1{2029} +% +% 9999 $\Longrightarrow$ #1{9999} +% +% 10000 $\Longrightarrow$ #1{10000} +% +% 101101 $\Longrightarrow$ #1{101101} +% +% 999999 $\Longrightarrow$ #1{999999} +% +% 1000000 $\Longrightarrow$ #1{1000000} +% +% 1234567 $\Longrightarrow$ #1{1234567} +% +% 123456789 $\Longrightarrow$ #1{123456789} +% +% 101101101 $\Longrightarrow$ #1{101101101} +% +% 999999999 $\Longrightarrow$ #1{999999999} +% } +% +% \addvspace{\baselineskip}\noindent Some examples using |\numstring|, +% |\numstr| and |\@numstring|: +% +% \zahlexamples{\numstr} +% +% \addvspace{\baselineskip}\noindent Some examples using |\ordstring|, +% |\ordstr| and |\@ordstring|: +% +% \zahlexamples{\ordstr} +% +% +% \addvspace{\baselineskip}\noindent Formatting the current page +% number (a \LaTeX\ counter) results in: Dies ist Seite +% \numstring{page} (|\numstring{page}|). Dies ist die \ordstring{page} +% Seite (|\ordstring{page}|). Seite: \Numstring{page} +% (|\Numstring{page}|). \Ordstring{page} Seite (|\Ordstring{page}|). +% +% +% +% \section{Options}\label{sec:Options} +% +% The package has the following option: +% +% \begin{description} +% \item[showrangeerrors] If a number larger than 999,999,999 +% is to be formatted, normally the number +% is not formatted as words, but using +% arabic digits. This option changes this +% behaviour to display an error instead, +% thus notifying you when you format too +% large a number +% +% \end{description} +% +% +% +% \section{Creating your own formatting} +% +% You can modify output of the \textsf{zahl2string} macros in a +% limited way by providing your own macros for formatting the numbers +% between `1' and `19. \emph{But note} that if you simply want to add +% something to the suffix, , i.e. if you want to format numbers with +% the suffix `tens' (`erstens', `zweitens' \ldots), then you can +% simply say |\ordstr{|\meta{number}|}ns|, resulting in i.e. +% `\ordstr{42}ns'. +% +% +% If on the other hand you want to create a more complicated +% formatting, then you have to do the following: +% +% \begin{itemize} +% \item Create a macro for formatting the numbers `1' to `19', +% i.e. |\my@neunzehnte|. See the predefined macros in +% section \ref{sec:LabFor} on page \pageref{sec:LabFor}, +% |\ns@neunzehn|, |\ns@neunzehns|, |\ns@neunzehne| and +% |\ns@neunzehnord| for examples and notes. +% +% This macro has one parameter, the number (up to two +% digits, in the range of `0' to `19'. `0' must expand to the +% generic suffix, i.e. `stens'; `19' to `19' simply format +% the number. +% +% Do not forget to insert discretionary hyphens using |\-|, +% or hyphenation will not be perfect! +% +% \item Create another macro you want to call, i.e. |\mynumstring|. +% This macro takes one parameter, the number, and calls +% |\ns@numstr| using the following parameters: +% +% \begin{enumerate} +% \item The number to be formatted (the parameter to +% |\mynumstring|). +% +% \item The macro for formatting numbers `1' to `19', +% i.e. |\my@neunzehnte|. +% +% \item The value that represents the number zero, +% i.e. `nulltens'. +% +% \item The suffix for numbers larger than 999,999,999, +% i.e. `tens'. +% +% \end{enumerate} +% +% \item Call the macro |\mynumstring| with the number to format. +% +% \end{itemize} +% If you want to create a macro to format a \LaTeX-counter, create an +% additional macro, i.e. |\myLnumstring|, that calls |\mynumstring| by +% saying: +% +% \begin{verbatim} +% \newcommand{\myLnumstring}[1]{% +% \expandafter\mynumstring\csname c@#1\endcsname% +% } +% \end{verbatim} +% See also the notes and predefined macros in section \ref{sec:LabFor} +% on page \pageref{sec:LabFor}. +% +% +% +% \section{Notes/Limitations} +% +% \begin{itemize} +% +% \item Ordinal numbers larger than 999999 do not look that +% good, as i.e. 1000000 gets formatted as +% `\ordstr{1000000}' instead of `einmillionste'. +% +% \end{itemize} +% +% +% +% \StopEventually{} +% +% \section{Implementation} +% +% \subsection{Main macros} +% +% +% \begin{macro}{\numstring} +% +% Usage: |\numstring| \marg{LaTeX counter}. +% +% Formats a \LaTeX\ counter in the range of 0 to 999,999,999 as words. +% +% \begin{macrocode} +\newcommand{\numstring}[1]{% + \expandafter\@numstring\csname c@#1\endcsname% +} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\Numstring} +% +% Usage: |\Numstring| \marg{LaTeX counter}. +% +% Formats a \LaTeX\ counter in the range of 0 to 999,999,999 as words. The +% first letter is uppercase. +% +% \begin{macrocode} +\newcommand{\Numstring}[1]{% + \expandafter\@Numstring\csname c@#1\endcsname% +} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\ordstring} +% +% Usage: |\ordstring| \marg{LaTeX counter}. +% +% Formats a \LaTeX\ counter in the range of 0 to 999,999,999 as an ordinal +% word. +% +% \begin{macrocode} +\newcommand{\ordstring}[1]{% + \expandafter\@ordstring\csname c@#1\endcsname% +} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\Ordstring} +% +% Usage: |\Ordstring| \marg{LaTeX counter}. +% +% Formats a \LaTeX\ counter in the range of 0 to 999,999,999 as an ordinal +% word. The first letter is uppercase. +% +% \begin{macrocode} +\newcommand{\Ordstring}[1]{% + \expandafter\@Ordstring\csname c@#1\endcsname% +} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\@numstring} +% +% Usage: |\@numstring| \marg{number or \TeX\ count register}. +% +% Formats a number or a \TeX\ count register in the range of 0 to +% 999,999,999 as words. +% +% \begin{macrocode} +\newcommand{\@numstring}[1]{% + \ns@numstr{#1}\ns@neunzehns{null}{}% +} +% \end{macrocode} +% +% \end{macro} +% +% +% \begin{macro}{\@Numstring} +% +% Usage: |\@Numstring| \marg{number or \TeX\ count register}. +% +% Formats a number or a \TeX\ count register in the range of 0 to +% 999,999,999 as words. The first letter is uppercase. +% +% \begin{macrocode} +\newcommand\@Numstring[1]{% + \expandafter\@@Numstring\expandafter{\number#1}% +} +% \end{macrocode} +% +% \end{macro} +% +% +% \begin{macro}{\@@Numstring} +% +% Support macro for |\@Numstring| to make |\@Numstring| robust. +% +% \changes{1.2.1}{2004/10/20}{Added} +% +% \begin{macrocode} +\DeclareRobustCommand{\@@Numstring}[1]{% + \protected@edef\@tempa{\@numstring{#1}}% + \expandafter\MakeUppercase\@tempa% +} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\@ordstring} +% +% Usage: |\@ordstring| \marg{number or \TeX\ count register}. +% +% Formats a number or a \TeX\ count register in the range of 0 to +% 999,999,999 as an ordinalword, i.e. `erste', `zweite' et cetera. +% +% \begin{macrocode} +\newcommand{\@ordstring}[1]{% + \ns@numstr{#1}\ns@neunzehnord{null\-te}{te}% +} +% \end{macrocode} +% +% \end{macro} +% +% +% \begin{macro}{\@Ordstring} +% +% Usage: |\@Ordstring| \marg{number or \TeX\ count register}. +% +% Formats a number or a \TeX\ count register in the range of 0 to +% 999,999,999 as an ordinalword, i.e. `Erste', `Zweite' et cetera. The +% first letter is uppercase. +% +% \begin{macrocode} +\newcommand{\@Ordstring}[1]{% + \expandafter\@@Ordstring\expandafter{\number#1}% +} +% \end{macrocode} +% +% \end{macro} +% +% +% \begin{macro}{\@@Ordstring} +% +% Support macro for |\@Ordstring| to make |\@Ordstring| robust. +% +% \changes{1.2.1}{2004/10/20}{Added} +% +% \begin{macrocode} +\DeclareRobustCommand{\@@Ordstring}[1]{% + \protected@edef\@tempa{\@ordstring{#1}}% + \expandafter\MakeUppercase\@tempa% +} +% \end{macrocode} +% \end{macro} +% +% +% +% We provide public aliases for the macros. The macros beginning with +% |@| are still necessary in order to be able to format the page +% number as a string. (see \textsf{ltpageno.dtx}) +% +% \changes{1.2}{2004/09/08}{Added} +% +% \begin{macrocode} +\let\numstr\@numstring% +\let\Numstr\@Numstring% +\let\ordstr\@ordstring% +\let\Ordstr\@Ordstring% +% \end{macrocode} +% +% +% \subsection{Option processing} +% +% \changes{1.1}{2004/08/13}{Options `publicnumstr' and `showrangeerrors' +% added.} +% \changes{1.2}{2004/09/08}{Option `publicnumstr' deprecated} +% +% \begin{macrocode} +\DeclareOption{publicnumstr}{% + \PackageWarning{zahl2string}{Option `publicnumstr' is % + deprecated and will be removed in version 1.3}% +} +% \end{macrocode} +% +% +% \begin{macro}{\ns@numoutofrange} +% +% Formats a number that is too large to be formatted as words. +% +% Usage: |\ns@numoutofrange| \marg{number} \marg{suffix}. +% +% This macro is redefined to show an error message using the package +% option |showrangeerrors|. +% +% \begin{macrocode} +\def\ns@numoutofrange#1#2{% + \number#1#2% +} +% \end{macrocode} +% \end{macro} +% + +% \begin{macrocode} +\DeclareOption{showrangeerrors}{% + \def\ns@numoutofrange#1#2{% + \PackageError{zahl2string}{The number `#1' is too large % + to be formatted using zahl2string}{The largest possible % + number is 999,999,999.} + }% +} +% \end{macrocode} +% +% +% +% \begin{macrocode} +\ProcessOptions\relax +% \end{macrocode} +% +% +% +% \subsection{Internal macros} +% +% \subsubsection{Splitting and formatting a number} +% +% \begin{macro}{\ns@numstr} +% +% Base macro for formatting a number. +% +% Usage: |\ns@numstr| \marg{number} \marg{macro} \marg{nullvalue} +% \marg{suffix}, where \meta{macro} is the macro to use for the +% numbers between |1| and |19|, as these require some special +% treatment, \meta{nullvalue} is the value this macro expands to when +% \meta{number} is zero, and \meta{suffix} is text added as a suffix +% to a number larger than 999,999,999. +% +% \changes{1.1}{2004/08/08}{Macro added} +% +% \begin{macrocode} +\def\ns@numstr#1#2#3#4{% + \ifnum\number#1<\@ne% + #3% + \else\ifnum\number#1<1000000000 % + \expandafter\ns@numstring\expandafter{\number#1}#2% + \else% + \ns@numoutofrange{#1}{#4}% + \fi\fi% +} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\ns@numstring} +% +% \changes{1.1}{2004/08/14}{Reimplemented to avoid using up TeX's +% space for control sequences} +% +% Formats a number as words. +% +% Usage: |\ns@numstring| \marg{number} \marg{macro}, where +% \meta{macro} is the macro to use for the numbers between |1| and +% |19|, as these require some special treatment. +% +% \emph{Note: \meta{number} must be a real number consisting of digits +% in the range 0 to 9! It must not be a \TeX\ count register!} +% +% How does this work? Modulo operations are not trivial in \TeX\ as in +% order to achieve $a \bmod b$ you have to calculate $a - (a \div b) +% \times b$. This is complicated and also not expandable, so another +% solution has to be found. +% +% \TeX's capabilities of parsing text using macro arguments are fairly +% strong, so why not use them? It would be much easier if it would be +% possible of defining a macro with, say, six parameters, where each +% parameter is one digit of the number to be formatted. Then it would +% be possible to directly access each digit (or several digits +% combined by grouping several parameters) without having to perform +% lengthy modulo calculations. +% +% Adding leading zeros to a number is easily done by comparing it +% using |\ifnum| and adding zeros if the number is too small. However, +% the macro must not receive the |\ifnum| et.al. tokens as a +% parameter, but the result of the expansion, that is the number with +% leading zeros. +% +% |\expandafter| would not suffice, as it expands a macro only once, +% not fully. |\edef| would accomplish the task at hand, however +% |\edef| is not fully expandable. +% +% So what do we do? We take advantage of the fact that when expanding +% an |\ifcase|, \TeX\ goes on expanding until it has made sure that +% the number for the |\ifcase| is complete. So immediately after the +% |\ifcase| we launch into several nested |\ifnum|s, which \TeX\ +% expands dutifully in order to determine the number to use. +% +% What these nested |\ifnum|s do is the following: Depending on the +% length of \meta{number}, they expand to a digit between one and +% nine, one being the digit if \meta{number} is less than 10 and nine +% being the digit if \meta{number} is larger than 99,999,999. +% +% Then \TeX\ uses this digit between one and nine to jump to the +% appropriate part of the |\ifcase|-clause. There \meta{number} is +% prefixed with the necessary amount of zeros to result in a number +% exactly nine digits long: For the digit one (resulting from the +% nested |\ifnum|s), eight leading zeros have to be prefixed, as +% \meta{number} is only one digit long, for the digit two, seven zeros +% are prefixed, as \meta{number} is less than 100 (but more than 9) et +% cetera, until for digit nine no zeros have to be prefixed, as +% \meta{number} is already nine digits long. +% +% Let's have an example: Suppose \meta{number} is 42. Then the result +% of the nested |\ifnum|s is 2, as \meta{number} is not less than 10 +% but less than 100 (the second |\ifnum| is true). This 2 leads to +% jumping to part after the second |\or| (before the first |\or| is +% the part for the number 0, in this case left blank, and after the +% first |\or| for the number 1), which is |0000000#1|. |#1| is 42. So +% the result is: |000000042|, a number prefixed with leading zeros and +% exactly nine digits long. +% +% Another example: Suppose \meta{number} is 12,345,678. Then the +% result of the nested |\ifnum|s is 8, as the eigths |\ifnum| is true +% (less than 100,000,000 but not less than 10,000,000). Then only one +% zero is prefixed, resulting in |012345678|. +% +% However, we are not finished yet, as \TeX\ does not expand further. +% So we are left (picking up the second example above) with this: +% |012345678\or12345678\or| (the second incarnation of |12345678| is +% due to the ninth part of the |\ifcase| clause, |\or#1|). +% +% We do not need all this |\or| baggage, we only want the number. But +% \TeX\ is good at matching text using macros with delimited +% parameters, so we just define |\ns@@numstring| in a way that gobbles +% up the first |\or| and whatever follows. +% +% And we are done: We have a number padded perfectly with leading +% zeros to a length of nine digits! +% +% \paragraph{Implementation note} In Version 1.0, we used |\csname| +% \ldots\ |\endcsname| to add the leading zeros, as |\csname| \ldots\ +% |\endcsname| expands everything inbetween until only unexpandable +% tokens remain, in this case digits (the |\ifnum|s are expanded). +% Afterwards, the resulting control sequence was converted into +% separate tokens using |\string| and finally, the backslash at the +% beginning was gobbled by |\ns@@numstring| as its first (and unused) +% argument. +% +% Unfortunately, this had its price: For every number we formatted +% using |\ns@numstring| and that had not been formatted before, a new +% entry was inserted into the hash table \TeX\ uses to store all +% control sequences. So if you had a document where you formatted a +% lot of numbers this way, you would run out of hash table space, and +% \TeX\ would complain. (The number of hash table entries used is +% indicated in the |log|-file as `multiletter control sequences'.) +% +% This was less than optimal, so we changed the implementation to this +% |\ifcase|-|\ifnum| construct. +% +% \begin{macrocode} +\def\ns@numstring#1#2{% + \expandafter\ns@@numstring% + \ifcase% + \ifnum#1<10 1% +% \end{macrocode} +% +% Why are the constants predefined by the \LaTeX-kernel used instead +% of numbers? Because they save tokens: |1000| are four tokens, |\@m| +% is only one. +% +% \begin{macrocode} + \else\ifnum#1<100 2% + \else\ifnum#1<\@m 3% + \else\ifnum#1<\@M 4% + \else\ifnum#1<100000 5% + \else\ifnum#1<1000000 6% + \else\ifnum#1<10000000 7% + \else\ifnum#1<100000000 8% + \else9% + \fi\fi\fi\fi\fi\fi\fi\fi % + \or00000000#1% case 1: Add 8 leading zeros + \or0000000#1% case 2: Add 7 leading zeros + \or000000#1% case 3: Add 6 leading zeros + \or00000#1% case 4: Add 5 leading zeros + \or0000#1% case 5: Add 4 leading zeros + \or000#1% case 6: Add 3 leading zeros + \or00#1% case 7: Add 2 leading zeros + \or0#1% case 8: Add 1 leading zero + \or#1% case 9: Add no leading zeros +% \end{macrocode} +% +% The next |\or| is only necessary because |\ns@@numstring| needs an +% |\or| as a delimiter of the number: +% +% \begin{macrocode} + \or% +% \end{macrocode} +% +% The last parameter to |\ns@@numstring| is \meta{macro}; we delimit +% it using |\@nil|: +% +% \begin{macrocode} + \@nil#2% +% \end{macrocode} +% +% Finally we end the |\ifcase| (note that this is \emph{after} the +% number has been formatted): +% +% \begin{macrocode} + \fi% +} +% \end{macrocode} +% +% \end{macro} +% +% +% \begin{macro}{\ns@@numstring} +% +% Expands to a number in words between |1| and |999,999,999|. +% +% Usage: |\ns@@numstring| \marg{9. digit} \marg{8. digit} \marg{7. +% digit} \marg{6. digit} \marg{5. digit} \marg{4. digit} \marg{3rd - +% 1st digit} \marg{(ignored)} \marg{macro}, where \meta{macro} is, as +% is the case with |\ns@numstring|, the macro to use for the numbers +% between |1| and |19|, as these require some special treatment. +% +% |\or| and the following |#8| (\meta{ignored}) gobble up whatever was +% left from the expansion of |\ifcase| in |\ns@numstring|. |\@nil| +% acts as a delimiter for the last parameter, \meta{macro}. +% +% \changes{1.1}{2004/08/08}{Formatting of millions added.} +% \changes{1.1}{2004/08/14}{Changed to match reeimplementation of +% ns@numstring.} +% +% \begin{macrocode} +\def\ns@@numstring#1#2#3#4#5#6#7\or#8\@nil#9{% + \ifnum#1#2#3>\z@ + \ns@million#1#2#3% +% \end{macrocode} +% +% We insert a space if a number follows: +% +% \begin{macrocode} + \ifnum#4#5#6>\z@\space\fi% + \fi% + \ifnum#4#5#6>\z@% + \ns@hundred#4#5#6{#1#2#3}{#4#5}\ns@neunzehn% +% \end{macrocode} +% +% If there has been a number larger than one before the `tausend', +% insert a discretionary hyphen before: +% +% \begin{macrocode} + \ifnum#4#5#6>\@ne\-\fi% + tau\-send% +% \end{macrocode} +% +% If there will be a number after the `tausend', insert a +% discretionary hyphen after: +% +% \begin{macrocode} + \ifnum#7>\z@\-\fi% + \fi% + \ns@hundred#7{#4#5#6}1#9% +} +% \end{macrocode} +% +% \end{macro} +% +% +% \begin{macro}{\ns@million} +% +% Expands to millions. +% +% Usage: |\ns@million| \marg{third digit} \marg{second digit} +% \marg{first digit}. +% +% \changes{1.1}{2004/08/08}{Macro added.} +% +% \begin{macrocode} +\def\ns@million#1#2#3{% + \ifnum#1#2#3=\@ne% + \ns@hundred#1#2#301\ns@neunzehne% + \space% + Mil\-lion% + \else% + \ns@hundred#1#2#301\ns@neunzehns% + \space% + Mil\-lio\-nen% + \fi% +} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\ns@hundred} +% +% Expands to a number in words between |1| and |100|. +% +% Usage: |\ns@hundred| \marg{third digit} \marg{second digit} +% \marg{first digit} \marg{shownumber} \marg{showone} +% \marg{macro}. +% +% \meta{shownumber} defines if the number before the |hundert| +% (`hundred') should be shown, i.e. |einhundert| (`onehundred') +% instead of |hundert|. |0| is |false|, everything else |true|. +% Can contain more than one digit. +% +% \meta{showone} defines if \meta{macro} should be called for the +% number |1|. |0| is |false|, everything else |true|. Can contain more +% than one digit. +% +% What does all this code do? First the third digit (`hundred'), +% contained in |#1|, is expanded -- if it is not zero. However, there +% is a catch: If the third digit is one, this digit is only included +% in the result of this macro if |#4| says so. The reason is that +% normally you would say |hunderteins| (`101') instead of +% |einhunderteins| -- but not if there is a fourth digit. Then the +% digit has to be included in the output of the macro, i.e. +% |tausendeinhunderteins| +% +% So we want to include the digit in the output of the macro, if |#3| +% is larger than one \emph{or} |#4| is larger than zero. We could use +% two |\ifnum|s to accomplish this, but it can be combined into a +% single |\ifnum|, saving tokens and time: +% +% We check if |#4#1| is larger than one. That means that if |#1|, the +% third digit, is larger than one, it is included in the output. But +% that also means that if |#4| is not zero, |#4#1| is always at least +% |10|, which is also larger than one and exactly what we want. +% +% After successfully processing the third digit, the remaining last +% two digits (|#2| and |#3|) are not really complicated anymore. We +% perform some special treatment of the numbers between |1| and |19| +% as these numbers are not constructed systematically. Here we have to +% perform a check similar to the one performed for the third digit: We +% have to check if we have to output the number if it is |1|, using +% the same trick for a logical |or| as before, only this time with +% |#5|, |#2| and |#3|. +% +% The macro to output |1| to |19| is parametrized as |#6| in order to +% be able to use different macros for normal numbers and ordinal +% numbers. +% +% If the last two digits are larger than |19|, we first output the +% third digit using |\ns@neunzehn|, followed by |und| (`and') and then +% the second digit. Here we don't have to use the parametrized macro +% as before, as the ordinal suffix is appended at the end of the +% number, not inbetween. +% +% But where to get the suffix from? We could pass it as a macro, but +% that would be tedious. So we simply define the macro to output the +% numbers |1| to |19| (|\ns@neunzehns| for normal numbers and +% |\ns@neunzehnord| for ordinal numbers) to output the suffix if +% called with |0| as its parameter. +% +% And we are done! +% +% \begin{macrocode} +\def\ns@hundred#1#2#3#4#5#6{% +% \end{macrocode} +% +% We expand the third digit: +% +% \begin{macrocode} + \ifnum#1>\z@% +% \end{macrocode} +% +% Logical |OR| hidden in |#4#1| (see above): +% +% \begin{macrocode} + \ifnum#4#1>\@ne\ns@neunzehn#1\-\fi% + hun\-dert% +% \end{macrocode} +% +% We insert a discretionary hyphen, if a number follows: +% +% \begin{macrocode} + \ifnum#2#3>\z@\-\fi% + \fi% +% \end{macrocode} +% +% We expand the first an second digit: +% +% \begin{macrocode} + \ifnum#2#3<20 % +% \end{macrocode} +% +% Again: Logical |OR| in |#5#2#3|: +% +% \begin{macrocode} + \ifnum#5#2#3>\@ne#6{#2#3}\fi% + \else% + \ifnum#3>\z@\ns@neunzehn#3\-und\-\fi% + \ns@neunzig#2% + #60% + \fi% +} +% \end{macrocode} +% +% \end{macro} +% +% +% \subsubsection{Macros for formatting `1' to `19'}\label{sec:LabFor} +% +% Very important: The position for |0| must expand to the suffix of +% the number (\emph{any number}), see the explanations for +% |\ns@hundred| above. If it expands to a text (as opposed to +% |\@empty|), this text must be prefixed by a discretionary hyphen! +% +% +% \begin{macro}{\ns@neunzehn} +% +% Expands to |ein| (`1') to |neunzehn| (`19'). +% +% \changes{1.1}{2004/08/08}{Hyphenation added.} +% +% \begin{macrocode} +\def\ns@neunzehn#1{% + \ifcase#1\@empty\or ein\or zwei\or drei\or vier\or f\"unf\or sechs\or% + sie\-ben\or acht\or neun\or zehn\or elf\or zw\"olf\or drei\-zehn\or% + vier\-zehn\or f\"unf\-zehn\or sech\-zehn\or sieb\-zehn\or% + acht\-zehn\or neun\-zehn\fi% +} +% \end{macrocode} +% +% \end{macro} +% +% +% \begin{macro}{\ns@neunzehns} +% +% Expands to |eins| (`1') to |neunzehn| (`19'). |0| expands to +% |\@empty|. +% +% Why |\@empty| instead of nothing? Because then \TeX\ would insert a +% |\relax| before the first |\or| in order to finish expansion of the +% number. This |\relax| would remain in the output and would stay +% there even when |\edef|ed, whereas |\@empty| expands to nothing. +% +% This is necessary for |\Numstring| and |\Ordstring|, as they convert +% the first token of the |\edef|ed result of |\numstring| and +% |\ordstring| to uppercase, and they need this token to be the first +% letter of the number, not |\relax|. +% +% \begin{macrocode} +\def\ns@neunzehns#1{% + \ifcase#1\@empty\or eins\else\ns@neunzehn{#1}\fi% +} +% \end{macrocode} +% +% \end{macro} +% +% +\def\ns@neunzehne#1{% + \ifcase#1\@empty\or ei\-ne\else\ns@neunzehn{#1}\fi% +} +% +% +% \begin{macro}{\ns@neunzehnord} +% +% Expands to |erste| (`1st') to |neunzehnte| (`19th'). |0| expands to +% |ste|. +% +% \changes{1.1}{2004/08/08}{Hyphenation added.} +% +% \begin{macrocode} +\def\ns@neunzehnord#1{% + \ifcase#1\-ste\or er\-ste\or zwei\-te\or drit\-te\or vier\-te\or% + f\"unf\-te\or sech\-ste\or sieb\-te\or ach\-te\or neun\-te\or% + zehn\-te\or elf\-te\or zw\"olf\-te\or drei\-zehn\-te\or% + vier\-zehn\-te\or f\"unf\-zehn\-te\or sech\-zehn\-te\or% + sieb\-zehn\-te\or acht\-zehn\-te\or neun\-zehn\-te\fi% +} +% \end{macrocode} +% +% \end{macro} +% +% +% \begin{macro}{\ns@neunzig} +% +% Expands to |zwanzig| (twenty) to |neunzig| (ninety) in steps of ten. +% +% \changes{1.1}{2004/08/08}{Hyphenation added.} +% +% \begin{macrocode} +\def\ns@neunzig#1{% + \ifcase#1\or\or zwan\-zig\or drei\ss ig\or vier\-zig\or% + f\"unf\-zig\or sech\-zig\or sieb\-zig\or acht\-zig\or% + neun\-zig\fi% +} +% \end{macrocode} +% +% \end{macro} +% +% \Finale +% \PrintChanges +% \PrintIndex +\endinput \ No newline at end of file diff --git a/macros/latex/contrib/sauerj/zahl2string.ins b/macros/latex/contrib/sauerj/zahl2string.ins new file mode 100644 index 0000000000..a03684bd8a --- /dev/null +++ b/macros/latex/contrib/sauerj/zahl2string.ins @@ -0,0 +1,19 @@ +\input docstrip +\keepsilent +\askforoverwritefalse + +\preamble +\endpreamble +\generate{% + \file{\jobname.sty}{\from{\jobname.dtx}{package}} +} + +\Msg{***************************************************************} +\Msg{*} +\Msg{* \space To finish the installation you have to copy the files} +\Msg{*} +\Msg{* \space *.sty into a directory searched by TeX} +\Msg{*} +\Msg{***************************************************************} + +\endbatchfile \ No newline at end of file diff --git a/macros/latex/contrib/sauerj/zahl2string.pdf b/macros/latex/contrib/sauerj/zahl2string.pdf new file mode 100644 index 0000000000..0b45d8cf1b Binary files /dev/null and b/macros/latex/contrib/sauerj/zahl2string.pdf differ -- cgit v1.2.3