From 1f54ab95d3bb8c747b233a9ab8872888ca651196 Mon Sep 17 00:00:00 2001 From: Karl Berry 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} +% +% \fi +% +% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% \section{Function descriptions} +% +%\begin{usage} +%\fmenu\foobar{ +% +%}{ +% +%}{ +% +%} +%\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{ +% +%}{ +% +%}{ +% +%} +%\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{ +% +%}{ +% +%}{ +% +%} +%\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} +% +% \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} +% +% \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 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 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