%%% ====================================================================
%%%  @LaTeX-style-file{
%%%     filename        = "menus.dtx",
%%%     version         = "1.99a",
%%%     date            = "2013/01/24",
%%%     author          = "Michael Downes",
%%%     copyright       = "This file is part of the dialogl package, released
%%%                        under the LPPL; see dialogl.ins for details."
%%%     keywords        = "TeX, menus",
%%%     supported       = "no",
%%%     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.",
%%%  }
%%% ====================================================================
%
% \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
