%%% ==================================================================== %%% @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} % % \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