From 1f54ab95d3bb8c747b233a9ab8872888ca651196 Mon Sep 17 00:00:00 2001
From: Karl Berry <karl@freefriends.org>
Date: Wed, 11 Jan 2006 23:52:18 +0000
Subject: trunk/Master/texmf-dist/source/latex/dialogl

git-svn-id: svn://tug.org/texlive/trunk@222 c570f23f-e606-0410-a88d-b1316a301751
---
 Master/texmf-dist/source/latex/dialogl/menus.dtx | 989 +++++++++++++++++++++++
 1 file changed, 989 insertions(+)
 create mode 100644 Master/texmf-dist/source/latex/dialogl/menus.dtx

(limited to 'Master/texmf-dist/source/latex/dialogl/menus.dtx')

diff --git a/Master/texmf-dist/source/latex/dialogl/menus.dtx b/Master/texmf-dist/source/latex/dialogl/menus.dtx
new file mode 100644
index 00000000000..b0f03f5f1ec
--- /dev/null
+++ b/Master/texmf-dist/source/latex/dialogl/menus.dtx
@@ -0,0 +1,989 @@
+%%% ====================================================================
+%%%  @LaTeX-style-file{
+%%%     filename        = "menus.sty",
+%%%     version         = "0.9x",
+%%%     date            = "1994/11/08",
+%%%     time            = "13:32:59 EST",
+%%%     checksum        = "38585 989 4295 33156",
+%%%     keywords        = "TeX, menus",
+%%%     author          = "Michael Downes",
+%%%     email           = "mjd@math.ams.org (Internet)",
+%%%     supported       = "yes",
+%%%     abstract        = "This file provides functions for writing
+%%%       messages and menus on screen, and reading user responses. It
+%%%       can be used with LaTeX as a documentstyle option, or in
+%%%       other forms of TeX by a standard \input statement.",
+%%%     docstring       = "The checksum field above contains a CRC-16
+%%%       checksum as the first value, followed by the equivalent of
+%%%       the standard UNIX wc (word count) utility output of lines,
+%%%       words, and characters.  This is produced by Robert Solovay's
+%%%       checksum utility.",
+%%%  }
+%%% ====================================================================
+%
+% \iffalse
+%<*driver>
+\input{dia-driv.tex}
+%</driver>
+% \fi
+%
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \section{Function descriptions}
+%
+%\begin{usage}
+%\fmenu\foobar{
+% <preliminary text>
+%}{
+% <menu lines>
+%}{
+% <following text>
+%}
+%\end{usage}
+%    Defines \cw{foobar} as a function that puts the preliminary text,
+%    the menu lines (list of choices), and the after text on screen.
+%    Normal usage:
+%
+%^^V \foobar           % print the menu on screen
+%^^V \readline{}\reply % read the answer
+%
+%    (See the description of \cw{readline} in \fn{dialog.doc}.) In the
+%    various text parts all special characters have category 12 except
+%    for braces, as with \cw{mesj}. Note the recommended placement of
+%    the braces: no closing brace falls at the end of a line, except
+%    the very last one. Because of the special catcodes in effect when
+%    reading the final three arguments, a \ctrl{M} or \qc{\%} between
+%    arguments would be read as an active character or category-12
+%    character respectively, instead of being ignored. But actually,
+%    after some rather difficult programming, I managed to make it
+%    possible to write just about anything (except brace characters)
+%    between the arguments and have it be ignored, so the recommended
+%    style is not mandatory. The first and last newline of each
+%    argument are stripped off anyway in order to produce consistent
+%    clean connections with \cw{menuprefix} etc.; see below.
+%
+%    Menu functions created by \cw{fmenu} are allowed optionally to
+%    have arguments, like functions created with \cw{fmesj} (from
+%    \fn{dialog.sty}), so that pieces of text can be inserted at the
+%    time of use. This makes it possible for several similar menus to
+%    share the same menu function if there are only minor variations
+%    between them.
+%
+%\begin{usage}
+%\menuprefix, \menusuffix
+%\inmenuA, \inmenuB
+%\end{usage}
+%    The text \cw{menuprefix} will be added at the beginning of each
+%    menu; \cw{menusuffix} will be added at the end. The text
+%    \cw{inmenuA} and \cw{inmenuB} will be added between the first and
+%    second, respectively second and third parts of the menu; their
+%    default values produce a blank line on screen. (But
+%    \cw{inmenuA} will be omitted if the first part is empty, and
+%    \cw{inmenuB} will be omitted if the last part is empty.) To change
+%    any of these texts, use \cw{storemesj} or \cw{storexmesj}. For
+%    example:
+%
+%^^V\storemesj\menuprefix{********* MENU **********}
+%
+%\begin{usage}
+%\menuprompt
+%\end{usage}
+%    Furthermore, the function \cw{menuprompt} is called at the very
+%    end of the menu, so that for example a standard prompt such as
+%    \verb'Enter a number:' could be applied at the end of all menus,
+%    if desired. To change \cw{menuprompt}, use \cw{fmesj} or
+%    \cw{fxmesj}.
+%
+%\begin{usage}
+%\menuline, \endmenuline
+%\menutopline, \menubotline
+%\end{usage}
+%    Each line in the middle argument of \cw{fmenu} (the list of
+%    choices) is embedded in a statement
+%    \cw{menuline}\verbdots\cw{endmenuline}. The default definition of
+%    \cw{menuline} is to add two spaces at the beginning and a newline
+%    at the end. Lines in the top or bottom part of the menu are
+%    embedded in \cw{menutopline}\verbdots\cw{endmenuline} or
+%    \cw{menubotline}\verbdots\cw{endmenuline} respectively. (Notice
+%    that all three share the same ending delimiter; if different
+%    actions are wanted at the end of a top or bottom line as opposed
+%    to a middle menu line, they must be obtained by defining
+%    \cw{menutopline} or \cw{menubotline} to read the entire line as
+%    an argument and perform the desired processing.)
+%
+%    An enclosing box for a menu can be obtained by
+%    defining \cw{menuline} and its relatives appropriately and using
+%    \cw{fxmenu} (see below).
+%
+%\begin{usage}
+%\fxmenu\foobar{
+% <preliminary text>
+%}{
+% <menu lines>
+%}{
+% <following text>
+%}
+%\end{usage}
+%    Similar to \cw{fmenu} but with full expansion in each part of the
+%    text, as with \cw{xmesj}.
+%
+%    To get an enclosing box for a menu, write \cs{\.} at the end of
+%    each menu line (to protect the preceding spaces from \tex/'s
+%    propensity to remove character 32 at the end of a line,
+%    regardless of its catcode), and then make sure that \cw{menuline}
+%    and \cw{endmenuline} put in the appropriate box-drawing
+%    characters on either side. I.e.:
+%
+%^^V \fxmenu\foobar{
+%^^V First line                                   \.
+%^^V Second line                                  \.
+%^^V }{
+%^^V Third line                                   \.
+%^^V ...
+%^^V }{
+%^^V Last line                                    \.
+%^^V }
+%
+%    With the \verb'/o' option of em\tex/, you can use the box-drawing
+%    characters in the standard PC DOS character set.
+%
+%\begin{usage}
+%\nmenu\Alph\foobar#1{
+% <preliminary text>
+%}{
+% <menu lines>
+%}{
+% <following text>
+%}
+%\end{usage}
+%    \cw{nmenu} and \cw{nxmenu} are like \cw{fmenu}, \cw{fxmenu}
+%    except that they automatically number each line of the middle
+%    part of the menu. (This allows menu choices to be added or deleted
+%    without tedious renumbering.) The first argument indicates the
+%    type of numbers to be used: \cw{alph}, \cw{Alph}, \cw{arabic},
+%    \cw{roman}, \cw{Roman} (following \latex/). {\em These are not yet
+%    implemented.}
+%^^A [15-May-1993,mjd]
+%
+%    The function \cw{menunumber} (taking one argument) is applied to
+%    each automatically generated number. The default value is to add
+%    brackets and a space after:
+%
+%^^V \def\menunumber#1{[#1] }
+%
+%    but by redefining \cw{menunumber} you can add parentheses or extra
+%    spaces or what have you around each number. Internally a line of
+%    an autonumbered menu is stored as
+%
+%^^V \menuline\menunumber{5}Text text ...\endmenuline
+%
+%\begin{usage}
+%\optionexec\answer
+%\end{usage}
+%    This is a companion function for \cw{readChar} and the menu
+%    functions: it checks to see if the answer is equal to any one of
+%    the characters \qc{\?} \qc{\Q} \qc{\q} \qc{\X} \qc{\x}, and if so
+%    executes \cw{moption?} or \cw{moptionQ} or \cw{moptionX}
+%    respectively, otherwise executes
+%
+%^^V \csname moption\curmenu C\endcsname
+%
+%    where \qc{\C} means the character that was read and \cw{curmenu} is
+%    a string identifying the current location in the menu system.
+%    (\cw{optionexec} pushes and pops \cw{curmenu} when going between
+%    menus, to keep it up to date.) If this control sequence is
+%    undefined, \cw{optionexec} gives a generic ``Sorry, I don't
+%    understand'' message and repeats the current menu.
+%
+%    Thus the major work involved in making a menu system is to define
+%    the menu screens using \cw{fmenu}, \cw{fxmenu}, and then define
+%    corresponding functions \cw{moptionXXX} that display one of the
+%    menu screens, read a menu choice, and call \cw{optionexec} to
+%    branch to the next action.
+%
+%\begin{usage}
+%\specialhelp\answer{Substitute message}
+%\end{usage}
+%    As it turns out, it is sometimes desirable to substitute some
+%    other message in place of the generic ``Sorry, I don't
+%    understand'' message given by \cw{optionexec}. For instance,
+%    suppose a given menu choice leads to a secondary prompt where you
+%    ask the user to enter a number of columns for printing some data.
+%    If the user accidentally mistypes \verb'0', it would be better to
+%    respond with something like
+%
+%^^V Number of columns must be greater than 0.
+%
+%    than with the generic message. The function \cw{specialhelp}
+%    allows you to do this. The first argument is the name of the
+%    macro that will be passed to \cw{optionexec}. \cw{specialhelp}
+%    modifies that macro to a flag value that will trigger the
+%    substitute message. (But does it carefully, so that you can still
+%    use the macro naturally in the substitute message text.)
+%
+%\begin{usage}
+%\optionfileexec\answer
+%\end{usage}
+%    Like \cw{optionexec}, but gets the next menu from a file instead
+%    of from main memory, if applicable. This is not yet
+%    implemented.
+%^^A [mjd,24-May-1993]
+%    The technical complications involved in managing the menu files
+%    are many\Dash for example: How do you prevent the usual file name
+%    message of \tex/ from intruding on your carefully designed menu
+%    screens, if \cw{input} is used to read the next menu file?
+%    Alternatively if you try to use \cw{read} to read the next menu
+%    file, how do you deal with catcode changes?
+%
+%\begin{usage}
+%\lettermenu{MN}
+%\end{usage}
+%    This is an abbreviation for
+%
+%^^V \menuMN \readChar{Q}\reply \optionexec\reply
+%
+%    It calls the menu function associated with the menu name \verb"MN",
+%    reads a single uppercase letter into \cw{reply}, and then calls
+%    \cw{optionexec} to branch to the case selected by the reply.
+%
+%\begin{usage}
+%\if\xoptiontest\answer ... \else ... \fi
+%\end{usage}
+%    The function \cw{xoptiontest} is for use with \cw{readline} or
+%    \cw{xreadline}, to trap the special responses \verb'? Q q X x'
+%    before executing some conditional code. It returns a `true' value
+%    suitable for \cw{if} testing, if and only if the replacement text
+%    of \cw{answer} is a single character matching one of those
+%    listed.  This is used when you are prompting for a response that
+%    can be an arbitrary string of characters, but you want to allow
+%    the user still to get help or quit with the same one-character
+%    responses that are recognized in other situations.
+%
+% \StopEventually{}
+%
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% \section{Implementation}
+%    Standard package identification:
+%    \begin{macrocode}
+%<*2e>
+\NeedsTeXFormat{LaTeX2e}
+\ProvidesPackage{menus}[1994/11/08 v0.9x]
+%    \end{macrocode}
+%    Load the dialog package if necessary.
+%    \begin{macrocode}
+\RequirePackage{dialog}
+%</2e>
+%    \end{macrocode}
+%
+%    This file requires \fn{grabhedr.sty} and \fn{dialog.sty}. If
+%    \fn{grabhedr.sty} is not already loaded, load it now and call
+%    \cw{fileversiondate}, since it's too late to apply \cw{inputfwh}
+%    to {\em this\/} file. See the documentation of \cw{trap.input} in
+%    \fn{grabhedr.doc}.
+%    \begin{macrocode}
+%<*209>
+\csname trap.input\endcsname
+\input grabhedr.sty \relax
+\fileversiondate{menus.sty}{0.9x}{1994/11/08}
+%    \end{macrocode}
+%
+%    \begin{macrocode}
+\inputfwh{dialog.sty}
+%</209>
+%    \end{macrocode}
+%
+%\section{Definitions}
+%
+%    We start by using the \cw{localcatcodes} function from
+%    \fn{grabhedr.sty} to save current catcodes and set new catcodes
+%    for certain significant characters, as explained at more length
+%    in \fn{dialog.doc}.
+%
+%    \begin{macrocode}
+\localcatcodes{\@{11}%
+  \~{13}\"{12}\#{6}\^{7}\`{12}\${3}\:{12}}
+%    \end{macrocode}
+%
+%\begin{macro}{\menuprefix}
+%    \cw{menuprefix} is a string added at the beginning of each menu to
+%    pretty it up a little (or uglify it a little, depending on your
+%    taste). The length of the default string is 70 characters, not
+%    counting the two newline characters. By using \cw{storexmesj} we
+%    get embedded newlines corresponding to the ones seen here. [That
+%    is, except for the extra line break (where the newline character is
+%    commented out), needed to make this fit in the current column
+%    width.]
+%
+%\iftrue
+%^^V \storexmesj\menuprefix{
+%^^V ===================================%
+%^^V ===================================
+%^^V }
+%
+%\else
+%    \begin{macrocode}
+\storexmesj\menuprefix{
+======================================================================
+}
+%    \end{macrocode}
+%\fi
+% \end{macro}
+%
+% \begin{macro}{\menusuffix}
+%    The default value for \cw{menusuffix} is the same as for
+%    \cw{menuprefix}.
+%    \begin{macrocode}
+\let\menusuffix=\menuprefix
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\inmenuA}
+% \begin{macro}{\inmenuB}
+%    The default for \cw{inmenuA} and \cw{inmenuB} is a single
+%    newline, which will produce a blank line on screen because they
+%    will occur after an \cw{endmenuline}, which also
+%    contains a newline.
+%    \begin{macrocode}
+\storemesj\inmenuA{
+}
+\storemesj\inmenuB{
+}
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+%\begin{macro}{\menuline}
+%    The default value for \cw{menuline} is two spaces. This means
+%    that each line in the middle section of a menu defined by
+%    \cw{fmenu} or \cw{fxmenu} will be indented two spaces.
+%    \begin{macrocode}
+\storemesj\menuline{  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\menutopline}
+% \begin{macro}{\menubotline}
+%    By default, no spaces are added at the beginning of a line in the
+%    top or bottom section of a menu:
+%    \begin{macrocode}
+\def\menutopline{}
+\def\menubotline{}
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\endmenuline}
+%    \cw{endmenuline} is just a newline.
+%    \begin{macrocode}
+\storemesj\endmenuline{
+}%
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\menunumber}
+%    This definition of \cw{menunumber} adds square brackets and a
+%    following space around each item number.
+%    \begin{macrocode}
+\def\menunumber#1{[#1] }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\menuprompt}
+%    This definition of \cw{menuprompt} is suitable for the purposes
+%    of \fn{listout.tex} but will probably need to be no-op'd or
+%    changed for other applications.
+%    \begin{macrocode}
+\def\menuprompt{\promptmesj{Your choice? }}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\menufirstpart}
+% \begin{macro}{\menuchoices}
+% \begin{macro}{\menulastpart}
+%    Each of the three pieces of a menu gets its own token register.
+%    \begin{macrocode}
+\newtoks\menufirstpart
+\newtoks\menuchoices
+\newtoks\menulastpart
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\fmenu}
+%
+%    The `arguments' of \cw{fmenu} are \arg{1} menu name, \arg{2}
+%    optional argument specifiers, \arg{3} preliminary text, \arg{4}
+%    list of menu choices, \arg{5} following text. But at first we read
+%    only the first two because we want to change some catcodes before
+%    reading the others. The auxiliary function \cw{fxmenub} is shared
+%    with \cw{fxmenu}.
+%
+%    Because of the catcode changes done by \cw{mesjsetup}, newlines,
+%    spaces, or percent signs between the three final arguments will
+%    not be ignored. To get around this, we use the peculiar
+%    \verb'#{' feature of \tex/, in intermediate scratch functions
+%    called \cw{@tempa}, to read and discard anything that may occur
+%    between one closing brace and the next opening brace. Token
+%    register assignments are used to read the arguments proper.
+%
+%    \begin{macrocode}
+\def\fmenu#1#2#{\mesjsetup
+  \catcode`\#=6 % for parameters
+  \toks@{\fxmenub{\gdef}{\begingroup}{}#1{#2}}%
+  \def\@tempa##1##{%
+    \def\@tempa####1####{%
+      \def\@tempa{\the\toks@}%
+      \afterassignment\@tempa \menulastpart}%
+    \afterassignment\@tempa \menuchoices}%
+  \afterassignment\@tempa \menufirstpart
+}
+%    \end{macrocode}
+% \end{macro}
+%
+%    Before proceeding to define \cw{fxmenub}, we must deal with a
+%    subproblem. What we will have to work with is three pieces of text
+%    in the token registers \cw{menufirstpart}, \cw{menuchoices}, and
+%    \cw{menulastpart}, containing active \ctrl{M} characters to mark
+%    line breaks, including possibly but not necessarily \ctrl{M} at the
+%    beginning and at the end of each piece. What we would like to do,
+%    for each piece, is to remove the first \ctrl{M}, if there is one,
+%    and the last one, if there is one. The function \cw{stripcontrolMs}
+%    does this.
+%
+%    If you are one of those rare \tex/ hackers who might actually
+%    want to understand the workings of \cw{stripcontrolMs}, the best
+%    way is probably to watch it in action with \cw{tracingmacros} =
+%    \cw{tracingcommands} = 2, rather than attempt to follow my labored
+%    commentary below.
+%    \begin{macrocode}
+\begingroup % localize \lccode change
+\lccode`\~=`\^^M
+%    \end{macrocode}
+%    The functions \cw{stripM}, \cw{stripMa}, \cw{stripMb}, \ldots\ are
+%    auxiliary functions for \cw{stripcontrolMs}. They all carry along
+%    an extra last argument, the name of the token register originally
+%    given to \cw{stripcontrolMs}, so that when we finally reach
+%    \cw{stripMd} we can carry out the assignment of the token
+%    register.
+%
+%    When \cw{stripM} is called, it should be called like this:
+%\begin{verbatim}
+% \expandafter\stripM\expandafter$\the\sometoks
+% $^^M$$\stripM\sometoks
+%\end{verbatim}
+%    That is, \qc{\$} should be added at the beginning and \verb'$^^M$$'
+%    at the end of the text to be processed. And \cw{expandafter}'s
+%    should be added to pre-expand the token register.
+%
+%    These examples illustrate the possible contents of (e.g.\@)
+%    \cw{menufirstpart}, before processing
+%\begin{enumerate}\renewcommand{\theenumi}{\alph{enumi}}
+%\renewcommand{\labelenumi}{(\theenumi)}
+%    \item \label{mmm}
+%      \verb'^^Maaa^^Mbbb^^M'
+%    \item \verb'aaa^^Mbbb'
+%    \item \verb'^^Maaa^^Mbbb'
+%    \item \verb'aaa^^Mbbb^^M'
+%\end{enumerate}
+%    The processing of example (\ref{mmm}) would proceed as follows.
+%    Call \cw{stripM}, adding \qc{\$} at the beginning and \verb'$^^M$$'
+%    at the end.
+%\begin{verbatim}
+% \stripM $^^Maaa^^Mbbb^^M$^^M$$\stripM
+%\end{verbatim}
+%    This finds a match with the \verb'$^^M' at the beginning. The
+%    remaining text is passed on to \cw{stripMb}. We know that there is
+%    now an extra \verb'$^^M$$' at the end, but we don't know if the
+%    first \qc{\$} is preceded by \ctrl{M}.
+%\begin{verbatim}
+% \stripMb aaa^^Mbbb^^M$^^M$$\stripMb
+%\end{verbatim}
+%    If it turns out that \arg{2} = \qc{\$}, then there was {\em not\/}
+%    a \ctrl{M} at the end of the original text, and we need to strip
+%    off a last remaining \qc{\$} sign. Otherwise we are finished if we
+%    just discard \arg{2} and \arg{3} (the remaining \ctrl{M} and
+%    \qc{\$} characters of the ones that we added).
+%
+%    We use \qc{\$} as a marker since any \qc{\$} characters that
+%    happen to occur in the menu text will have category 12 and thus
+%    not match the category-3 \qc{\$} used in the definition of
+%    \cw{stripMa} etc. A control sequence could also be used as a
+%    marker if we took care to give it a bizarre name that would never
+%    arise in the menu text (\cw{fxmenub} is used not just by
+%    \cw{fmenu} but also by \cw{fxmenu}, which might have arbitrary
+%    control sequences in its arguments); but that means using up one
+%    more hash table entry and additional string pool.
+%
+% \begin{macro}{\stripM}
+%    \begin{macrocode}
+\lowercase{%
+\long\gdef\stripM#1$~#2#3\stripM#4{%
+  \ifx$#2%
+    \stripMa#1\stripMa#4%
+  \else
+    \stripMb#2#3\stripMb#4%
+  \fi
+}
+}% end lowercase
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\stripMa}
+%    \begin{macrocode}
+\lowercase{%
+\long\gdef\stripMa $#1\stripMa#2{%
+  \stripMb#1$~$$\stripMb#2}
+}% end lowercase
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\stripMb}
+%    \begin{macrocode}
+\lowercase{%
+\long\gdef\stripMb#1~$#2#3\stripMb#4{%
+  \ifx$#2%
+    \stripMc#1\stripMc#4%
+  \else
+    \stripMd#1\stripMd#4%
+  \fi
+}
+}% end lowercase
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\stripMc}
+%    \begin{macrocode}
+\long\gdef\stripMc#1$#2\stripMc#3{%
+  \stripMd#1\stripMd#3}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\stripMd}
+%    \begin{macrocode}
+\long\gdef\stripMd#1\stripMd#2{#2{#1}}
+\endgroup
+%    \end{macrocode}
+% \end{macro}
+%
+%    Some tests.
+%\begin{verbatim}
+% %\lowercase{\def\test#1{\stripM $#1$~$$\stripM}
+% %\tracingmacros=2 \tracingcommands=2 \tracingonline=1
+% %\test{~aaa~bbb~}
+% %\test{aaa~bbb}
+% %\test{~aaa~bbb}
+% %\test{aaa~bbb~}
+% %\tracingmacros=0 \tracingcommands=0 \tracingonline=0
+% %}% end lowercase
+%\end{verbatim}
+%
+% \begin{macro}{\stripcontrolMs}
+%    The argument of \cw{stripcontrolMs} is a token register. The text
+%    of the token register will be stripped of a leading and trailing
+%    \ctrl{M} if either or both are present, and the remainder text will
+%    be left in the token register.
+%
+%    \begin{macrocode}
+\begingroup \lccode`\~=`\^^M
+\lowercase{%
+\gdef\stripcontrolMs#1{\xp@\stripM
+  \xp@$\the#1$~$$\stripM#1}
+}% end lowercase
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\addmenulines}
+%    \begin{macrocode}
+\lowercase{%
+\gdef\addmenulines#1#2#3{%
+%    \end{macrocode}
+%    Add \arg{2} at the beginning and \arg{3} at the end of every line
+%    of token register \arg{1}.
+%    \begin{macrocode}
+  \def ~##1~##2{%
+    #1\xp@{\the#1#2##1#3}%
+    \ifx\end##2\xp@\@gobbletwo\fi~##2}%
+  \edef\@tempa{\nx@~\the#1\nx@~}#1{}%
+  \@tempa\end}
+}% end lowercase
+\endgroup % restore lccode of ~
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\fxmenub}
+%
+%    The function \cw{fxmenub} is the one that does most of the hard
+%    work for \cw{fmenu} and \cw{fxmenu}. Argument \arg{4} is the name
+%    of the menu, \arg{5} is the argument specifiers (maybe empty).
+%    Arguments \arg{1}\arg{2}\arg{3} are assignment type, extra setup,
+%    and expansion control; specifically, these arguments are
+%    \cw{gdef} \cw{begingroup} \cw{empty} for \cw{fmenu} or \cw{xdef}
+%    \cw{xmesjsetup} and an extra \cw{noexpand} for \cw{fxmenu}.
+%
+%    That this function actually works should probably be regarded as
+%    a miracle rather than a result of my programming efforts.^^A
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \footnote{Let's see, three miracles is a prerequisite for sainthood
+% in the Catholic church\Dash only two more needed for Don
+% Knuth to be a candidate \dots}
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%    \begin{macrocode}
+\def\fxmenub#1#2#3#4#5{%
+  \stripcontrolMs\menufirstpart
+  \stripcontrolMs\menulastpart
+  \stripcontrolMs\menuchoices
+  \addmenulines\menuchoices\menuline\endmenuline
+  \actively\let\^^M\relax % needed for \xdef
+%    \end{macrocode}
+%    Define \arg{4}. Expansion control is rather tricky because of the
+%    possibility of parameter markers inside \cw{menufirstpart},
+%    \cw{menuchoices} or \cw{menulastpart}.
+%    \begin{macrocode}
+  \toks@{\long#1#4#5}% e.g. \xdef\foo##1##2
+%    \end{macrocode}
+%    If \cw{menufirstpart} is empty, we don't add the separator
+%    material \cw{inmenuA}.
+%    \begin{macrocode}
+  \edef\@tempa{\the\menufirstpart}%
+  \ifx\@tempa\@empty
+    \let\nxa@\@gobble
+  \else
+    \addmenulines\menufirstpart
+      \menutopline\endmenuline
+    \let\nxa@\nx@
+  \fi
+%    \end{macrocode}
+%    If \cw{menulastpart} is empty, we don't add the separator
+%    material \cw{inmenuB}.
+%    \begin{macrocode}
+ \edef\@tempa{\the\menulastpart}%
+  \ifx\@tempa\@empty
+    \let\nxb@\@gobble
+  \else
+    \addmenulines\menulastpart
+      \menubotline\endmenuline
+    \let\nxb@\nx@
+  \fi
+%    \end{macrocode}
+%    Set up the definition statement that will create the new menu.
+%    \arg{2} = \cw{begingroup} or \cw{xmesjsetup}.
+%    \begin{macrocode}
+\edef\@tempa{{#3\nx@#3#2%
+    \def#3\nx@#3\mesjtext{%
+      #3\nx@#3\menuprefix
+      \the\menufirstpart #3\nxa@#3\inmenuA
+      \the\menuchoices #3\nxb@#3\inmenuB
+      \the\menulastpart #3\nx@#3\menusuffix}%
+    #3\nx@#3\sendmesj
+    #3\nx@#3\menuprompt}}%
+  \toks2 \xp@{\@tempa}%
+  \edef\@tempa{\the\toks@\the\toks2 }%
+%    \end{macrocode}
+%    Temporarily \cw{relax}ify \cw{menuline} etc. in order to prevent
+%    their premature expansion if \cw{xdef} is applied.
+%    \begin{macrocode}
+  \let\menutopline\relax \let\menuline\relax
+  \let\menubotline\relax \let\endmenuline\relax
+  \let\menunumber\relax
+  \@tempa % finally, execute the \gdef or \xdef
+  \endgroup % matches \mesjsetup done by \fxmenu
+}% end \fxmenub
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\fxmenu}
+%
+%    Expanding analog of \cw{fmenu}.
+%    \begin{macrocode}
+\def\fxmenu#1#2#{\xmesjsetup
+  \toks@{\fxmenub{\xdef}{\xmesjsetup}\nx@#1{#2}}%
+  \def\@tempa##1##{%
+    \def\@tempa####1####{%
+      \def\@tempa{\the\toks@}%
+      \afterassignment\@tempa \menulastpart}%
+    \afterassignment\@tempa \menuchoices}%
+  \afterassignment\@tempa \menufirstpart
+}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\notyet}
+%
+%    \begin{macrocode}
+\def\notyet#1{%
+  \errmessage{Not yet implemented:  \string#1}}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\nmenu}
+% \begin{macro}{\nxmenu}
+%    These two functions aren't implemented yet.
+%^^A [mjd,24-May-1993]
+%    \begin{macrocode}
+\long\def\nmenu#1#2#3#4#5{\notyet\nmenu}
+\long\def\nxmenu#1#2#3#4#5{\notyet\nxmenu}
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \section{Menu traversal functions}
+%
+%    For reliable travel up and down the menu tree, we need to push
+%    and pop the value of \cw{curmenu} as we go along. Among other
+%    things, \cw{curmenu} is used to repeat the current menu after a
+%    help message.
+%
+% \begin{macro}{\optionstack}
+%    \begin{macrocode}
+\newtoks\optionstack
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\curmenu}
+%    \begin{macrocode}
+\let\curmenu\@empty
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\estart}
+%    Start of a stack element.
+%    \begin{macrocode}
+\let\estart\relax
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\eend}
+%    End of a stack element.
+%    \begin{macrocode}
+\let\eend\relax
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\pushoptions}
+%    \begin{macrocode}
+\def\pushoptions#1{%
+  \edef\pushtemp{\estart
+    \def\nx@\curmenu{\curmenu}%
+    \eend
+    \the\optionstack}%
+  \global\optionstack\xp@{\pushtemp}%
+  \edef\curmenu{\curmenu#1}%
+}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\popoptions}
+%    \begin{macrocode}
+\def\popoptions{%
+  \edef\@tempa{\the\optionstack}%
+  \ifx\@empty\@tempa
+    \errmessage{Can't pop empty stack
+      (\string\optionstack)}%
+  \else
+    \def\estart##1\eend##2\@nil{%
+      \global\optionstack{##2}%
+      \let\estart\relax##1}%
+    \the\optionstack\@nil
+  \fi
+}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\moptionX}
+%
+%    The \qc{\X} option is a total exit from the menu maze, as
+%    compared to \cw{moptionQ}, which returns you to the previous menu
+%    level.
+%
+%    \begin{macrocode}
+\fmesj\moptionX{Exiting . . .}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\repeatoption}
+%    \begin{macrocode}
+\def\repeatoption{%
+  \csname moption\curmenu\endcsname}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\moptionQ}
+%    \begin{macrocode}
+\def\moptionQ{\popoptions \repeatoption}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\badoptionmesj}
+%    The sole reason for using \cw{fxmesj} rather than \cw{fmesj} here
+%    is to use \qc{\%} to comment out the initial newline, as the line
+%    break was needed only for convenient printing of this
+%    documentation within a narrow column width.
+%    \begin{macrocode}
+\fxmesj\badoptionmesj#1{%
+?---I don't understand "#1".}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\optionexec}
+%
+%    The function \cw{optionexec} takes one argument, which it uses
+%    together with \cw{curmenu} to determine the next action. The
+%    argument is expected to be a macro containing a single letter,
+%    the most recent menu choice received from the user.
+%
+%    Common options such as \qc{\?}, \qc{\Q}, or \qc{\X} that may
+%    occur at any level of the menu system are handled specially, to
+%    cut down on the number of control sequence names needed for a
+%    csname implementation of the menus.
+%    \begin{macrocode}
+\def\optionexec#1{%
+  \if ?#1\relax \let\@tempa\moptionhelp
+  \else \if Q#1\relax
+    \ifx\curmenu\@empty \let\@tempa\moptionX
+    \else \let\@tempa\moptionQ \fi
+  \else \if X#1\relax \let\@tempa\moptionX
+  \else
+%    \end{macrocode}
+%    Because special characters, including backslash, are deactivated
+%    by \cw{readChar}, we can apply \cw{csname} without fearing problems
+%    from responses such as \cw{relax}.
+%    \begin{macrocode}
+    \xp@\let\xp@\@tempa
+      \csname moption\curmenu#1\endcsname
+    \ifx\@tempa\relax
+      \badoptionmesj{#1}\let\@tempa\repeatoption
+    \else
+      \pushoptions{#1}%
+    \fi
+  \fi\fi\fi
+%    \end{macrocode}
+%    We save up the next action in \cw{@tempa} and execute it last, to
+%    get tail recursion.
+%    \begin{macrocode}
+  \@tempa
+}
+%    \end{macrocode}
+% \end{macro}
+%
+%    Really big menu systems could get around \tex/ memory limits by
+%    storing individual menus or groups of menus in separate files and
+%    using \cw{optionfileexec} in place of \cw{optionexec} to
+%    retrieve the menu text from disk storage instead of from main
+%    memory. However there are a number of technical complications and
+%    I probably won't get around to working on them in the near future.
+%^^A [mjd,24-May-1993]
+%
+% \begin{macro}{\optionfileexec}
+%    \begin{macrocode}
+\def\optionfileexec#1{\notyet\optionfileexec}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\xoptiontest}
+%    The function \cw{xoptiontest} must return true if and only if the
+%    macro \arg{1} consists entirely of one of the one-letter
+%    responses \verb"? Q q X x" that correspond to special menu
+%    actions. The rather cautious implementation with \cw{aftergroup}
+%    avoids rescanning the contents of \verb"#1", just in case it
+%    contains anything that's \cw{outer}.
+%    \begin{macrocode}
+\def\xoptiontest#1{TT\fi
+  \begingroup \def\0{?}\def\1{Q}%
+  \def\2{q}\def\3{x}\def\4{X}%
+    \aftergroup\if\aftergroup T%
+    \ifx\0#1\aftergroup T%
+    \else\ifx\1#1\aftergroup T%
+    \else\ifx\2#1\aftergroup T%
+    \else\ifx\3#1\aftergroup T%
+    \else\ifx\4#1\aftergroup T%
+    \else \aftergroup F%
+    \fi\fi\fi\fi\fi
+  \endgroup
+}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\menuhelpmesj}
+%
+%    Default help message, can be redefined if necessary. The extra
+%    newlines commented out with \qc{\%} are here only for convenient
+%    printing within a narrow column width.
+%
+%    \begin{macrocode}
+\fxmesj\menuhelpmesj{&\menuprefix%
+A response of Q will usually send you back to %
+the previous menu.
+A response of X will get you entirely out of %
+the menu system.
+&\menusuffix%
+Press the <Return> key ( Enter ) to continue:
+}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\moptionhelp}
+%    \begin{macrocode}
+\def\moptionhelp{%
+  \menuhelpmesj \readline{}\reply \repeatoption}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\moptionhelp}
+%    \cw{moptionhelp} is the branch that will be taken if the user
+%    enters a question mark in response to a menu.
+%    \begin{macrocode}
+\def\moptionhelp{%
+  \menuhelpmesj \readline{}\reply \repeatoption}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\moption?}
+%    \begin{macrocode}
+\xp@\def\csname moption?\endcsname{%
+  \moptionhelp}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\specialhelp}
+%    The function \cw{specialhelp} can be used to provide a one-time
+%    alternate help message tailored to a specifc response given by
+%    the user. It defines the first argument (the macro containing the
+%    response) to contain \qc{\?}, then redefines \cw{menuhelpmesj} to
+%    use the message text given in arg \arg{2}.
+%    \begin{macrocode}
+\def\specialhelp#1#2{%
+  \let\specialhelpreply=#1\def#1{?}\begingroup
+  \def\menuhelpmesj{\let#1\specialhelpreply
+    \promptxmesj{#2\
+Press <return> to continue:}\endgroup}%
+}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\specialhelpreply}
+%    Init.
+%    \begin{macrocode}
+\def\specialhelpreply{}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\lettermenu}
+%    This is a convenient abbreviation for an often-used combination.
+%    \begin{macrocode}
+\def\lettermenu#1{%
+  \csname menu#1\endcsname
+  \readChar{Q}\reply \optionexec\reply
+}
+%    \end{macrocode}
+% \end{macro}
+%
+%    Restore any catcodes changed locally, and depart.
+%    \begin{macrocode}
+\restorecatcodes
+\endinput
+%    \end{macrocode}
+%
+% \CheckSum{513}
+% \Finale
-- 
cgit v1.2.3

