1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
|
%\iffalse meta-comment
%<*internal>
\def\nameofplainTeX{plain}
\ifx\fmtname\nameofplainTeX\else
\expandafter\begingroup
\fi
%</internal>
%<*install>
\input docstrip.tex
\keepsilent
\askforoverwritefalse
\preamble
\endpreamble
\ifx\fmtname\nameofplainTeX
\generate{\file{\jobname.def}{\from{\jobname.dtx}{package}}}
\fi
%</install>
%<install>\endbatchfile
%<*internal>
\ifx\fmtname\nameofplainTeX
\expandafter\endbatchfile\else
\expandafter\endgroup\fi
%</internal>
%<*driver>
\documentclass{ltxdoc}
%\usepackage[numbered]{hypdoc}
\begin{document}
\DocInput{\jobname.dtx}
\end{document}
%</driver>
% \fi
%
%\title{\textsf{contsolns}}
%\author{D. P. Story}
%
%\maketitle
%
% \paragraph{Installation.} Open the file \texttt{\jobname.dtx} in
% your favorite tex editor (\textsf{WinEdt}) and compile using the
% \emph{\textbf{tex} compiler}, not the \textbf{latex} compiler. Doing so,
% generates the file \texttt{\jobname.def}. The files \texttt{\jobname.dtx}
% and \texttt{\jobname.def} are distributed with AeB. The \textsf{exerquiz}
% package has the \texttt{contsolns} option to use the code in this file.
%
% \subparagraph{Demo file.} The demo file for this feature of \textsf{exerquiz}
% is \texttt{contsolns\_ex.tex}. This feature is available to users of any
% supported driver.
% \begin{macrocode}
%<*package>
% \end{macrocode}
%
% \section{Introduction}
%
% This collection of definitions is designed for use with \textbf{AeB}
% (more specifically, the \textsf{web} and \textsf{exerquiz} package).
% My occasional friend J\"{u}rgen wanted to have a ``continued on next page'' string to
% appear at the bottom of a solution (when it appears at the end of the
% file) to indicate the solution to this current problem continues onto the
% next page. Originally, this was done for the \texttt{shortquiz}
% environment, and later extended to the \texttt{quiz} and \texttt{exercise}
% environments.
%
% \paragraph{Assumptions.} The code assumes the \textsf{web} package page style,
% \texttt{webheadings}, is in effect; otherwise, this code fails.
%
%\section{Documentation}
%
% The use of the \texttt{contsolns} option should be pretty
% seamless. The message that appears in the right footer is \DescribeMacro{\rfootContStr}
% \cmd{\rfootContStr}; the command takes two argument, the second of which is a short
% string that identifies the question. It can be redefined. The labels \DescribeMacro{\Qlabel}\cmd{\Qlabel}
% and \DescribeMacro{\Elabel}\cmd{\Elabel} may also be redefined. When compiled
% for paper (\texttt{forpaper} option), we emit the \textsf{exerquiz} command
% \cmd{\promoteNewPageHere} with an argument of \DescribeMacro{\promoteNPHskip}\cmd{\promoteNPHskip}
% in a vain attempt to get the numbers right. \cmd{\promoteNPHskip} is set to
% \texttt{.1\cs{textheight}} and may be redefined if this value is not working as it should.
%
% This code file uses the running headers, left and right. If you want to use these
% footers and this feature, you need to preserve the code. This is what I do in this
% code file:
%\begin{verbatim}
%\expandafter\lfooter\expandafter{\expandafter\newLFooterCmd\web@lfoot}
%\expandafter\rfooter\expandafter{\web@rfoot\newRFooterCmd}
%\end{verbatim}
%This demonstrates how to put the new code on the left of the old, or on the right.
%
% \subparagraph{Problems.} Problems arise if the numbers in the footer do not match
% the exercise or quiz numbers, this may occur when using the \texttt{forpaper} option,
% the workaround is to adjust \cmd{\promoteNPHskip} to a larger value.
%
% When using the \texttt{navibar} option of \textsf{web}, there may be insufficient
% room to the right of the navigation bar; in this case, shorten the text created by
% \cmd{\rfootContStr}, or reduce the number of navigation buttons on the solution pages.
%
% \section{The Code}
% First, we determine if \textsf{web} is loaded.
% \begin{macrocode}
\@ifpackageloaded{web}{}{\PackageError{exerquiz}
{The consolns option of exerquiz requires\MessageBreak
the web package}{Use the web package.}}
% \end{macrocode}
% \DescribeMacro{\setQNum}\cmd{\setQNum} sets the question number in to the solutions at
% end of the file. While \DescribeMacro{\setENum}\cs{setENum} does the same thing
% for exercises. \DescribeMacro{\Qlabel}\cmd{\Qlabel} provides a label for the
% quiz question as a result, \cs{setQNum} expands to strings like `Q1', `Q1(a)',
% or `Q1(a)(i)'. \DescribeMacro{\Elabel}\cmd{\Elabel} does the same for exercises.
% \cs{setEnum} expands to `E1' and `E1(a)', for example.
% Both \cs{Qlabel} and \cs{Elabel} are fragile. All four of these commands may be redefined.
% \begin{macrocode}
\def\setQNum{\Qlabel\ifcase\@eqquestiondepth\or\arabic{eqquestionnoi}%
\or\arabic{eqquestionnoi}(\alph{eqquestionnoii})%
\or\arabic{eqquestionnoi}(\alph{eqquestionnoii})%
(\roman{eqquestionnoiii})\fi}
\def\setENum{\Elabel\if\exerstar*\theeqexno(\alph{partno})\else
\theeqexno\fi}
% \end{macrocode}
% The default definitions of \cs{Qlabel} and \cs{Elabel} are next.
% \begin{macrocode}
\def\Qlabel{Q}\def\Elabel{E}
% \end{macrocode}
% \DescribeMacro{\solContMarks}\cmd{\solContMarks} really does nothing other than expand
% to arguments enclosed in braces. The arguments act as a signal
% to the running footer telling it to insert some text or not.
% \begin{macrocode}
\def\SolContMrk#1#2{\gdef\solContMarks{{#1}{#2}}}
% \end{macrocode}
% The default definition of \cs{solContMarks}
% \begin{macrocode}
\def\solContMarks{{}{}}
% \end{macrocode}
% We use \cs{eq@sqPostHeaderHook} (\cs{eq@qPostHeaderHook}) to insert some
% special code into the top of each solution. It inserts the command
% \cmd{\SolContMrk} with two arguments, the quiz number
% (\verb!Q\@shortquizCnt!, resp., \verb!Q\@quizCnt!) and the question
% number (\verb!\setQNum!).
% \begin{macrocode}
\def\eq@sqPostHeaderHook{%
\string\SolContMrk{Q\@shortquizCnt}{\setQNum}\relax}
\def\eq@qPostHeaderHook{%
\string\SolContMrk{Q\@quizCnt}{\setQNum}\relax}
\def\exer@solnheadhook{%
\string\SolContMrk{Ex}{\setENum}}
% \end{macrocode}
% \DescribeMacro{\promoteNPHskip} used if compiled for paper, this is the amount
% that we use to promote a new page. We have to do this for otherwise, if {\TeX}s
% page breaking algorithm is used, then the page number may be wrong.
% \begin{macrocode}
\newlength{\promoteNPHskip}
\setlength{\promoteNPHskip}{.1\textheight}
% \end{macrocode}
% There are two definitions of \DescribeMacro{\redefForContSolns}\cmd{\redefForContSolns},
% one for paper and one for screen. The command itself redefines the solution markers
% that appear in the solution files (\textsf{SOL} and \textsf{QSL}).
% \begin{macrocode}
\ifeqforpaper
\def\redefForContSolns{%
% \end{macrocode}
% If the document is compiled for paper, we promote a new page using the
% command \verb!\promoteNewPageHere{\promoteNPHskip}!, and modify the
% commands \cs{fpAfterSolutionsSkip} and \cmd{\belowexsolnskip}, which appear
% in the \texttt{forpaper} option.
% It's the last command that appears at the end of each solution.
% Here we clear the arguments of \cs{SolContMrk}.
% The two \cs{prior@...} commands are special hooks at the top of the
% definitions of \cs{quizSolnHeader} and \cs{exerSolnHeader}. These latter
% two hooks were added (2013/12/15) to \textsf{exerquiz}
% \begin{macrocode}
\def\prior@quizSolnHeaderHook{\promoteNewPageHere{\promoteNPHskip}}
\def\prior@exerSolnHeaderHook{\promoteNewPageHere{\promoteNPHskip}}
% \end{macrocode}
% We use \cs{eq@scratchtoks}, a token register declared in \textsf{exerquiz}
% \begin{macrocode}
\eq@scratchtoks=\expandafter{\fpAfterSolutionsSkip\SolContMrk{}{}}
\edef\@tempExp{\noexpand\promoteNewPageHere{%
\noexpand\promoteNPHskip}\the\eq@scratchtoks}
\eq@scratchtoks=\expandafter{\@tempExp}
\edef\fpAfterSolutionsSkip{\the\eq@scratchtoks}
\eq@scratchtoks=\expandafter{%
\belowexsolnskip\protect\SolContMrk{}{}}
\edef\belowexsolnskip{\noexpand\noexpand
\string\promoteNewPageHere{%
\noexpand\noexpand\string\promoteNPHskip}\the\eq@scratchtoks}
}
\else
% \end{macrocode}
% Now if the document is compiled for the screen, each solution starts
% on a new digital piece of paper, so no need to modify \cs{eqSQt} as
% above. The command \cs{fpAfterSolutionsSkip} is not used in the
% screen version, so the last command is \cs{endeqSqt}, which we
% modify.
% \begin{macrocode}
\def\redefForContSolns{%
\let\endeqSQtSAVE\endeqSQt
\def\endeqSQt{\endeqSQtSAVE\par\SolContMrk{}{}}
\let\endeqQtSAVE\endeqSQt
\def\endeqQt{\endeqQtSAVE\par\SolContMrk{}{}}
\let\endeqEXtSAVE\endeqEXt
\def\endeqEXt{\endeqEXtSAVE\par\SolContMrk{}{}}
}
\fi % \ifeqforpaper
% \end{macrocode}
% We expand \cmd\redefForContSolns at the beginning of the document so as to
% include any changes made by the document author, or another package developer.
% \begin{macrocode}
\AtBeginDocument{\redefForContSolns}
% \end{macrocode}
% \DescribeMacro{\getSolContMarks} is the command that decides whether
% to put something in the running footer. If the first argument is
% empty (we have already cleared the arguments of \cs{SolContMrk} we do
% nothing; if the first argument is nonempty, we emit a message.
% \DescribeMacro{\rfootContStr} \cmd{\rfootContStr} is the string that
% contains the string that appears in the running footer.
% \begin{macrocode}
\newcommand{\getSolContMarks}[2]{\ifcontSoln
\rfootContStr{#1}{#2}\fi}
\newcommand{\rfootContStr}[2]{Solution to {#2} continues next page}
% \end{macrocode}
% Set the running footer; this should only appear in the solutions section
% at the end of the file. \DescribeMacro{\ifcontSol}We establish a new
% switch \cs{ifcontSoln} that will be use to signal the need for a
% continuation of the solution.
% \begin{macrocode}
\newif\ifcontSoln \contSolnfalse
% \end{macrocode}
% We put this in the left footer. {\TeX} processes from left to right,
% so we need this on the left, so the switch will be set for the
% \cs{cfooter} and \cs{rfooter}. The \DescribeMacro{\bSolContMarks}\cmd{\bSolContMarks}
% command makes the decision of setting the switch \cs{ifcontSoln}. It reads the
% expansion of \cs{solContMarks}, which holds two arguments.
% \begin{macrocode}
\newcommand{\bSolContMarks}[2]{%
\def\eq@argi{#1}\def\eq@argii{#2}%
\ifx\eq@argi\@empty\global\contSolnfalse\else
\global\contSolntrue\fi}
% \end{macrocode}
% \DescribeMacro{\lFootbCont} is placed in \cs{lfooter}, and it will set the switch
% by first expanding \cs{solContMarks}, then \cs{bSolContMarks}.
% \begin{macrocode}
\def\lFootbCont{\expandafter\bSolContMarks\solContMarks}
% \end{macrocode}
% \cs{rFootCont} goes in \cs{rfooter}, and holds the continuation string.
% \begin{macrocode}
\def\rFootCont{\makebox[0pt][r]{%
\expandafter\getSolContMarks\solContMarks}}
% \end{macrocode}
% Set the left and right footers.
% \begin{macrocode}
\@ifundefined{web@footerprivate}{%
\def\addtolfooter{\expandafter
\lfooter\expandafter{\expandafter\lFootbCont\web@lfoot}}%
}{%
\def\addtolfooter{\def\web@footerprivate{\lFootbCont}}%
}
\def\addtorfooter{\expandafter
\rfooter\expandafter{\web@rfoot\rFootCont}}
% \end{macrocode}
% Install these footers at the beginning of the document. First check
% to see if the \texttt{webheadings} pagestyle is being used.
% \begin{macrocode}
\def\cs@testWH#1#2{\ifx\webfootwrapper#1
\def\cs@next{\AtBeginDocument{\addtolfooter\addtorfooter}}\else
\def\cs@next{\PackageError{contsoln.def}{%
webheadings of the web package are NOT\MessageBreak
in effect. The contsoln.def file requires\MessageBreak
webheadings}{Use the default webheadings pagestyle
from the web package.}}\fi
\cs@next
}
% \end{macrocode}
% The default definition of \cs{@oddfoot} is
%\begin{verbatim}
% \renewcommand{\@oddfoot}{\webfootwrapper{..}}
%\end{verbatim}
% So, the first token is \cs{webfootwrapper}, if that token
% is there, we install the footers, and they should work as
% expected; otherwise we declare an error.
% \begin{macrocode}
\AtBeginDocument{\expandafter\cs@testWH\@oddfoot}
% \end{macrocode}
% \begin{macrocode}
%</package>
% \end{macrocode}
%\Finale
\endinput
\def\addtolfooter{\ifx\web@lfoot\@empty
\lfooter{\lFootbCont}\else
\expandafter\lfooter\expandafter{\expandafter
\noexpand\expandafter\lFootbCont\web@lfoot}\fi
}
\def\addtorfooter{\ifx\web@rfoot\@empty
\rfooter{\rFootCont}\else
\expandafter\rfooter\expandafter{\expandafter
\noexpand\expandafter\rFootCont\web@rfoot}\fi
}
|