]> git.donarmstrong.com Git - lib.git/blob - texmf/tex/latex/exam.cls
added a new version of exam.cls
[lib.git] / texmf / tex / latex / exam.cls
1 % exam.cls
2 %
3 % A LaTeX2e document class for preparing exams.
4
5 %% exam.cls
6 %% Copyright (c) 1994, 1997, 2000, 2004 Philip S. Hirschhorn
7 %
8 % This work may be distributed and/or modified under the
9 % conditions of the LaTeX Project Public License, either version 1.3
10 % of this license or (at your option) any later version.
11 % The latest version of this license is in
12 %   http://www.latex-project.org/lppl.txt
13 % and version 1.3 or later is part of all distributions of LaTeX
14 % version 2003/12/01 or later.
15 %
16 % This work has the LPPL maintenance status "author-maintained".
17
18 % This work consists of the files exam.cls and examdoc.tex.
19
20
21 % The user documentation for exam.cls is in the file examdoc.tex.
22
23
24 %%% Philip Hirschhorn
25 %%% Department of Mathematics
26 %%% Wellesley College
27 %%% Wellesley, MA 02481
28 %%% psh@math.mit.edu
29
30 % The newest version of this documentclass should always be available
31 % from my web page: http://www-math.mit.edu/~psh/
32
33
34 \def\fileversion{2.2}
35 \def\filedate{2004/08/14}
36 %---------------------------------------------------------------------
37 %---------------------------------------------------------------------
38 % PLEASE DO NOT MAKE ANY CHANGES TO THIS FILE!
39
40 % If you wish to make changes to this file, rename this file
41 % to something other than exam.cls BEFORE YOU MAKE THE CHANGES!
42
43 % If there's some feature that you'd like that this file doesn't
44 % provide, tell me about it.
45
46 %
47 %
48 %
49 %
50 % Thanks to:
51 %
52 % Piet van Oostrum, from whose excellent ``fancyheadings.sty'' we
53 % shamelessly stole most of the code for setting the headers and
54 % footers.
55 %
56 % Mate Wierdl <mw@wierdlmpc.msci.memphis.edu>, who contributed the
57 % code so that if the number of points is ``1'', then the default
58 % value of \pointname will print ``1 point'' instead of ``1 points''.
59 %
60 % Tom Brikowski <brikowi@utdallas.edu>, who contributed the code for
61 % making the number of points and number of questions available as
62 % macros (as well as the idea of putting the number of points in a 
63 % box, instead of in parentheses).  (I changed his code to make this
64 % all optional, so if there are errors there, it's my fault and not
65 % his.)
66 %
67 % Ottmar Beucher <beucher@fh-karlsruhe.de>, Dan Drake
68 % <drake@math.umn.edu>, and Justus Piater <Justus.Piater@ULg.ac.be> who
69 % contributed ideas and code for the \pointsofquestion and \gradetable
70 % commands for printing a Grading Table.  (I changed all the code to
71 % make this compatible with hyperref.sty, so if there are errors there,
72 % it's my fault and not theirs.)
73 %
74 % Justus Piater <Justus.Piater@ULg.ac.be>, who contributed the code for
75 % the solution environment.  (I changed his code to allow page breaks
76 % inside solutions so, once again, if it's buggy, it's my fault.) 
77 %
78 % Donald Arseneau <asnd@triumf.ca>, who created the excellent
79 % ``framed.sty'' and generously allowed me to include basically the
80 % whole thing in exam.cls, making the few changes needed for it to
81 % work well with question environments:
82 % framed.sty   v 0.8a   21-Jul-2003
83 % Copyright (C) 1992-2003 by Donald Arseneau
84 % These macros may be freely transmitted, reproduced, or modified
85 % provided that this notice is left intact.
86 %
87 %--------------------------------------------------------------------
88 %--------------------------------------------------------------------
89 %                             Changelog:
90
91
92 % Version 2.2:
93 %
94 % Enough already with betatest.
95 %
96 %--------------------------------------------------------------------
97 %
98 % Version 2.116$\beta$:
99 %
100 % We futzed with the oneparchoices environment so that a bit more
101 % space will be left before the first choice when the list of choices
102 % continues the paragraph of the question.
103 %
104 %--------------------------------------------------------------------
105 %
106 % Version 2.115$\beta$:
107 %
108 % New environment: oneparchoices
109 %
110 % Intended for multiple choice questions (just like the choices
111 % environment), except that the oneparchoices prints all the choices in
112 % a single paragraph.  This environment does *not* create a paragraph
113 % break at its beginning, so if you begin the environment without
114 % skipping a line before it, the choices will be printed as a
115 % continuation of the paragraph preceding the environment.
116 %
117 %--------------------------------------------------------------------
118 %
119 % Version 2.114$\beta$:
120 %
121 % We fixed up the code for \uplevel and \fullwidth so that they work
122 % correctly if a solution environment is inside the argument.
123 %
124 %--------------------------------------------------------------------
125 %
126 % Version 2.113$\beta$:
127 %
128 % Added code to warn if point totals have changed since the last run of
129 % LaTeX (which requires running LaTeX again to make sure that
130 % gradetables, pointsofquestion, and pointsonpage values are correct).
131 %
132 %
133 % We also added code to create a label for every question, part,
134 % subpart, and subsubpart.  We make no use of these labels, but we put
135 % them there so that if a question (or part, etc.) is, e.g., moved from
136 % one page to another, LaTeX will notice this and warn the user that
137 % LaTeX must be run one more time to be sure everything is correct.
138 %
139 % We need to do this even though we've already included code to check
140 % when point totals change because questions (and parts, etc.) know what
141 % page they're on from reading the info written to the .aux file on the
142 % previous run.  Thus, if a question (or part, etc.) is moved to a
143 % different page, then the pointsonpage totals won't notice until the
144 % *second* subsequent run of LaTeX, and so there'll be no warning to the
145 % user on the *first* run.  Including these labels gives the user a
146 % warning on that first run.
147 %
148 %--------------------------------------------------------------------
149 %
150 % Version 2.112$\beta$:
151 %
152 % New environment: coverpages
153 %
154 % This is for use only *before* any questions (or parts, or subparts, or
155 % subsubparts).  It allows you to print one or more cover pages,
156 % numbered in a different sequence of page numbers from the main pages.
157 % That is, the page number is reset to 1 at the end of a coverpages
158 % environment.
159 %
160 % The default is that headers and footers are empty on the coverpages,
161 % but if you print the page number (using \thepage in the header or
162 % footer) then the page number will be printed in roman numerals.  When
163 % the coverpages environment ends, the page number is reset to 1 and the
164 % page numbers revert to the (standard) arabic numbers.
165 %
166 % Headers and footers on coverpages are determined by commands
167 % completely analogous to the relevant commands for the main pages,
168 % except that the names of the commands begin with the word ``cover''.
169 % That is, the following commands are available to define headers and
170 % footers, and to leave additional space for the headers and footers as
171 % needed: 
172 %
173 %
174 % New commands:
175 %
176 % \coverheader
177 % \coverrunningheader
178 % \coverfirstpageheader
179 %
180 % \coverlhead
181 % \coverchead
182 % \coverrhead
183 %
184 % \coverfooter
185 % \coverrunningfooter
186 % \coverfirstpagefooter
187 %
188 % \coverlfoot
189 % \covercfoot
190 % \coverrfoot
191 %
192 % \coverextraheadheight
193 % \coverextrafootheight
194 %
195 %--------------------------------------------------------------------
196 %
197 % Version 2.111$\beta$:
198 %
199 % Bugfix: There was an incompatibility with spanish.ldf (loaded when the
200 % user loads the babel package with the spanish option) (and possibly
201 % with other language packages as well).  That file redefines \@roman,
202 % which is used by \roman, which I had used to define some internally
203 % used command names.  I replaced
204 %
205 %   \roman{countername}
206 %
207 % with
208 %
209 %   \romannumeral \csname c@countername\endcsname
210 %
211 % for all of those command names, and now all at least seems to be
212 % well.
213 %
214 %
215 % The following stuff isn't really complete yet:
216 % New environment: coverpages
217 %
218 % New commands:
219 %
220 % \coverheader
221 % \coverrunningheader
222 % \coverfirstpageheader
223 %
224 % \coverlhead
225 % \coverchead
226 % \coverrhead
227 %
228 % \coverfooter
229 % \coverrunningfooter
230 % \coverfirstpagefooter
231 %
232 % \coverlfoot
233 % \covercfoot
234 % \coverrfoot
235 %
236 % \coverextraheadheight
237 % \coverextrafootheight
238 %
239 %--------------------------------------------------------------------
240 %
241 % Version 2.110$\beta$:
242 %
243 % We change the definition of \half to print a fraction one half that
244 % uses a slanted fraction bar.  We also created two new commands:
245 %
246 %   \newcommand*\usehorizontalhalf
247 %   \newcommand*\useslantedhalf
248 %
249 % The first one changes the definition of \half so that it produces a
250 % fraction with a horizontal fraction bar (via $\frac{1}{2}$), and the
251 % second one returns the definition of \half to its default.
252 %
253 %--------------------------------------------------------------------
254 %
255 % Version 2.109$\beta$:
256 %
257 % Point values for questions (and parts, etc.) can now include half
258 % points.  To specify a half point, you include ``\half'' immediately
259 % following the integer part (or just with ``\half'' if the integer part
260 % is zero).  For example, the following are all valid point values:
261 %
262 % 0
263 % \half
264 % 1
265 % 1\half
266 % 2
267 % 2\half
268 % Etc.
269 %
270 %--------------------------------------------------------------------
271 %
272 % Version 2.108$\beta$:
273 %
274 % New environment: solutionorlines
275 %
276 % This is almost identical to the solution environment, except that when
277 % solutions are not being printed and an optional argument appears
278 % specifying an amount of space to be left for answers, that space is
279 % filled with ruled lines (created by \fillwithlines), rather than being
280 % left blank (as it is by the solution environment).
281 %
282 % Also: Changed the shade of gray used as the default color for
283 %       \shadedsolutions.
284 %
285 %       Changed the default thickness of lines used by \fillwithlines.
286 %
287 %--------------------------------------------------------------------
288 %
289 % Version 2.107$\beta$:
290 %
291 % We added an option to have solution environments use a \colorbox (from
292 % the color package) instead of an \fbox.  Instead of surrounding the
293 % solution with a printed box, it prints the solution on a colored
294 % background.  The default color is a light gray (so that it can be
295 % printed on any printer that can do grayscale), but the color can be
296 % changed.
297 %
298 % To use this option, the user must load the color package with the
299 % command
300 %
301 %   \usepackage{color}
302 %
303 % in the preamble.  (If appropriate, optional arguments can be used in
304 % that command.)  The user can then give the command
305 %
306 %   \shadedsolutions
307 %
308 % to have all solutions printed using a \colorbox.  After giving that
309 % command, the user can change the color of the backgrounds of solutions
310 % by defining the color ``SolutionColor''.  The default SolutionColor is
311 % set via the command
312 %
313 %   \definecolor{SolutionColor}{gray}{0.9}
314 %
315 % and the user can change that by giving a \definecolor command *after*
316 % giving the command \shadedsolutions.  For example, the command
317 %
318 %   \definecolor{SolutionColor}{rgb}{0.8,0.9,1}
319 %
320 % sets the background color to a light blue.
321 %
322 % You can return to the default situation of having solutions printed
323 % inside an \fbox by giving the command
324 %
325 %   \framedsolutions
326 %
327 % Note added later: The default shade of gray was changed in version
328 % 2.108$\beta$.
329 %
330 %--------------------------------------------------------------------
331 %
332 % Version 2.106$\beta$:
333 %
334 %
335 % We redid the solution environment to use Donald Arseneau's framed.sty
336 % macros, so that the solution can be broken across pages with each
337 % piece enclosed in a frame.
338 %
339 % We also changed the default definition of \solutiontitle; it's now
340 % defined by:
341 %
342 %  \newcommand{\solutiontitle}{\noindent\textbf{Solution:}\enspace}
343 %
344 %
345 %--------------------------------------------------------------------
346 %
347 % Version 2.105$\beta$:
348 %
349 % We're making the thickness of the lines used by \fillwithlines
350 % changeable, and changing the default thickness.
351 %
352 % We're doing this by defining a new command:
353 %
354 %   \linefill,
355 %
356 % which is similar to \hrulefill, except that \linefill uses a line of
357 % height \linefillthickness, whose default value is 0.2pt.
358 % (\fillwithlines used to use \hrulefill, which uses a line of height
359 % 0.4pt.)
360 %
361 % The default value of \linefillthickness is set by the command
362 %
363 %   \setlength\linefillthickness{0.2pt}
364 %
365 % and this can be changed by giving a new \setlength command.
366 %
367 % Note added later: The default thickness was changed in version
368 % 2.108$\beta$.
369 %
370 %--------------------------------------------------------------------
371 %
372 % Version 2.104$\beta$:
373 %
374 % We added a new command: \fillwithlines
375 %
376 % \fillwithlines takes one argument, which is either a length or \fill,
377 % and it fills that much vertical space with horizontal lines that run
378 % the length of the current line.  That is, they extend from the current
379 % left margin (which depends on whether we're in a question, part,
380 % subpart, or subsubpart) to the right margin.
381 %
382 % The distance between the lines is \linefillheight, whose default value
383 % is set with the command
384 %
385 %   \setlength\linefillheight{.25in}
386 %
387 % This value can be changed by giving a new \setlength command.
388 %
389 %--------------------------------------------------------------------
390 %
391 % Version 2.103$\beta$:
392 %
393 % We added a new command: \answerline
394 %
395 % This is intended for short answer questions.  It inserts a \vskip of
396 % length \answerskip and then inserts a horizontal line of length
397 % \answerlinelength at the right margin, preceded by the number of the
398 % current question, part, subpart, or subsubpart.
399 %
400 % The default values are set by the commands
401 %
402 %   \setlength\answerlinelength{1in}
403 %   \setlength\answerskip{2ex}
404 %
405 % and these can be changed by giving new \setlength commands.
406 %
407 %--------------------------------------------------------------------
408 %
409 % Version 2.101$\beta$:
410 %
411 % We eliminated the command \marks, since it conflicts with a definition
412 % of that name in some package or other.  We changed the definition of
413 % \marksnotpoints so that it still accomplishes the same thing, but now
414 % it works through the \pointpoints command.
415 %
416 % We changed the default format for the \droptotalpoints command, so
417 % that it now prints
418 %
419 %   Total for Question 1: 25
420 %
421 % where the ``25'' is followed by \marginpointname, whose default value
422 % is empty.
423 %
424 %--------------------------------------------------------------------
425 %
426 % Version 2.098$\beta$:
427 %
428 % We moved the definitions of \thepartno, \thesubpart, and
429 % \thesubsubpart outside of the associated list environments, so that
430 % the user can redefine them once at the beginning of the LaTeX file and
431 % not have their redefinition overridden in every such list.
432 %
433 % We also replaced most occurrences of \thequestion with
434 % \arabic{question}, so that the user can safely redefine \thequestion
435 % to something like \Alph{question}, etc.
436 %
437 % We rewrote the components of the \gradetable[v][questions] and
438 % \gradetable[h][questions] to use the question counter in place of
439 % @iterator, and to insert \thequestion instead of \the@iterator as the
440 % question number in the table (so that if the user redefines
441 % \thequestion, then the table will print the question ``numbers'' (or
442 % letters, etc.) in whatever format \thequestion prints the question
443 % numbers on the exam).
444 %
445 % We also created a new command:
446 %
447 %   \totalpoints
448 %
449 % for use in the argument of a \totalformat command.  \totalpoints is
450 % just an abbreviation for \pointsofquestion{\arabic{question}}.  That
451 % is, it's a macro that prints the total number of points for the
452 % current question.
453 %
454 % We changed the longsolution environment to make it easy to change the
455 % amount by which the left and right margins are increased.  The default
456 % amount is set by the command
457 %
458 %   \setlength{\longsolutionindent}{2em}
459 %
460 % and the user can change this by giving a new \setlength command.
461 %
462 % Note added later: longsolution was eliminated in version
463 % 2.106$\beta$.
464 %
465 %--------------------------------------------------------------------
466 %
467 % Version 2.097$\beta$:
468 %
469 % We've changed the default format for the total points for a question
470 % printed by the \droptotalpoints command.  This command still prints
471 % the total points for the question right justified a distance of
472 % \rightpointsmargin from the right edge of the paper, but now the
473 % number of points will, by default, be surrounded by either
474 %
475 %   a double box, if \boxedpoints is in effect,
476 %   double brackets, if \bracketedpoints is in effect, or
477 %   double parentheses, otherwise.
478 %
479 % It's still true that if you use a \totalformat command, then the
480 % format of the printed total points is completely controlled by the
481 % argument of the \totalformat command and the default doesn't matter at
482 % all.
483 %
484 %
485 % Note added later: We changed the default format again in version
486 % 2.101$\beta$; see the notes above.
487 %
488 %--------------------------------------------------------------------
489 %
490 % Version 2.096$\beta$:
491 %
492 % The labels for questions, parts, subparts, and subsubparts can now be
493 % customized.  The format now depends on the commands
494 %
495 %   \questionlabel
496 %   \partlabel
497 %   \subpartlabel
498 %   \subsubpartlabel
499 %
500 % the default definitions of which are:
501 %
502 %   \newcommand\questionlabel{\thequestion.}
503 %   \newcommand\partlabel{(\thepartno)}
504 %   \newcommand\subpartlabel{\thesubpart.}
505 %   \newcommand\subsubpartlabel{\thesubsubpart)}
506 %
507 % These definions can be changed by using a \renewcommand command.
508 % Note that the definition of \partlabel used `\thepartno', and *not*
509 % `\thepart'.  This is because `\thepart' refers to the counter for the
510 % standard sectioning command \part, and not the counter used in the
511 % parts environment.  The counter used by the parts environment is
512 % inserted with the command `\thepartno'.
513 %
514 %--------------------------------------------------------------------
515 %
516 % Version 2.095$\beta$:
517 %
518 % Added solution and longsolution environments.
519 %
520 % The command \printanswers causes both of these environments print the
521 % solution, and the command \noprintanswers causes both of these
522 % environments not to print the solution.  The default is
523 % \noprintanswers.
524 %
525 % The commands \printanswers and \noprintanswers can be given as many
526 % times as desired to switch back and forth between the two.
527 %
528 % The documentclass option ``answers'' is equivalent to giving a
529 % \printanswers command at the beginning of the file.
530 %
531 %
532 % Both of these environments take an optional argument which is an
533 % amount of blank vertical space to be left when \noprintanswers is in
534 % effect.  (The default value of this blank vertical space is 0pt.)
535 %
536 %
537 % The solution environment prints the solution inside of a box, which
538 % cannot be broken across pages.  Thus, it is only appropriate for
539 % solutions that are short enough to fit on a page.
540 %
541 % The longsolution environment prints the solution with left and right
542 % margins slightly increased, and it can be broken across pages.
543 %
544 % When printing the solution, both environments begin with
545 % \solutiontitle, the default value of which is created by the command
546 %
547 % \newcommand{\solutiontitle}{\textbf{Solution:}\enspace}
548 %
549 % This can be changed with the \renewcommand command.
550 %
551 % Note added later: solution was changed and longsolution was
552 % eliminated in version 2.106$\beta$.
553 %
554 %--------------------------------------------------------------------
555 %
556 % Version 2.094$\beta$:
557 %
558 % We've expanded the options of the \gradetable command, so that you
559 % can now get a grading table indexed by either question numbers or by
560 % page numbers, and in either case you can have either a horizontally
561 % oriented table or a vertically oriented table.
562 %
563 % \gradetable now takes two optional arguments: The first can be either
564 % `[v]' or `[h]', and the second can be either `[questions]' or
565 % `[pages]'.  The defaults are `[v]' and `[questions]', and you must
566 % specify a first option if you want to specify a second option.
567 %
568 % Thus: \gradetable is equivalent to \gradetable[v][questions]
569 %
570 % `[v]' and `[h]' are as before: Vertically oriented or horizontally
571 % oriented.
572 %
573 % `[questions]' is the same as the earlier version: A table that lists
574 % the question numbers, the possible total points for each question the
575 % total for the entire exam, and spaces are left for the score on each
576 % question.
577 %
578 % `[pages]' prints a table indexed by page numbers instead of by
579 % question numbers.  It lists only the numbers of pages that have points
580 % on them, and for each such page it lists the number of points possible
581 % on that page.  It also lists the total possible points on the exam,
582 % and spaces are left for the score on each page.
583 %
584 % For both tables indexed by questions and tables indexed by points,
585 % there are commands that allow you to change the column and row
586 % headings (the following are shown setting the default values:)
587 %
588 %    \hpword{Points:}
589 %    \hsword{Score:}
590 %    \htword{Total}
591 %    \vpword{Points}
592 %    \vsword{Score}
593 %    \vtword{Total:}
594 %
595 % For tables indexed by questions, the appropriate row and column titles
596 % are set by the following commands:
597 %
598 %    \hqword{Question:}
599 %    \vqword{Question}
600 %
601 % For tables indexed by pages, the appropriate row and column titles are
602 % set by the following commands:
603 %
604 %    \hpgword{Page:}
605 %    \vpgword{Page}
606 %
607 %
608 % For both \gradetable[h] and \gradetable [v], the width of the blank
609 % cells created for filling in the grades can be changed with the
610 % command \cellwidth, and the arraystretch applied to the table can be
611 % changed with the command \gradetablestretch.  The default values are
612 % created by the commands:
613 %
614 %   \cellwidth{2em}
615 %   \gradetablestretch{1.5}
616 %
617 %--------------------------------------------------------------------
618 %
619 % Version 2.093$\beta$:
620 %
621 % If the user gives the comman \addpoints, then
622 % \pointsonpage{n} expands to the number of points on page n.
623 %
624 %--------------------------------------------------------------------
625 %
626 % Version 2.092$\beta$:
627 %
628 % Increased the \leftmargin in the choices environment.
629 %
630 %--------------------------------------------------------------------
631 %
632 % Version 2.091$\beta$:
633 %
634 % New commands:
635 % \pointsdroppedatright
636 % \droppoints
637 % \droptotalpoints
638 % \totalformat
639 %
640 % \pointsdroppedatright: The command \pointsdroppedatright causes points
641 % not to be printed until you give the command \droppoints, except that
642 % a \qformat command still works as expected (i.e., if you include
643 % ``\thepoints'' in the argument of the \qformat, it will print the
644 % points as usual).
645 %
646 %
647 % \droppoints: The command \droppoints should be given only at the end
648 % of a paragraph or between paragraphs; if you give it within a
649 % paragraph, it causes the paragraph to end.  \droppoints prints the
650 % most recent point value in the right margin, formatted as it is when
651 % you give the command \pointsinrightmargin, except that the points
652 % appear opposite the last line of the paragraph (or, if the command
653 % \droppoints is given between paragraphs, then additional vertical
654 % space is left between the paragraphs and the points are printed
655 % opposite the blank space).  Thus, the formatting can be changed by
656 % using giving the commands \bracketedpoints, \boxedpoints, or
657 % \marginpointname.
658 %
659 % The command \droppoints actually works this way even if one of the
660 % commands \pointsdroppedatright, \pointsinmargin, or
661 % \pointsinrightmargin, is in effect, but if you use it that way the
662 % points will appear twice on the page.
663 %
664 %
665 % \droptotalpoints: To use the command \droptotalpoints, you must first
666 % give the command \addpoints.  The command \droptotalpoints should be
667 % given only at the end of a paragraph or between paragraphs; if you
668 % give it within a paragraph, it causes the paragraph to end.
669 % \droptotalpoints prints the total points for the current question
670 % (i.e., the sum of the points assigned to the question and to all of
671 % its parts, subparts, and subsubparts) in the right margin, formatted
672 % formatted by default inside either double brackets, double box, or
673 % double parentheses, depending on whether \bracketedpoints,
674 % \boxedpoints, or neither is in effect.
675 %
676 % \totalformat: The \totalformat command allows you to change the format
677 % used by the \droptotalpoints command.  It takes one argument, and that
678 % argument becomes the command to print the total points, right
679 % justified a distance of \rightpointsmargin from the right edge of the
680 % paper.  The argument should contain the expression
681 % ``\pointsofquestion{\arabic{question}}'' at the point at which the number
682 % of points should appear.  For example, the command
683 %
684 %   \totalformat{[\pointsofquestion{\arabic{question}}]}
685 %
686 % will produce the same appearance as the default does when the command
687 % \bracketedpoints is in effect and \marginpointname is empty, and the
688 % command
689 %
690 %   \totalformat{\fbox{Total: \pointsofquestion{\arabic{question}}}}
691 %
692 % produces a box surrounding ``Total: 25''.
693 %
694 %--------------------------------------------------------------------
695 %
696 % Version 2.087$\beta$:
697 %
698 % We changed ``\point@toks={}'' into ``\global \point@toks={}'' when
699 % \point@toks is set, so that if the user somehow arranges for us to be
700 % inside of a group when we enter horizontal mode, the \point@toks will
701 % be properly set equal to null, and so the points won't accidentally be
702 % placed a second time at the second paragraph of the question.
703 %
704 % Similarly, we changed ``\pageinfo@commands={}'' to 
705 % ``\global \pageinfo@commands={}''.
706 %
707 %--------------------------------------------------------------------
708 %
709 % Version 2.080$\beta$:
710 %
711 % We added a new command \gradetable that produces a grading table,
712 % oriented either vertically or horizontally, that lists the questions,
713 % their point values, and the total points, and leaves spaces for
714 % entering the grade for each question and the total grade.  We also
715 % added a new command \pointsofquestion that takes one argument that is
716 % assumed to be the number of a question and returns the total number of
717 % points for that question.  \pointsofquestion is used by the
718 % \gradetable command, but the user can choose to use it separately.
719
720 % To use either \gradetable or \pointsofquestion, the user must give the
721 % command \addpoints.  \pointsofquestion{n} will then return the total
722 % number of points for question n and all of its parts, subparts, and
723 % subsubparts.  Since all this information is stored in the .aux file
724 % and then read back on the next run of LaTeX, the user must run LaTeX
725 % twice after any changes to the questions or points.
726
727 % \gradetable[h] produces a horizonatlly oriented grade table, and
728 % \gradetable[v] produces a vertically oriented grade table.  The
729 % command \gradetable is equivalent to \gradetable[v].
730
731 % \gradetable[h] produces a table with three rows, titled (by default)
732 % ``Question:'', ``Points:'', and ``Score:'' (the titles are in the
733 % first column of the table).  There is then one column for each
734 % question (with the question number and point value in the first two
735 % rows), plus a final column labelled ``Total'' with the total points in
736 % the second row.
737
738 % \gradetable[v] produces a table with three columns, titled (by
739 % default) ``Question'', ``Points'', and ``Score'' (the titles are in
740 % the first row of the table).  There is then one row for each question
741 % (with the question number and point value in the first two columns),
742 % plus a final row labelled ``Total:'' with the total points in the
743 % second column.
744
745 % Note that \gradetable[h] produces row titles whose default values
746 % contains colons, while \gradetable[v] produces column titles whose
747 % default values do not contain colons.
748
749 % The row and column titles and the word ``Total'' can be changed using
750 % the commands \hqword, \hpword, \hsword, \htword, \vqword,
751 % \vpword, \vsword, and \vtword, where the first four affect
752 % \gradetable[h] and the second four affect \gradetable[v].  The default
753 % values are created by the commands:
754
755 %   \hqword{Question:}
756 %   \hpword{Points:}
757 %   \hsword{Score:}
758 %   \htword{Total}
759 %   \vqword{Question}
760 %   \vpword{Points}
761 %   \vsword{Score}
762 %   \vtword{Total:}
763
764 % For both \gradetable[h] and \gradetable [v], the width of the blank
765 % cells created for filling in the grades can be changed with the
766 % command \cellwidth, and the arraystretch applied to the table can be
767 % changed with the command \gradetablestretch.  The default values are
768 % created by the commands:
769
770 %   \cellwidth{2em}
771 %   \gradetablestretch{1.5}
772
773
774
775 % Changing the definition of \points:
776
777 % The default definition of \points is that it expands to ``point'' if
778 % the number of points is 1 and to ``points'' otherwise.  There is now a
779 % command ``\pointpoints'' that takes two arguments, after which
780 % \points will expand to the first argument when the number of points is
781 % 1 and to the second argument otherwise.  For example, the default is
782 % the result of the command \pointpoints{point}{points}.
783 %
784 %--------------------------------------------------------------------
785 %
786 % Version 2.070$\beta$:
787 %
788 % We made this compatible with hyperref.sty.
789 % We did this by eliminating all use of LaTeX's 
790 % \label, \newlabel, \ref, and \pageref commands.
791 % We now put information into the .aux file using the
792 % \PgInfo@write command, and get that info out of the aux file
793 % using \PgInfo and \PgInfo@get, along with a few \gdef commands
794 % written straight to the .aux file.
795 %
796 %--------------------------------------------------------------------
797 %
798 % Version 2.067$\beta$:
799 %
800 % We're adding code to enable headers and footers
801 % to know whether the current page continues a question started on an
802 % earlier page, and whether the page ends with a question still
803 % incomplete.
804
805 %--------------------------------------------------------------------
806 % For use in headers and footers:
807 %
808 % \ifcontinuation{Text 1}{Text 2}
809 % Expands to ``Text 1'' if this page begins with a part or subpart or
810 % subsubpart that continues a question begun on an earlier page, and
811 % expands to ``Text 2'' if this page begins with a new question.
812 %
813 % \ContinuedQuestion expands to the number of the question that is
814 % being continued from an earlier page.
815 %
816 % \ifincomplete{Text 1}{Text 2}
817 % Expands to ``Text 1'' if the last question begun on or before this
818 % page has a part, subpart, or subsubpart that begins on a later page,
819 % and if we have not yet encountered a \nomorequestions command.
820 %
821 % \IncompleteQuestion expands to the number of the question that is
822 % continued on the next page.
823 %
824 % \nomorequestions is a command that you can give after the last
825 % question if you intend to include extra material (e.g., tables for
826 % use on the exam) but you don't want the pages containing the extra
827 % material to be labelled as continuing the last question on the exam.
828 %
829 %--------------------------------------------------------------------
830 %
831 %
832 % Also: 
833 % Changed the code for headers and footers to
834 % use the command \normalfont instead of \rm so that the main
835 % document font will appear in headers and footers even when the
836 % main document font is *not* a roman font.
837 %
838 % \def\marksnotpoints
839 %
840 % Changes \pointname so that it is identical to the default \pointname
841 % except that the work ``mark'' is used instead of the word
842 % ``point''.  That is, if the number of points is 1, then you'll get
843 % ``1 mark'', and if the number of points is other than 1 then you'll
844 % get ``n marks'' (where n is the number of points).
845 %
846 %
847 % \bracketedpoints
848 % \nobracketedpoints
849 %
850 % The default remains to put the points inside of parentheses.
851 % \bracketedpoints switches to points inside of square brackets and
852 % \boxedpoints switches to points in side of a box.  Both
853 % \nobracketedpoints and \noboxedpoints return to the default of
854 % points inside of parentheses no matter how many \boxedpoints and
855 % \bracketedpoints commands have been given in any order.
856 %
857 %
858 % \pointsinrightmargin
859 % \nopointsinrightmargin
860 %
861 % The default remains to put the points right after the question
862 % number, before the text of the question. \pointsinrightmargin
863 % switches to points in the right margin and \pointsinleftmargin
864 % switches to points in the left margin.  Both \nopointsinrightmargin
865 % and \nopointsinleftmargin return to the default of points right
866 % after the question number, before the text of the question, no
867 % matter how many \pointsinrightmargin and \pointsinleftmargin
868 % commands have been given in any order. 
869 %
870 % if \pointsinrightmargin is used, then the points are printed
871 % right justified in the right margin, with the right edge a distance
872 % of \rightpointsmargin from the right edge of the paper.
873 % The default value of \rightpointsmargin is 1 cm, but it can be set
874 % to any other length with the usual \setlength command
875 % (as in \setlength{\rightpointsmargin}{0.5cm}).
876 %
877 %
878 % subsubparts environment
879 % Numbered using lower case greek letters.
880 %
881 %
882 % choices environment, for multiple choice answers
883 %
884 %
885 % \qformat{Format line}
886
887 % Format line must have some stretch (e.g., at least one \hfil or
888 % \dotfill or something similar).
889 % \thequestion inserts the question number,
890 % \thepoints inserts the number of points followed by pointname if
891 %   a number of points has been specified for this question, and it
892 %   inserts nothing at all if no points have been specified.
893 %
894 % \noqformat returns to the standard question number formatting.
895 %
896 %
897 %
898 % The standard options
899 %   a4paper
900 %   a5paper
901 %   b5paper
902 %   letterpaper
903 %   legalpaper
904 %   executivepaper
905 %   landscape
906 % now all work.
907 %
908 %
909 %
910 % Two new commands for use in \pointname, \marginpointname, and
911 % \qformat: 
912 %
913 % \points expands to either ``point'' or ``points'', depending on
914 % whether the number of points is 1 or other than 1.
915 %
916 % \marks expands to either ``mark'' or ``marks'', depending on
917 % whether the number of points is 1 or other than 1.
918 %
919 %
920 %--------------------------------------------------------------------
921 %--------------------------------------------------------------------
922 %
923 % The only change from version 2.0 to version 2.01 is that this
924 % documentclass (and its accompanying documentation) is now
925 % explicitly distributed under the LaTeX Project Public License.
926 %
927 %--------------------------------------------------------------------
928 %--------------------------------------------------------------------
929
930 \NeedsTeXFormat{LaTeX2e}
931
932 \ProvidesClass{exam}[\filedate\space Version \fileversion\space by
933   Philip Hirschhorn]
934
935 \RequirePackage{ifthen}
936
937 \newif\if@printanswers
938 \@printanswersfalse
939 \DeclareOption{answers}{\@printanswerstrue}
940 \DeclareOption{noanswers}{\@printanswersfalse}
941
942 \DeclareOption*{%
943   \PassOptionsToClass{\CurrentOption}{article}%
944 }
945 \ProcessOptions\relax
946 \LoadClass{article}
947
948
949
950
951 %                         *****************
952 %                         ** PAGE LAYOUT **
953 %                         *****************
954
955
956 % We set the parameters in terms of \paperwidth and \paperheight
957 % so that the options
958
959 % a4paper
960 % a5paper
961 % b5paper
962 % letterpaper
963 % legalpaper
964 % executivepaper
965 % landscape
966
967 % will all work:
968
969 \setlength{\textwidth}{\paperwidth}
970 \addtolength{\textwidth}{-2in}
971 \setlength{\oddsidemargin}{0pt}
972 \setlength{\evensidemargin}{0pt}
973
974 \setlength{\headheight}{15pt}
975 \setlength{\headsep}{15pt}
976 \setlength{\topmargin}{0in}
977 \addtolength{\topmargin}{-\headheight}
978 \addtolength{\topmargin}{-\headsep}
979 \setlength{\footskip}{29pt}
980 \setlength{\textheight}{\paperheight}
981 \addtolength{\textheight}{-2.2in}
982
983 \setlength{\marginparwidth}{.5in}
984 \setlength{\marginparsep}{5pt}
985
986
987
988
989
990 %--------------------------------------------------------------------
991
992 %                          ****************
993 %                          ** EXTRAWIDTH **
994 %                          ****************
995
996 \newlength\@extrawidth
997
998 % \@rightmargin is needed for \pointsinrightmargin and
999 % \pointsdroppedatright, so that we can right justify the points:
1000 \newlength\@rightmargin
1001 \setlength{\@rightmargin}{1in}
1002
1003 % We put the argument of \extrawidth into a length so that it will
1004 % work correctly even if it's negative:
1005
1006 \def\extrawidth#1{%
1007   \@extrawidth=#1
1008   \advance \textwidth by \@extrawidth
1009   \divide\@extrawidth by 2
1010   \advance\oddsidemargin by -\@extrawidth
1011   \advance\evensidemargin by -\@extrawidth
1012   % Bug fix, 13 April 2004: 
1013   %\advance\@rightmargin by \@extrawidth
1014   \advance\@rightmargin by -\@extrawidth
1015 }
1016
1017
1018
1019
1020 %--------------------------------------------------------------------
1021 %--------------------------------------------------------------------
1022 %             Making room for large headers and footers
1023
1024 % The following are used to save the effect of any changes to 
1025 % \topmargin and \textheight caused by \extraheadheight or
1026 % \extrafootheight commands.  They hold the values currently in effect.
1027 % We put them into lengths so that it will work correctly even if the
1028 % argument is negative:
1029
1030 \newlength\@extrahead
1031 \newlength\@extrafoot
1032 \setlength{\@extrahead}{0in}
1033 \setlength{\@extrafoot}{0in}
1034
1035 % The following are used to hold the requested values for extrahead and
1036 % extrafoot, first page and all pages after the first, and then the
1037 % similar things requested for the cover pages:
1038 \newlength\run@exhd
1039 \newlength\fp@exhd
1040 \newlength\run@exft
1041 \newlength\fp@exft
1042 \newlength\covrun@exhd
1043 \newlength\covfp@exhd
1044 \newlength\covrun@exft
1045 \newlength\covfp@exft
1046
1047 \setlength{\run@exhd}{0in}
1048 \setlength{\fp@exhd}{0in}
1049 \setlength{\run@exft}{0in}
1050 \setlength{\fp@exft}{0in}
1051 \setlength{\covrun@exhd}{0in}
1052 \setlength{\covfp@exhd}{0in}
1053 \setlength{\covrun@exft}{0in}
1054 \setlength{\covfp@exft}{0in}
1055
1056
1057 \newcommand*\adj@hdht@ftht{%
1058   \if@coverpages
1059     \ifnum\value{page}=1
1060       \@setheadheight{\covfp@exhd}%
1061       \@setfootheight{\covfp@exft}%
1062     \else
1063       \@setheadheight{\covrun@exhd}%
1064       \@setfootheight{\covrun@exft}%
1065     \fi
1066   \else
1067     \ifnum\value{page}=1
1068       \@setheadheight{\fp@exhd}%
1069       \@setfootheight{\fp@exft}%
1070     \else
1071       \@setheadheight{\run@exhd}%
1072       \@setfootheight{\run@exft}%
1073     \fi
1074   \fi
1075 }
1076
1077
1078 \newcommand*\extraheadheight{%
1079   \@ifnextchar[{\@xtrahd}{\@ytrahd}%
1080 }
1081
1082 \def\@xtrahd[#1]#2{%
1083   \setlength{\fp@exhd}{#1}%
1084   \setlength{\run@exhd}{#2}%
1085   \adj@hdht@ftht
1086 }
1087
1088 \def\@ytrahd#1{%
1089   \setlength{\fp@exhd}{#1}%
1090   \setlength{\run@exhd}{#1}%
1091   \adj@hdht@ftht
1092 }
1093
1094 \newcommand*\extrafootheight{%
1095   \@ifnextchar[{\@xtraft}{\@ytraft}%
1096 }
1097
1098 \def\@xtraft[#1]#2{%
1099   \setlength{\fp@exft}{#1}%
1100   \setlength{\run@exft}{#2}%
1101   \adj@hdht@ftht
1102 }
1103
1104 \def\@ytraft#1{%
1105   \setlength{\fp@exft}{#1}%
1106   \setlength{\run@exft}{#1}%
1107   \adj@hdht@ftht
1108 }
1109
1110
1111 \newcommand*\coverextraheadheight{%
1112   \@ifnextchar[{\cov@xtrahd}{\cov@ytrahd}%
1113 }
1114
1115 \def\cov@xtrahd[#1]#2{%
1116   \setlength{\covfp@exhd}{#1}%
1117   \setlength{\covrun@exhd}{#2}%
1118   \adj@hdht@ftht
1119 }
1120
1121 \def\cov@ytrahd#1{%
1122   \setlength{\covfp@exhd}{#1}%
1123   \setlength{\covrun@exhd}{#1}%
1124   \adj@hdht@ftht
1125 }
1126
1127 \newcommand*\coverextrafootheight{%
1128   \@ifnextchar[{\cov@xtraft}{\cov@ytraft}%
1129 }
1130
1131 \def\cov@xtraft[#1]#2{%
1132   \setlength{\covfp@exft}{#1}%
1133   \setlength{\covrun@exft}{#2}%
1134   \adj@hdht@ftht
1135 }
1136
1137 \def\cov@ytraft#1{%
1138   \setlength{\covfp@exft}{#1}%
1139   \setlength{\covrun@exft}{#1}%
1140   \adj@hdht@ftht
1141 }
1142
1143 \def\@appendoutput#1{%
1144   \output=\expandafter{\the\output #1}%
1145 }
1146
1147 \@appendoutput{\adj@hdht@ftht}
1148
1149 %--------------------------------------------------------------------
1150 %                 \setheadheight and \setfootheight:
1151
1152 \def\@setheadheight#1{%
1153   \begingroup % Avoid trouble from using \@temp and \@spaces
1154     % Reset the effect of the most recent change:
1155     \global\advance\topmargin by -\@extrahead
1156     \global\advance\textheight by \@extrahead
1157     % Save the newly set value:
1158     \def\@temp{#1}
1159     \def\@spaces{ }
1160     \ifx\@temp\@empty
1161       \global\@extrahead=0in
1162     \else
1163       \ifx\@temp\@spaces
1164         \global\@extrahead=0in
1165       \else
1166         \global\@extrahead=#1
1167       \fi
1168     \fi
1169     % Set the new values:
1170     \global\advance\topmargin by \@extrahead
1171     \global\advance\textheight by -\@extrahead
1172     % Make it take effect RIGHT NOW!:
1173     % (The following stuff isn't necessary if \@setheadheight is
1174     % executed only in the preamble or as we return from the output
1175     % routine, but we're leaving it in so that this will still work if
1176     % we use this at some random point in the middle of composing a
1177     % page). 
1178     \global\@colht=\textheight
1179     \global\@colroom=\textheight
1180     \global\vsize=\textheight
1181     \global\pagegoal=\textheight
1182   \endgroup
1183 }
1184
1185 \def\@setfootheight#1{%
1186   \begingroup % Avoid trouble from using \@temp and \@spaces
1187     % Reset the effect of the most recent change:
1188     \global\advance\textheight by \@extrafoot
1189     % Save the newly set value:
1190     \def\@temp{#1}
1191     \def\@spaces{ }
1192     \ifx\@temp\@empty
1193       \global\@extrafoot=0in
1194     \else
1195       \ifx\@temp\@spaces
1196         \global\@extrafoot=0in
1197       \else
1198         \global\@extrafoot=#1
1199       \fi
1200     \fi
1201     % Set the new values:
1202     \global\advance\textheight by -\@extrafoot
1203     % Make it take effect RIGHT NOW!:
1204     % (The following stuff isn't necessary if \@setfootheight is
1205     % executed only in the preamble or as we return from the output
1206     % routine, but we're leaving it in so that this will still work if
1207     % we use this at some random point in the middle of composing a
1208     % page). 
1209     \global\@colht=\textheight
1210     \global\@colroom=\textheight
1211     \global\vsize=\textheight
1212     \global\pagegoal=\textheight
1213   \endgroup
1214 }
1215
1216
1217
1218
1219 %---------------------------------------------------------------------
1220 %
1221 %                      *************************
1222 %                      ** HEADERS AND FOOTERS **
1223 %                      *************************
1224
1225 % The pagestyles available are head, foot, headandfoot, and empty.
1226 % \pagestyle{head} prints the head, and gives an empty foot.
1227 % \pagestyle{foot} prints the foot, and gives an empty head.
1228 % \pagestyle{headandfoot} prints both the head and the foot.
1229 % \pagestyle{empty} gives an empty head and an empty foot.
1230
1231
1232 %                            Pagestyles:
1233
1234 \newcommand*\ps@head{%
1235   \@dohead
1236   \@nofoot
1237 }
1238
1239 \newcommand*\ps@headandfoot{%
1240   \@dohead
1241   \@dofoot
1242 }
1243
1244 \newcommand*\ps@foot{%
1245   \@nohead
1246   \@dofoot
1247 }
1248
1249 % \ps@empty is already defined by article.cls, so we'll
1250 % say \def instead of \newcommand*:
1251 \def\ps@empty{%
1252   \@nohead
1253   \@nofoot
1254 }
1255
1256 \newif\if@coverpages
1257 \@coverpagesfalse
1258
1259 \newenvironment{coverpages}{%
1260     \ifnum \value{numquestions}>0
1261       \ClassError{exam}{%
1262         Coverpages cannot be used after questions have begun.\MessageBreak
1263       }{%
1264         All question, part, subpart, and subsubpart environments
1265         \MessageBreak
1266         must begin after the cover pages are complete.\MessageBreak
1267       }%
1268     \fi
1269     \@coverpagestrue
1270     \pagenumbering{roman}%
1271     \adj@hdht@ftht
1272   }{%
1273     \clearpage
1274     \pagenumbering{arabic}%
1275     \adj@hdht@ftht
1276 }
1277
1278 \newcommand*\cover@question@error{%
1279   \ClassError{exam}{%
1280     No questions are allowed in the cover pages.\MessageBreak
1281   }{%
1282     All question, part, subpart, and subsubpart environments
1283     \MessageBreak
1284     must begin after the cover pages are complete.\MessageBreak
1285   }%
1286 }
1287
1288
1289
1290 \newcommand*\@dohead{%
1291   \def\@oddhead{%
1292     \if@coverpages
1293       \ifnum\value{page}=1
1294         \cov@fullhead
1295       \else
1296         \covrun@fullhead
1297       \fi
1298     \else
1299       \ifnum\value{page}=1
1300         \@fullhead
1301       \else
1302         \run@fullhead
1303       \fi
1304     \fi
1305   }% @oddhead
1306   \let\@evenhead=\@oddhead
1307 }
1308
1309 \newcommand*\@dofoot{%
1310   \def\@oddfoot{%
1311     \if@coverpages
1312       \ifnum\value{page}=1
1313         \cov@fullfoot
1314       \else
1315         \covrun@fullfoot
1316       \fi
1317     \else
1318       \ifnum\value{page}=1
1319         \@fullfoot
1320       \else
1321         \run@fullfoot
1322       \fi
1323     \fi
1324   }% @oddfoot
1325   \let\@evenfoot=\@oddfoot
1326 }
1327
1328 \newcommand*\@nohead{%
1329   \def\@oddhead{}%
1330   \let\@evenhead=\@oddhead
1331 }
1332
1333 \newcommand*\@nofoot{%
1334   \def\@oddfoot{}%
1335   \let\@evenfoot=\@oddfoot
1336 }
1337
1338
1339
1340
1341 %--------------------------------------------------------------------
1342 %       \@fullhead, \run@fullhead, \@fullfoot, and \run@fullfoot:
1343
1344 \newcommand*\@fullhead{%
1345   \vbox to \headheight{%
1346     \vss
1347     \hbox to \textwidth{%
1348       \normalfont\rlap{\parbox[b]{\textwidth}{\raggedright\@lhead\strut}}%
1349         \hss\parbox[b]{\textwidth}{\centering\@chead\strut}\hss
1350         \llap{\parbox[b]{\textwidth}{\raggedleft\@rhead\strut}}%
1351     }% hbox
1352     \if@headrule
1353       \hrule
1354     \else
1355       % an invisible hrule, to keep positioning constant:
1356       \hrule width 0pt
1357     \fi
1358   }% vbox
1359 }
1360
1361
1362 \newcommand*\run@fullhead{%
1363   \vbox to \headheight{%
1364     \vss
1365     \hbox to \textwidth{%
1366       \normalfont\rlap{\parbox[b]{\textwidth}{\raggedright\run@lhead\strut}}%
1367         \hss\parbox[b]{\textwidth}{\centering\run@chead\strut}\hss
1368         \llap{\parbox[b]{\textwidth}{\raggedleft\run@rhead\strut}}%
1369     }% hbox
1370     \ifrun@headrule
1371       \hrule
1372     \else
1373       % an invisible hrule, to keep positioning constant:
1374       \hrule width 0pt
1375     \fi
1376   }% vbox
1377 }
1378
1379
1380
1381 % We arrange it so that the very top of first line of text in the
1382 % foot is at a fixed position on the page, whether or not there's
1383 % a footrule:
1384
1385 \newcommand*\@fullfoot{%
1386   \vbox to 0pt{%
1387     \if@footrule
1388       \hrule
1389     \else
1390       % an invisible hrule, to keep positioning constant:
1391       \hrule width 0pt
1392     \fi
1393     \vskip 3pt
1394     \hbox to \textwidth{%
1395       \normalfont\rlap{\parbox[t]{\textwidth}{\raggedright\@lfoot}}%
1396         \hss\parbox[t]{\textwidth}{\centering\@cfoot}\hss
1397         \llap{\parbox[t]{\textwidth}{\raggedleft\@rfoot}}%
1398     }% hbox
1399     \vss
1400   }% vbox
1401 }
1402
1403
1404 \newcommand*\run@fullfoot{%
1405   \vbox to 0pt{%
1406     \ifrun@footrule
1407       \hrule
1408     \else
1409       % an invisible hrule, to keep positioning constant:
1410       \hrule width 0pt
1411     \fi
1412     \vskip 3pt
1413     \hbox to \textwidth{%
1414       \normalfont\rlap{\parbox[t]{\textwidth}{\raggedright\run@lfoot}}%
1415         \hss\parbox[t]{\textwidth}{\centering\run@cfoot}\hss
1416         \llap{\parbox[t]{\textwidth}{\raggedleft\run@rfoot}}%
1417     }% hbox
1418     \vss
1419   }% vbox
1420 }
1421
1422 %--------------------------------------------------------------------
1423 %       \cov@fullhead, \covrun@fullhead, \cov@fullfoot, and
1424 %       \covrun@fullfoot: 
1425
1426 \newcommand*\cov@fullhead{%
1427   \vbox to \headheight{%
1428     \vss
1429     \hbox to \textwidth{%
1430       \normalfont\rlap{\parbox[b]{\textwidth}{\raggedright\cov@lhead\strut}}%
1431         \hss\parbox[b]{\textwidth}{\centering\cov@chead\strut}\hss
1432         \llap{\parbox[b]{\textwidth}{\raggedleft\cov@rhead\strut}}%
1433     }% hbox
1434     \ifcov@headrule
1435       \hrule
1436     \else
1437       % an invisible hrule, to keep positioning constant:
1438       \hrule width 0pt
1439     \fi
1440   }% vbox
1441 }
1442
1443
1444 \newcommand*\covrun@fullhead{%
1445   \vbox to \headheight{%
1446     \vss
1447     \hbox to \textwidth{%
1448       \normalfont\rlap{\parbox[b]{\textwidth}{\raggedright\covrun@lhead\strut}}%
1449         \hss\parbox[b]{\textwidth}{\centering\covrun@chead\strut}\hss
1450         \llap{\parbox[b]{\textwidth}{\raggedleft\covrun@rhead\strut}}%
1451     }% hbox
1452     \ifcovrun@headrule
1453       \hrule
1454     \else
1455       % an invisible hrule, to keep positioning constant:
1456       \hrule width 0pt
1457     \fi
1458   }% vbox
1459 }
1460
1461
1462
1463 % We arrange it so that the very top of first line of text in the
1464 % foot is at a fixed position on the page, whether or not there's
1465 % a footrule:
1466
1467 \newcommand*\cov@fullfoot{%
1468   \vbox to 0pt{%
1469     \ifcov@footrule
1470       \hrule
1471     \else
1472       % an invisible hrule, to keep positioning constant:
1473       \hrule width 0pt
1474     \fi
1475     \vskip 3pt
1476     \hbox to \textwidth{%
1477       \normalfont\rlap{\parbox[t]{\textwidth}{\raggedright\cov@lfoot}}%
1478         \hss\parbox[t]{\textwidth}{\centering\cov@cfoot}\hss
1479         \llap{\parbox[t]{\textwidth}{\raggedleft\cov@rfoot}}%
1480     }% hbox
1481     \vss
1482   }% vbox
1483 }
1484
1485
1486 \newcommand*\covrun@fullfoot{%
1487   \vbox to 0pt{%
1488     \ifcovrun@footrule
1489       \hrule
1490     \else
1491       % an invisible hrule, to keep positioning constant:
1492       \hrule width 0pt
1493     \fi
1494     \vskip 3pt
1495     \hbox to \textwidth{%
1496       \normalfont\rlap{\parbox[t]{\textwidth}{\raggedright\covrun@lfoot}}%
1497         \hss\parbox[t]{\textwidth}{\centering\covrun@cfoot}\hss
1498         \llap{\parbox[t]{\textwidth}{\raggedleft\covrun@rfoot}}%
1499     }% hbox
1500     \vss
1501   }% vbox
1502 }
1503
1504
1505 %--------------------------------------------------------------------
1506 %--------------------------------------------------------------------
1507 %
1508 %            ********************************************
1509 %            ** COMMANDS TO DEFINE HEADERS AND FOOTERS **
1510 %            ********************************************
1511 %
1512 % \lhead[#1]{#2} sets the first page left head to #1, and the
1513 %   running left head to #2
1514
1515 % \lhead{#1} sets both the first page left head and the running
1516 %   left head to #1
1517
1518 % \chead, \rhead, \lfoot, \cfoot, and \rfoot work similarly.
1519
1520
1521 % \@lhead is the left head for Page 1
1522 % \run@lhead is the running left head
1523 % (i.e., for all pages other than the first)
1524
1525 % \@chead is the center head for Page 1
1526 % \run@chead is the running center head
1527 % (i.e., for all pages other than the first)
1528
1529 % etc.
1530
1531 % Alternative commands are:
1532 % \firstpageheader{LEFT}{CENTER}{RIGHT}
1533 % \runningheader{LEFT}{CENTER}{RIGHT}
1534 % or
1535 % \header{LEFT}{CENTER}{RIGHT}
1536 % which is equivalent to the two commands
1537 %          \firstpageheader{LEFT}{CENTER}{RIGHT}
1538 %          \runningheader{LEFT}{CENTER}{RIGHT}
1539
1540 % Alternative commands are:
1541 % \firstpagefooter{LEFT}{CENTER}{RIGHT}
1542 % \runningfoother{LEFT}{CENTER}{RIGHT}
1543 % or
1544 % \footer{LEFT}{CENTER}{RIGHT}
1545 % which is equivalent to the two commands
1546 %          \firstpagefooter{LEFT}{CENTER}{RIGHT}
1547 %          \runningfoother{LEFT}{CENTER}{RIGHT}
1548
1549 \def\firstpageheader#1#2#3{%
1550   \def\@lhead{#1}%
1551   \def\@chead{#2}%
1552   \def\@rhead{#3}%
1553 }
1554
1555 \def\runningheader#1#2#3{%
1556   \def\run@lhead{#1}%
1557   \def\run@chead{#2}%
1558   \def\run@rhead{#3}%
1559 }
1560
1561 \def\header#1#2#3{%
1562   \firstpageheader{#1}{#2}{#3}%
1563   \runningheader{#1}{#2}{#3}%
1564 }
1565
1566
1567 \def\firstpagefooter#1#2#3{%
1568   \def\@lfoot{#1}%
1569   \def\@cfoot{#2}%
1570   \def\@rfoot{#3}%
1571 }
1572
1573 \def\runningfooter#1#2#3{%
1574   \def\run@lfoot{#1}%
1575   \def\run@cfoot{#2}%
1576   \def\run@rfoot{#3}%
1577 }
1578
1579 \def\footer#1#2#3{%
1580   \firstpagefooter{#1}{#2}{#3}%
1581   \runningfooter{#1}{#2}{#3}%
1582 }
1583
1584
1585
1586 \def\lhead{\@ifnextchar[{\@xlhead}{\@ylhead}}
1587 \def\@xlhead[#1]#2{\def\@lhead{#1}\def\run@lhead{#2}}
1588 \def\@ylhead#1{\def\run@lhead{#1}\def\@lhead{#1}}
1589
1590 \def\chead{\@ifnextchar[{\@xchead}{\@ychead}}
1591 \def\@xchead[#1]#2{\def\@chead{#1}\def\run@chead{#2}}
1592 \def\@ychead#1{\def\run@chead{#1}\def\@chead{#1}}
1593
1594 \def\rhead{\@ifnextchar[{\@xrhead}{\@yrhead}}
1595 \def\@xrhead[#1]#2{\def\@rhead{#1}\def\run@rhead{#2}}
1596 \def\@yrhead#1{\def\run@rhead{#1}\def\@rhead{#1}}
1597
1598 \def\lfoot{\@ifnextchar[{\@xlfoot}{\@ylfoot}}
1599 \def\@xlfoot[#1]#2{\def\@lfoot{#1}\def\run@lfoot{#2}}
1600 \def\@ylfoot#1{\def\run@lfoot{#1}\def\@lfoot{#1}}
1601
1602 \def\cfoot{\@ifnextchar[{\@xcfoot}{\@ycfoot}}
1603 \def\@xcfoot[#1]#2{\def\@cfoot{#1}\def\run@cfoot{#2}}
1604 \def\@ycfoot#1{\def\run@cfoot{#1}\def\@cfoot{#1}}
1605
1606 \def\rfoot{\@ifnextchar[{\@xrfoot}{\@yrfoot}}
1607 \def\@xrfoot[#1]#2{\def\@rfoot{#1}\def\run@rfoot{#2}}
1608 \def\@yrfoot#1{\def\run@rfoot{#1}\def\@rfoot{#1}}
1609
1610
1611 %                    Initialize head and foot:
1612
1613
1614
1615 \pagestyle{headandfoot}
1616
1617 \lhead{}
1618 \chead{}
1619 \rhead{}
1620 \lfoot{}
1621 \cfoot[]{Page \thepage}
1622 \rfoot{}
1623
1624 %--------------------------------------------------------------------
1625 %                    Coverpage headers and footers
1626 %
1627 % \coverlhead[#1]{#2} sets the first cover page left head to #1, and the
1628 %   running cover left head to #2
1629
1630 % \coverlhead{#1} sets both the first cover page left head and the running
1631 %   cover left head to #1
1632
1633 % \coverchead, \coverrhead, \coverlfoot, \covercfoot, and \coverrfoot
1634 % work similarly.
1635
1636
1637 % \cov@lhead is the left head for Page 1
1638 % \covrun@lhead is the running left head
1639 % (i.e., for all pages other than the first)
1640
1641 % \cov@chead is the center head for Page 1
1642 % \covrun@chead is the running center head
1643 % (i.e., for all pages other than the first)
1644
1645 % etc.
1646
1647 % Alternative commands are:
1648 % \coverfirstpageheader{LEFT}{CENTER}{RIGHT}
1649 % \coverrunningheader{LEFT}{CENTER}{RIGHT}
1650 % or
1651 % \coverheader{LEFT}{CENTER}{RIGHT}
1652 % which is equivalent to the two commands
1653 %          \coverfirstpageheader{LEFT}{CENTER}{RIGHT}
1654 %          \coverrunningheader{LEFT}{CENTER}{RIGHT}
1655
1656 % Alternative commands are:
1657 % \coverfirstpagefooter{LEFT}{CENTER}{RIGHT}
1658 % \coverrunningfoother{LEFT}{CENTER}{RIGHT}
1659 % or
1660 % \coverfooter{LEFT}{CENTER}{RIGHT}
1661 % which is equivalent to the two commands
1662 %          \coverfirstpagefooter{LEFT}{CENTER}{RIGHT}
1663 %          \coverrunningfoother{LEFT}{CENTER}{RIGHT}
1664
1665 \def\coverfirstpageheader#1#2#3{%
1666   \def\cov@lhead{#1}%
1667   \def\cov@chead{#2}%
1668   \def\cov@rhead{#3}%
1669 }
1670
1671 \def\coverrunningheader#1#2#3{%
1672   \def\covrun@lhead{#1}%
1673   \def\covrun@chead{#2}%
1674   \def\covrun@rhead{#3}%
1675 }
1676
1677 \def\coverheader#1#2#3{%
1678   \coverfirstpageheader{#1}{#2}{#3}%
1679   \coverrunningheader{#1}{#2}{#3}%
1680 }
1681
1682
1683 \def\coverfirstpagefooter#1#2#3{%
1684   \def\cov@lfoot{#1}%
1685   \def\cov@cfoot{#2}%
1686   \def\cov@rfoot{#3}%
1687 }
1688
1689 \def\coverrunningfooter#1#2#3{%
1690   \def\covrun@lfoot{#1}%
1691   \def\covrun@cfoot{#2}%
1692   \def\covrun@rfoot{#3}%
1693 }
1694
1695 \def\coverfooter#1#2#3{%
1696   \coverfirstpagefooter{#1}{#2}{#3}%
1697   \coverrunningfooter{#1}{#2}{#3}%
1698 }
1699
1700
1701
1702 \def\coverlhead{\@ifnextchar[{\cov@xlhead}{\cov@ylhead}}
1703 \def\cov@xlhead[#1]#2{\def\cov@lhead{#1}\def\covrun@lhead{#2}}
1704 \def\cov@ylhead#1{\def\covrun@lhead{#1}\def\cov@lhead{#1}}
1705
1706 \def\coverchead{\@ifnextchar[{\cov@xchead}{\cov@ychead}}
1707 \def\cov@xchead[#1]#2{\def\cov@chead{#1}\def\covrun@chead{#2}}
1708 \def\cov@ychead#1{\def\covrun@chead{#1}\def\cov@chead{#1}}
1709
1710 \def\coverrhead{\@ifnextchar[{\cov@xrhead}{\cov@yrhead}}
1711 \def\cov@xrhead[#1]#2{\def\cov@rhead{#1}\def\covrun@rhead{#2}}
1712 \def\cov@yrhead#1{\def\covrun@rhead{#1}\def\cov@rhead{#1}}
1713
1714 \def\coverlfoot{\@ifnextchar[{\cov@xlfoot}{\cov@ylfoot}}
1715 \def\cov@xlfoot[#1]#2{\def\cov@lfoot{#1}\def\covrun@lfoot{#2}}
1716 \def\cov@ylfoot#1{\def\covrun@lfoot{#1}\def\cov@lfoot{#1}}
1717
1718 \def\covercfoot{\@ifnextchar[{\cov@xcfoot}{\cov@ycfoot}}
1719 \def\cov@xcfoot[#1]#2{\def\cov@cfoot{#1}\def\covrun@cfoot{#2}}
1720 \def\cov@ycfoot#1{\def\covrun@cfoot{#1}\def\cov@cfoot{#1}}
1721
1722 \def\coverrfoot{\@ifnextchar[{\cov@xrfoot}{\cov@yrfoot}}
1723 \def\cov@xrfoot[#1]#2{\def\cov@rfoot{#1}\def\covrun@rfoot{#2}}
1724 \def\cov@yrfoot#1{\def\covrun@rfoot{#1}\def\cov@rfoot{#1}}
1725
1726
1727 %                 Initialize coverpage head and foot:
1728
1729
1730 \coverlhead{}
1731 \coverchead{}
1732 \coverrhead{}
1733 \coverlfoot{}
1734 \covercfoot{}
1735 \coverrfoot{}
1736
1737
1738
1739
1740 %--------------------------------------------------------------------
1741 %--------------------------------------------------------------------
1742
1743 %                      Headrules and footrules:
1744
1745 \newif\if@headrule
1746 \newif\ifrun@headrule
1747
1748 \def\firstpageheadrule{\@headruletrue}
1749 \def\nofirstpageheadrule{\@headrulefalse}
1750
1751 \def\runningheadrule{\run@headruletrue}
1752 \def\norunningheadrule{\run@headrulefalse}
1753
1754 \def\headrule{\@headruletrue\run@headruletrue}
1755 \def\noheadrule{\@headrulefalse\run@headrulefalse}
1756
1757
1758
1759 \newif\if@footrule
1760 \newif\ifrun@footrule
1761
1762 \def\firstpagefootrule{\@footruletrue}
1763 \def\nofirstpagefootrule{\@footrulefalse}
1764
1765 \def\runningfootrule{\run@footruletrue}
1766 \def\norunningfootrule{\run@footrulefalse}
1767
1768 \def\footrule{\@footruletrue\run@footruletrue}
1769 \def\nofootrule{\@footrulefalse\run@footrulefalse}
1770
1771
1772
1773 %                             Initialize:
1774
1775 \noheadrule
1776 \nofootrule
1777
1778
1779 %                 Cover page headrules and footrules:
1780
1781 \newif\ifcov@headrule
1782 \newif\ifcovrun@headrule
1783
1784 \def\coverfirstpageheadrule{\cov@headruletrue}
1785 \def\nocoverfirstpageheadrule{\cov@headrulefalse}
1786
1787 \def\coverrunningheadrule{\covrun@headruletrue}
1788 \def\nocoverrunningheadrule{\covrun@headrulefalse}
1789
1790 \def\coverheadrule{\cov@headruletrue\covrun@headruletrue}
1791 \def\nocoverheadrule{\cov@headrulefalse\covrun@headrulefalse}
1792
1793
1794
1795 \newif\ifcov@footrule
1796 \newif\ifcovrun@footrule
1797
1798 \def\coverfirstpagefootrule{\cov@footruletrue}
1799 \def\nocoverfirstpagefootrule{\cov@footrulefalse}
1800
1801 \def\coverrunningfootrule{\covrun@footruletrue}
1802 \def\nocoverrunningfootrule{\covrun@footrulefalse}
1803
1804 \def\coverfootrule{\cov@footruletrue\covrun@footruletrue}
1805 \def\nocoverfootrule{\cov@footrulefalse\covrun@footrulefalse}
1806
1807
1808
1809 %                             Initialize:
1810
1811 \nocoverheadrule
1812 \nocoverfootrule
1813
1814
1815
1816 %--------------------------------------------------------------------
1817 %--------------------------------------------------------------------
1818
1819 %                \numpages, \iflastpage, and \oddeven
1820 %     Also: \numpoints, \numquestions, \numparts, and \numsubparts
1821 %                    Also also: \pointsofquestion
1822
1823 % Make the number of pages available as the macro \numpages,
1824 % the number of points as \numpoints,
1825 % the number of questions as \numquestions,
1826 % the number of parts as \numparts, and
1827 % the number of subparts as \numsubparts
1828 %\def\numpages{\pageref{@lastpage}}
1829 %\def\numpoints{\pageref{@numpoints}}
1830 %\def\numquestions{\pageref{@numquestions}}
1831 %\def\numparts{\pageref{@numparts}}
1832 %\def\numsubparts{\pageref{@numsubparts}}
1833 %\def\numsubsubparts{\pageref{@numsubsubparts}}
1834
1835 % This was previously done with \pageref commands.  When I eliminated
1836 % all \label, \ref, and \pageref commands in order to make this
1837 % compatible with hyperref.sty, this stuff was created:
1838
1839 % \gdef commands for exam@lastpage, exam@numpoints, exam@numquestions,
1840 % exam@numparts, exam@numsubparts and exam@numsubsubparts are written to
1841 % the .aux file via \AtEndDocument.
1842
1843 % \gdef commands for pointsofq@i, pointsofq@ii, etc. are written to the
1844 % .aux file as each question is completed (see the definition of the
1845 % questions environment).
1846
1847 % \gdef commands for pointsonpage@i, pointsonpage@ii, etc. are written
1848 % to the .aux file as we encounter points defined for a later page, and
1849 % for the last such page with AtEndDocument.
1850
1851 \def\numpages{\@ifundefined{exam@lastpage}%
1852   {\mbox{\normalfont\bf ??}}%
1853   \exam@lastpage
1854 }
1855
1856 \def\numpoints{\@ifundefined{exam@numpoints}%
1857   {\mbox{\normalfont\bf ??}}%
1858   \exam@numpoints
1859 }
1860
1861 \def\numquestions{\@ifundefined{exam@numquestions}%
1862   {\mbox{\normalfont\bf ??}}%
1863   \exam@numquestions
1864 }
1865
1866 \def\numparts{\@ifundefined{exam@numparts}%
1867   {\mbox{\normalfont\bf ??}}%
1868   \exam@numparts
1869 }
1870
1871 \def\numsubparts{\@ifundefined{exam@numsubparts}%
1872   {\mbox{\normalfont\bf ??}}%
1873   \exam@numsubparts
1874 }
1875
1876 \def\numsubsubparts{\@ifundefined{exam@numsubsubparts}%
1877   {\mbox{\normalfont\bf ??}}%
1878   \exam@numsubsubparts
1879 }
1880
1881 \def\pointsofquestion#1{\@ifundefined{pointsofq@\romannumeral #1}%
1882   {\mbox{\normalfont\bf ??}}%
1883   {\csname pointsofq@\romannumeral #1\endcsname}%
1884 }
1885
1886 \def\pointsonpage#1{\@ifundefined{pointsonpage@\romannumeral #1}%
1887   {\mbox{\normalfont\bf ??}}%
1888   {\csname pointsonpage@\romannumeral #1\endcsname}%
1889 }
1890
1891
1892 \newif\if@pointschanged
1893 \@pointschangedfalse
1894
1895
1896
1897 %%%\let\@realenddocument=\enddocument
1898 %%%\def\enddocument{\clearpage
1899 %%%   \if@filesw 
1900 %%%     {\advance\c@page-1 \immediate\write\@mainaux
1901 %%%       {\string\newlabel{@lastpage}{{}{\arabic{page}}}}%
1902 %%%     }
1903 %%%   \fi
1904 %%%   \@realenddocument
1905 %%%}
1906
1907
1908 \AtEndDocument{%
1909   \clearpage
1910   \if@filesw
1911     \advance\c@page-1
1912     \immediate\write\@mainaux
1913       {\string\gdef\string\exam@lastpage{\arabic{page}}}%
1914     \advance\c@page+1 % In case some other package looks at \c@page
1915     \immediate\write\@mainaux
1916         {\string\gdef\string\exam@numpoints{\prtaux@hlfcntr{numpoints}}}%
1917     % See if this has changed from the last run of LaTeX:
1918     \@ifundefined{exam@numpoints}%
1919       {\global\@pointschangedtrue}%
1920       {%
1921       % OK; it's defined.  See if it's changed:
1922       \begingroup
1923         \set@hlfcntr{tmp@hlfcntr}{\exam@numpoints}%
1924         \edef\othpt@check{\prtaux@hlfcntr{tmp@hlfcntr}}%
1925         \edef\pt@check{\prtaux@hlfcntr{numpoints}}%
1926         \ifx \pt@check \othpt@check
1927           % Do nothing
1928         \else
1929           \global\@pointschangedtrue
1930         \fi
1931       \endgroup
1932       }%
1933     \immediate\write\@mainaux
1934       {\string\gdef\string\exam@numquestions{\thenumquestions}}%
1935     \immediate\write\@mainaux
1936       {\string\gdef\string\exam@numparts{\thenumparts}}%
1937     \immediate\write\@mainaux
1938       {\string\gdef\string\exam@numsubparts{\thenumsubparts}}%
1939     \immediate\write\@mainaux
1940       {\string\gdef\string\exam@numsubsubparts{\thenumsubsubparts}}%
1941     \ifnum \thepageof@pagepoints > 0\relax
1942       \immediate\write\@mainaux
1943           {\string\gdef\string\pointsonpage@\romannumeral
1944                           \csname c@pageof@pagepoints\endcsname
1945              {\prtaux@hlfcntr{@pagepoints}}}%
1946       % See if this has changed from the last run of LaTeX:
1947       \@ifundefined{pointsonpage@\romannumeral
1948                           \csname c@pageof@pagepoints\endcsname}%
1949         {\global\@pointschangedtrue}%
1950         {%
1951         % OK; it's defined.  See if it's changed:
1952         \begingroup
1953           \set@hlfcntr{tmp@hlfcntr}{\csname pointsonpage@\romannumeral 
1954                     \csname c@pageof@pagepoints\endcsname\endcsname}%
1955           \edef\othpt@check{\prtaux@hlfcntr{tmp@hlfcntr}}%
1956           \edef\pt@check{\prtaux@hlfcntr{@pagepoints}}%
1957           \ifx \pt@check \othpt@check
1958             % Do nothing
1959           \else
1960             \global\@pointschangedtrue
1961           \fi
1962         \endgroup
1963         }%
1964     \fi
1965     \immediate\write\@mainaux
1966       {\string\gdef\string\lastpage@withpoints{\page@withpoints}}%
1967     % See if this has changed from the last run of LaTeX:
1968     \@ifundefined{lastpage@withpoints}%
1969       {\global\@pointschangedtrue}%
1970       {%
1971       % OK; it's defined.  See if it's changed:
1972       \begingroup
1973         \edef\othpt@check{\page@withpoints}%
1974         \edef\pt@check{\lastpage@withpoints}%
1975         \ifx \pt@check \othpt@check
1976           % Do nothing
1977         \else
1978           \global\@pointschangedtrue
1979         \fi
1980       \endgroup
1981       }%
1982   \fi
1983   % Echo numbers of questions, parts, and subparts:
1984   \typeout{This exam contains \thenumquestions\space questions
1985     with \thenumparts\space parts, \thenumsubparts\space subparts,
1986     and \thenumsubsubparts\space subsubparts.}
1987   % If counting points, echo total points:
1988   \if@printtotalpoints
1989     \begingroup
1990       \def\typ@expnd{%
1991         \thenumpoints
1992         \ifnumpoints@half
1993           \space and a half%
1994         \fi
1995       }
1996       \typeout{This exam has a total of \typ@expnd\space points.}
1997     \endgroup
1998   \fi
1999   \if@pointschanged
2000     \ClassWarningNoLine{exam}{Point totals have changed.
2001                Rerun to get point totals right}%
2002   \fi
2003 }
2004
2005
2006 % We define \iflastpage so that it can safely be used
2007 % in headers and footers:
2008 \def\iflastpage#1#2{%
2009   \@ifundefined{exam@lastpage}{\def\@@lastpage{-1}}%
2010           {\edef\@@lastpage{\exam@lastpage}}%
2011   \ifnum\value{page}=\@@lastpage
2012     #1%
2013   \else
2014     #2%
2015   \fi
2016 }
2017
2018
2019 % The macro \oddeven takes two arguments.  If the page number is odd,
2020 % then you get the first argument; otherwise, you get the second
2021 % argument.
2022 \def\oddeven#1#2{%
2023   \ifodd\value{page}%
2024     #1
2025   \else
2026     #2
2027   \fi
2028 }
2029
2030
2031
2032 %--------------------------------------------------------------------
2033 %--------------------------------------------------------------------
2034 %                 \ifcontinuation, \ContinuedQuestion,
2035 %                \ifincomplete, and \IncompleteQuestion
2036
2037 % The commands \ifcontinuation, \ContinuedQuestion, \ifincomplete, and
2038 % \IncompleteQuestion assume that there is only one questions
2039 % environment in the entire document.  (Actually, \ContinuedQuestion
2040 % should work even if there are multiple questions environments, but
2041 % none of the other three will work in general.)
2042
2043
2044
2045 % \PgInfo@write, \PgInfo and \PgInfo@get are our replacements
2046 % for \label, \newlabel, and \pageref.  (We're avoiding using
2047 % \label, \newlabel, and \pageref so that we will be compatible
2048 % with hyperref.sty, which redefines those commands.)
2049
2050 % We use \PgInfo, \PgInfo@write, and \PgInfo@get to know on which page
2051 % each question, part, subpart, and subsubpart appears.
2052
2053 % We use \PgInfo@write to write \PgInfo commands to the .aux file.  The
2054 % \PgInfo command takes two arguments: A question (or part, or subpart,
2055 % or subsubpart) label, and the number of the page on which it appears.
2056
2057 % The label for a question is of the form `question@2' (if it's question
2058 % 2).
2059
2060 % The label for a part is of the form `part@2@1' (if it's part a of
2061 % question 2).
2062
2063 % The label for a subpart is of the form `subpart@2@1@3' (if it's
2064 % subpart iii of part a of question 2).
2065
2066 % The label for a subsubpart is of the form `subsubpart@2@1@3@4' (if
2067 % it's subsubpart $\delta$ of subpart iii of part a of question 2).
2068
2069 % The \PgInfo command defines a control sequence of the form `Pg@label'
2070 % that expands to the page number for the corresponding question.  For
2071 % example, \PgInfo{subsubpart@2@1@3@4}{7} defines 
2072 %   \csname Pg@subsubpart@2@1@3@4\endcsname 
2073 % to expand to 7.
2074
2075 % The \PgInfo@get{label} command returns the value of the macro Pg@label,
2076 % but it *doesn't* check whether that macro is defined.  Thus, it's
2077 % important to check that the macro Pg@label is defined before giving the
2078 % command \PgInfo@get{label}.
2079
2080
2081
2082 % The token list to a \write command isn't expanded until
2083 % it's shipped out.  Since the argument to PgInfo@write
2084 % generally contains macros, we want to expand those macros
2085 % now, rather than waiting until this is shipped out, at which
2086 % point the macros may have different values.  Thus, we use
2087 % \edef to force expansion of the argument, and we put
2088 % a \noexpand in front of \thepage so that the \thepage
2089 % will not be expanded now.  (This may not get shipped out
2090 % until a later page, and so we want the \thepage to be expanded
2091 % only when it's shipped out.)
2092 % We use the \begingroup \endgroup pair so that our use
2093 % of \reserved@a won't affect its use anywhere else.
2094 \def\PgInfo@write#1{%
2095   \begingroup
2096     \edef\reserved@a{\write\@mainaux
2097       {\string\PgInfo{#1}{\noexpand\thepage}}}%
2098     \reserved@a
2099   \endgroup
2100 }
2101
2102 %\PgInfo commands are written to the .aux file by the \PgInfo@write
2103 %command; that's the only place that \PgInfo commands appear.
2104 \def\PgInfo#1#2{\expandafter\gdef\csname Pg@#1\endcsname{#2}}
2105
2106 % Note: PgInfo@get assumes that the control sequence being
2107 % constructed is already defined; you have to make sure of this
2108 % *before* calling \Pginfo@get
2109 \def\PgInfo@get#1{\csname Pg@#1\endcsname}
2110
2111 % \set@counter@to@pageof takes two arguments: The first is the name
2112 % of a counter, and the second (expands to) the label of a question,
2113 % part, subpart, or subsubpart.  If that label exists, then we set
2114 % the counter equal to the page on which the question (or part, etc.)
2115 % appears.  If that label doesn't exist, we set the counter equal
2116 % to -1.  (No labels exist on the first run of LaTeX on the file,
2117 % and if a new question (or part, etc.) was created by editing the
2118 % file, then the label will not exist until the second run of LaTeX
2119 % after that.
2120 \def\set@counter@to@pageof#1#2{%
2121   \@ifundefined{Pg@#2}%
2122   {\setcounter{#1}{-1}}%
2123   {\setcounter{#1}{\csname Pg@#2\endcsname}}%
2124 }
2125
2126
2127 %--------------------------------------------------------------------
2128
2129 % \ifcontinuation#1#2 expands to #2 if either: (1) The current page is
2130 % before the page containing question number 1, or (2) A question begins
2131 % on this page before any part, subpart, or subsubpart begins, or (3)
2132 % The current page is later than a page with the \nomorequestions
2133 % command.  Otherwise, it expands to #1.
2134
2135
2136 \def\ifcontinuation#1#2{%
2137   % We need to first check whether we're on a page *before* the page on
2138   % which the first question appears.  If we don't yet know which page
2139   % has question number 1, then we must be doing an early run of LaTeX,
2140   % and we'll assume we're not a continuation.
2141   \expandafter\ifx\csname Pg@question@1\endcsname\relax
2142     % No page info yet; assume not a continuation
2143     #2%
2144   \else
2145     % Note: The ``\relax'' at the end of the following \ifnum
2146     % serves an entirely different purpose from the one at the
2147     % end of the above \expandafter\ifx.  That one (above)
2148     % is one of the things being compared, whereas the
2149     % one we're about to use is just to clearly mark the
2150     % end of the second number being compared by the \ifnum
2151     % (since it's conceivable that the ``#2'' would begin
2152     % with a digit).
2153     \ifnum \thepage < \csname Pg@question@1\endcsname\relax
2154       % We're before the page with question 1:
2155       #2%
2156     \else
2157       % The current page begins a new question if Contin@\thepage
2158       % has been defined as a macro that expands to \relax
2159       % (Note that this is different from if Contin@\thepage
2160       % has never been defined at all, in which case it will
2161       % be let equal to \relax (temporarily) by the \csname command.)
2162       \expandafter\ifx\csname Contin@\thepage\endcsname\ref@relax
2163         #2%
2164       \else
2165         % See if we're after a \nomorequestions command:
2166         \@ifundefined{Pg@@endquestions}%
2167         {#1}%
2168         {\ifnum \thepage > \PgInfo@get{@endquestions}\relax
2169           % We're after a \nomorequestions:
2170           #2
2171          \else
2172            % We actually are incomplete:
2173            #1
2174          \fi
2175         }%
2176       \fi
2177     \fi 
2178   \fi
2179 }
2180
2181 \def\nomorequestions{
2182   \PgInfo@write{@endquestions}%
2183 }
2184
2185
2186
2187 %--------------------------------------------------------------------
2188 % \ContinuedQuestion is for use in headers and footers, where we can
2189 % assume that \thepage is the number of the page on which we'll
2190 % actually appear.
2191
2192 % \ContinuedQuestion expands to the number of the question that
2193 % continues onto this page, or to -1 if this page begins with a new
2194 % question.
2195
2196 % ACTUALLY: \ContinuedQuestion expands to a positive number if either
2197 % (1) this page doesn't contain the beginning of any question, part,
2198 % subpart, or subsubpart, or (2) this page has a part, subpart, or
2199 % subsubpart that appears before any question.  That means that if the
2200 % current page actually begins with space for a continuation of the
2201 % previous question (but doesn't begin any part, subpart, or subsubpart
2202 % of that question) and then has a question, then we'll be asserting
2203 % that this page begins with a new question, but the actual top of the
2204 % page will begin with some blank space that's intended for the previous
2205 % question.
2206
2207 % \ContinuedQuestion works by examining the value of the macro
2208 % Contin@\thepage.  If this page starts with a question (i.e., if no
2209 % question continues onto this page), then the macro Contin@\thepage
2210 % will be defined, and will expand to `\relax' (and so an \ifx between
2211 % \csname Contin@\thepage\endcsname and \ref@relax will be true).
2212
2213 % If Contin@\thepage is undefined, then when it is used in an \ifx
2214 % command it will be temporarily set equal to \relax (which is
2215 % *different* from being a macro that expands to \relax); in this case,
2216 % there is no question, part, subpart, or subsubpart that begins on this
2217 % page, and so \ContinuedQuestion will be set equal to the last question
2218 % that was begun on a page before this one.
2219
2220 % The last possibility is that this page begins with either a part,
2221 % subpart, or subsubpart.  In this case, Contin@\thepage is defined, and
2222 % it expands to the number of the question that is continues onto this
2223 % page.
2224
2225
2226 \def\ref@relax{\relax}
2227
2228 \def\ContinuedQuestion{%
2229   \expandafter\ifx\csname Contin@\thepage\endcsname\relax
2230     % We get here if there's no question, part, subpart, or
2231     % subsubpart on this page, and so Contin@\thepage has
2232     % never been defined at all.  In that case, this page
2233     % continues whichever question was last begun on or 
2234     % before this page.
2235     \find@latestques
2236     \thelatest@ques
2237   \else
2238     \expandafter\ifx\csname Contin@\thepage\endcsname\ref@relax
2239       % We get here if this page begins with a new question,
2240       % which is why Contin@\thepage has been defined to be
2241       % a macro that expands to \relax.
2242       % ACTUALLY: We get here if this page has a question that
2243       % appears before any part, subpart, or subsubpart.  That
2244       % means that if the current page actually begins with space
2245       % for a continuation of the previous question but doesn't begin
2246       % any part, subpart, or subsubpart of that question, then
2247       % we'll be asserting that this page begins with a new question,
2248       % but the actual top of the page will begin with some space
2249       % that's intended for the previous question.
2250       -1\relax
2251     \else
2252       % We get here if we didn't get anywhere above.  This happens
2253       % if Contin@\thepage has been defined to be a macro that expands
2254       % to something other than \relax, in which case it has been
2255       % defined to be a macro that expands to the number of the
2256       % question that continues onto this page.
2257       \csname Contin@\thepage\endcsname
2258     \fi
2259   \fi
2260 }
2261
2262 %--------------------------------------------------------------------
2263 % \find@latestques is for use in headers and footers, where we can
2264 % assume that \thepage actually equals the page on which we'll appear.
2265 % We find the last question that was started on or before the current
2266 % page.
2267
2268 \newcounter{latest@ques}
2269
2270 \newcommand\find@latestques{%
2271   % \find@latestques is for use in headers and footers.
2272   % \find@latestques will set the counter latest@ques
2273   % to the number of the last question
2274   % that was begun on the exam from page 1 through the current
2275   % page.  This may well be the value of the question counter,
2276   % but it may be less than that if the page following this one
2277   % begins a new question and that question beginning was
2278   % typeset before the present page was shipped out.
2279   % Note: This macro is called both by \ContinuedQuestion and by
2280   % \find@quesend, which is why it has to find the last question
2281   % begun on or before the current page, rather than just before
2282   % the current page.
2283   \ifnum 1 > \arabic{question}\relax
2284     % Oops; probably because we're before the first question
2285     % Just set latest@ques to -1:
2286     \setcounter{latest@ques}{-1}%
2287   \else
2288     % If question latest@ques actually begins on this page (rather
2289     % than on the next page, but early enough on the next page
2290     % that the counter was advanced before we ran off into the
2291     % output routine to output the page and set the header and 
2292     % footer), then that's the correct question number.
2293     \expandafter\ifx\csname Pg@question@\arabic{question}\endcsname\relax
2294       % We don't know what page that question is on;
2295       % this must be an early run, before the aux file
2296       % is helpful.  Just set it equal to -1 and wait until the next
2297       % run to get it right.
2298       \setcounter{latest@ques}{-1}%
2299     \else
2300       % We now know that \PgInfo@get can tell us the page number
2301       % of \arabic{question} and of all earlier questions.
2302       % Set latest@ques equal to the current question number, and
2303       % then call \decr@latest@ques to recursively decrement
2304       % latest@ques as needed to find a question that begins on
2305       % or before the current page:
2306       \setcounter{latest@ques}{\arabic{question}}%
2307       \decr@latest@ques
2308     \fi
2309   \fi
2310 }
2311
2312 \def\decr@latest@ques{%
2313   % If we get here, then we've already checked that the reference
2314   % Pg@question@\thelatest@ques is defined at least for a value of
2315   % \thelatest@ques greater than or equal to it's present value,
2316   % so we assume it's defined for all lesser values as well:
2317   \ifnum \thepage < \PgInfo@get{question@\thelatest@ques}\relax
2318     % Nope; latest@ques starts on a later page
2319     % Decrement latest@ques and see if that one's right:
2320     \addtocounter{latest@ques}{-1}%
2321     \ifnum \thelatest@ques < 1\relax
2322       \setcounter{latest@ques}{-1}%
2323       \let\next@dlq=\relax
2324     \else
2325       \let\next@dlq=\decr@latest@ques
2326     \fi
2327   \else
2328     % latest@ques starts on this page or earlier, so
2329     % that's the correct question number!  Exit:
2330     \let\next@dlq=\relax
2331   \fi
2332   \next@dlq
2333 }
2334          
2335
2336
2337 %--------------------------------------------------------------------
2338 %--------------------------------------------------------------------
2339 %--------------------------------------------------------------------
2340 \newcounter{ques@end}
2341 \def\find@quesend{%
2342   % We find the last question started on or before the current page
2343   % and then find the page containing the last part (or subpart, or
2344   % subsubpart) of that question, and set the counter ques@end to that
2345   % page number.
2346   % Set latest@ques equal to the correct question number:
2347   \find@latestques
2348   \ifnum \value{latest@ques} < 0\relax
2349     % This must be an early run of LaTeX, before we have
2350     % \PgInfo commands in the .aux file:
2351     \setcounter{ques@end}{-1}%
2352   \else
2353     % See if this question has any parts.  (It has one or more parts
2354     % if and only if it has a part number 1.)
2355     \@ifundefined{Pg@part@\thelatest@ques @1}%
2356       {%
2357         % Nope; no parts.
2358         \setcounter{ques@end}{\PgInfo@get{question@\thelatest@ques}}%
2359       }%
2360       {\find@part}%
2361   \fi
2362 }
2363
2364 \newcounter{last@part}
2365 \def\find@part{%
2366   % We now know that this question has at least one part.
2367   % We'll find its highest numbered part by setting last@part
2368   % equal to 2 and then calling \find@lastpart to recursively
2369   % test whether that part number exists and, if so, incrementing
2370   % last@part to test for a higher numbered one:
2371   \setcounter{last@part}{2}%
2372   \find@lastpart
2373   % Now: See if this part has any subparts.  (It has one or more
2374   % subparts if and only if it has a subpart numbered 1.)
2375   \@ifundefined{Pg@subpart@\thelatest@ques @\thelast@part @1}%
2376     {%
2377       % Nope; no subparts.
2378       \setcounter{ques@end}{\PgInfo@get{part@\thelatest@ques
2379                                           @\thelast@part}}%
2380     }%
2381     {\find@subpart}%
2382 }
2383
2384 \def\find@lastpart{%
2385   % We check whether this question has a part numbered last@part
2386   % and recursively increment last@part to find the highest
2387   % numbered value for which the part exists:
2388   \@ifundefined{Pg@part@\thelatest@ques @\thelast@part}%
2389     {\addtocounter{last@part}{-1}%
2390       \let\nextfind@lastpart=\relax
2391     }%
2392     {\addtocounter{last@part}{1}%
2393       \let\nextfind@lastpart=\find@lastpart
2394     }%
2395   \nextfind@lastpart
2396 }
2397
2398 \newcounter{last@subpart}
2399 \def\find@subpart{%
2400   % We now know that this part has at least one subpart.
2401   % We'll find its highest numbered subpart by setting last@subpart
2402   % equal to 2 and then calling \find@lastsubpart to recursively
2403   % test whether that subpart number exists and, if so, incrementing
2404   % last@subpart to test for a higher numbered one:
2405   \setcounter{last@subpart}{2}%
2406   \find@lastsubpart
2407   % Now: See if this subpart has any subsubparts.  (It has one or more
2408   % subsubparts if and only if it has a subsubpart numbered 1.)
2409   \@ifundefined{Pg@subsubpart@\thelatest@ques 
2410                          @\thelast@part @\thelast@subpart @1}%
2411     {%
2412       % Nope; no subsubparts
2413       \setcounter{ques@end}{\PgInfo@get{subpart@\thelatest@ques
2414                                   @\thelast@part @\thelast@subpart}}%
2415     }%
2416     {\find@subsubpart}%
2417 }
2418
2419 \def\find@lastsubpart{%
2420   % We check whether this part has a subpart numbered last@subpart
2421   % and recursively increment last@subpart to find the highest
2422   % numbered value for which the subpart exists:
2423   \@ifundefined{Pg@subpart@\thelatest@ques 
2424                          @\thelast@part @\thelast@subpart}%
2425     {\addtocounter{last@subpart}{-1}%
2426       \let\nextfind@lastsubpart=\relax
2427     }%
2428     {\addtocounter{last@subpart}{1}%
2429       \let\nextfind@lastsubpart=\find@lastsubpart
2430     }%
2431   \nextfind@lastsubpart
2432 }
2433
2434 \newcounter{last@subsubpart}
2435 \def\find@subsubpart{%
2436   % We now know that this subpart has at least one subsubpart.
2437   % We'll find its highest numbered subsubpart by setting last@subsubpart
2438   % equal to 2 and then calling \find@lastsubsubpart to recursively
2439   % test whether that subsubpart number exists and, if so, incrementing
2440   % last@subsubpart to test for a higher numbered one:
2441   \setcounter{last@subsubpart}{2}%
2442   \find@lastsubsubpart
2443   \setcounter{ques@end}{\PgInfo@get{subsubpart@\thelatest@ques
2444                @\thelast@part @\thelast@subpart @\thelast@subsubpart}}%
2445 }
2446
2447 \def\find@lastsubsubpart{%
2448   % We check whether this subpart has a subsubpart numbered last@subsubpart
2449   % and recursively increment last@subsubpart to find the highest
2450   % numbered value for which the subsubpart exists:
2451   \@ifundefined{Pg@subsubpart@\thelatest@ques 
2452               @\thelast@part @\thelast@subpart @\thelast@subsubpart}%
2453     {\addtocounter{last@subsubpart}{-1}%
2454       \let\nextfind@lastsubsubpart=\relax
2455     }%
2456     {\addtocounter{last@subsubpart}{1}%
2457       \let\nextfind@lastsubsubpart=\find@lastsubsubpart
2458     }%
2459   \nextfind@lastsubsubpart
2460 }
2461
2462
2463 %--------------------------------------------------------------------
2464 \newcounter{incmp@ques}
2465
2466 \def\IncompleteQuestion{%
2467   \Find@Incmp@ques
2468   \theincmp@ques
2469 }
2470
2471 \def\Find@Incmp@ques{%
2472   \iflastpage{\setcounter{incmp@ques}{-1}}{\chk@incomp}%
2473 }
2474 \newcounter{next@ques}
2475 \newcounter{nextq@page}
2476 \def\chk@incomp{%
2477   \find@quesend
2478   \ifnum \theques@end > \thepage\relax
2479     % This question has a part (or sub...) starting on a later page
2480     \setcounter{incmp@ques}{\value{latest@ques}}%
2481   \else
2482     \setcounter{next@ques}{\thelatest@ques}%
2483     \addtocounter{next@ques}{1}%
2484     \expandafter\ifx\csname Pg@question@\thenext@ques \endcsname\relax
2485       % This isn't the last page but there is no next question:
2486       \setcounter{incmp@ques}{\thelatest@ques}%
2487     \else
2488       % This isn't the last page and there is a next question:
2489       \setcounter{nextq@page}{\PgInfo@get{question@\thenext@ques}}%
2490       \addtocounter{nextq@page}{-1}%
2491       \ifnum \thenextq@page > \thepage\relax
2492         \setcounter{incmp@ques}{\thelatest@ques}%
2493       \else
2494         \setcounter{incmp@ques}{-1}%
2495       \fi
2496     \fi
2497   \fi
2498 }
2499
2500
2501 \def\ifincomplete#1#2{%
2502   \def\incomp@first{#1}%
2503   \def\incomp@second{#2}%
2504   \Find@Incmp@ques
2505   \ifnum \theincmp@ques < 0\relax
2506     \incomp@second
2507   \else
2508         \@ifundefined{Pg@@endquestions}%
2509         {\incomp@first}%
2510         {\ifnum \thepage < \PgInfo@get{@endquestions}%
2511            \incomp@first
2512          \else
2513            \incomp@second
2514          \fi
2515         }%
2516   \fi
2517 }
2518
2519
2520
2521
2522 %---------------------------------------------------------------------
2523 %
2524 %                    ***************************
2525 %                    ** QUESTION ENVIRONMENTS **
2526 %                    ***************************
2527 %
2528 %
2529 %
2530
2531 % We define the command \part only inside of a parts environment, so
2532 % that we don't interfere with the meaning of the standard article
2533 % documentclass command \part if that is used inside of a questions
2534 % environment.  The commands \question, \subpart, and \subsubpart are
2535 % defined everywhere inside of a questions environment.  If the user
2536 % accidentally gives a \subpart command outside of a subparts
2537 % environment, then an error will be created.
2538
2539
2540 %--------------------------------------------------------------------
2541 % These are the commands for dealing with hlfcntr's, i.e., the things
2542 % used to count points.
2543 %
2544 % A point value is a nonnegative integer with an optional half integer.
2545 % A hlfcntr consists of a regular counter together with an \if: If the
2546 % regular counter is called ``counter'', then the \if is called
2547 % ``\ifcounter@half''; it's set true by ``\counter@halftrue'' and set
2548 % false by ``\counter@halffalse''.
2549 %
2550 % The commands:
2551 %
2552 % \set@hlfcntr{countername}{value}
2553 % \copy@hlfcntr{tocounter}{fromcounter}
2554 % \addto@hlfcntr{countername}{value}
2555 % \add@hlfcntrtohlfcntr
2556 % \ifhlfcntr@pos{countername}
2557 % \prtaux@hlfcntr{countername}
2558 %
2559 % ``value'' can be either a (nonnegative) integer, an integer followed by
2560 % ``\half'', or just plain ``\half''.  (Actually, ``value'' can be empty
2561 % (although the braces must be present), in which case it's interpreted
2562 % as ``0''.)
2563 %
2564 % Examples of valid values:
2565 %   0
2566 %   0\half
2567 %   1
2568 %   1\half
2569 %   2
2570 %   2\half
2571 % etc.
2572
2573 % Note on using ``\global'': LaTeX's \setcounter and \addtocounter
2574 % commands are already \global (i.e., you don't have to say
2575 % ``\global''), but \somethingtrue and \somethingfalse (used to set
2576 % \ifsomething) aren't.  Thus, we need to say ``\global'' when setting
2577 % these things.
2578
2579 % A scratch hlfcntr:
2580 \newcounter{tmp@hlfcntr}
2581 \newif\iftmp@hlfcntr@half
2582
2583 \newcommand*\horiz@half{$\frac{1}{2}$}
2584 \newcommand*\slanted@half{%
2585   $\raise0.6ex\hbox{$\scriptstyle 1$}\kern -.2em/\kern -.2em
2586      \raise-0.5ex\hbox{$\scriptstyle 2$}$%
2587 }
2588 \newcommand*\useslantedhalf{\let\half\slanted@half}
2589 \newcommand*\usehorizontalhalf{\let\half\horiz@half}
2590 \newcommand*\half{\slanted@half}
2591
2592
2593 \newcommand*\set@hlfcntr[2]{%
2594   \begingroup
2595     \expandafter\global\csname #1@halffalse\endcsname
2596     % If there as a `\half' present, it will be executed
2597     % right after the assignment of the digit part of #2
2598     % to the counter #1.
2599     \def\half{%
2600       \expandafter\global\csname #1@halftrue\endcsname
2601     }%
2602     % We insert a `0' in case there are no digits present:
2603     \setcounter{#1}{0#2}\relax
2604   \endgroup
2605 }
2606
2607 \newcommand*\copy@hlfcntr[2]{%
2608   % We set #1 to the value of #2
2609   \setcounter{#1}{\value{#2}}%
2610   \csname if#2@half\endcsname
2611     \expandafter\global\csname #1@halftrue\endcsname
2612   \else
2613     \expandafter\global\csname #1@halffalse\endcsname
2614   \fi
2615 }
2616
2617 \newcommand*\addto@hlfcntr[2]{%
2618   % We add the valueandhalf #2 to hlfcntr #1
2619   \begingroup
2620     \def\half{\add@half{#1}}%
2621     % We insert a `0' in case there are no digits present:
2622     \addtocounter{#1}{0#2}\relax
2623   \endgroup
2624 }
2625
2626 \newcommand*\add@hlfcntrtohlfcntr[2]{%
2627   % We add the hlfcntr #2 to the hlfcntr #1
2628   \addtocounter{#1}{\value{#2}}%
2629   \csname if#2@half\endcsname
2630     \add@half{#1}%
2631   \fi
2632 }
2633
2634 \newcommand*\add@half[1]{%
2635   % We add one half to hlfcntr #1:
2636   \csname if#1@half\endcsname
2637     \addtocounter{#1}{1}%
2638     \expandafter\global\csname #1@halffalse\endcsname
2639   \else
2640     \expandafter\global\csname #1@halftrue\endcsname
2641   \fi
2642 }
2643
2644 \newcounter{ifpos@cntr}
2645 \def\ifhlfcntr@pos#1{%
2646   % The argument must be a hlfcntr (which, of course,
2647   % can never be negative); we'll be true if and only if
2648   % that halfcntr is positive:
2649   \setcounter{ifpos@cntr}{\value{#1}}%
2650   \csname if#1@half\endcsname
2651     \addtocounter{ifpos@cntr}{1}%
2652   \fi
2653   \ifnum \value{ifpos@cntr} > 0
2654 }
2655
2656 % \prtaux@hlfcntr is used inside the argument of a \write command for
2657 % writing to the .aux file:
2658 \newcommand*\prtaux@hlfcntr[1]{%
2659   % We don't want a \relax after the 0 in the following
2660   % line, because it would sometimes appear in the aux file:
2661   \ifnum \value{#1} = 0 
2662     % We have to make the following a macro, because if we
2663     % don't do this part, the \fi will cause confusion, since
2664     % there's no \if visible until the \csname is expanded:
2665     \prtaux@halforzero{#1}%
2666   \else
2667     \arabic{#1}%
2668     % We have to make the following a macro, because if we
2669     % don't do this part, the \fi will cause confusion, since
2670     % there's no \if visible until the \csname is expanded:
2671     \prtaux@halforblank{#1}%
2672   \fi
2673 }
2674 \newcommand*\prtaux@halforzero[1]{%
2675   \csname if#1@half\endcsname
2676     \string\half
2677   \else
2678     0%
2679   \fi
2680 }
2681 \newcommand*\prtaux@halforblank[1]{%
2682   \csname if#1@half\endcsname
2683     \string\half
2684   \fi
2685 }
2686 %--------------------------------------------------------------------
2687
2688
2689
2690
2691 % We use the counter name `partno' for the parts environment so that
2692 % we will not interfere with the counter `part' used by the article
2693 % document class.
2694
2695 \newcounter{question}
2696 \newcounter{partno}
2697 \newcounter{subpart}
2698 \newcounter{subsubpart}
2699 \newcounter{choice}
2700 \newcounter{numpoints}
2701 \newif\ifnumpoints@half
2702 \set@hlfcntr{numpoints}{0}
2703 \newcounter{pointsof@thisquestion}
2704 \newif\ifpointsof@thisquestion@half
2705 \set@hlfcntr{pointsof@thisquestion}{0}
2706 \newcounter{numquestions}
2707 \newcounter{numparts}
2708 \newcounter{numsubparts}
2709 \newcounter{numsubsubparts}
2710 \newcounter{Curr@Page}
2711
2712 % @pagepoints accumulates the points on a single page:
2713 \newcounter{@pagepoints}
2714 \newif\if@pagepoints@half
2715 %\setcounter{@pagepoints}{0}
2716 \set@hlfcntr{@pagepoints}{0}
2717 \newcounter{pageof@pagepoints}
2718 \setcounter{pageof@pagepoints}{0}
2719
2720 % latest@points is a holding area for points until we know
2721 % whether they'll land on the same page as the points
2722 % currently counted in @pagepoints:
2723 \newcounter{latest@points}
2724 \newif\iflatest@points@half
2725 \set@hlfcntr{latest@points}{0}
2726
2727 % Whenever we meet a new page on which points are defined, we'll
2728 % redefine \page@withpoints to expand to that page.  At the end of the
2729 % document, it will hold the last page that has points, and we'll write
2730 % a \gdef\lastpage@withpoints command to the .aux file.
2731 % We initialize \page@withpoints here:
2732 \def\page@withpoints{0}%
2733
2734 % \pageinfo@commands is used by each question, part, subpart, and
2735 % subsubpart to insert into everypar the \PgInfo@write command to put
2736 % its page number inot the .aux file, the \PgInfo@get command to read
2737 % the page number into the counter Curr@Page, and to test and set
2738 % \Contin@\theCurr@Page.  \temp@toks is used by part, subpart, and
2739 % subsubpart to append all that to \pageinfo@commands, rather than
2740 % deleting whatever may have been put into \pageinfo@commands by the
2741 % current question and/or part and/or subpart.
2742 \newtoks\pageinfo@commands
2743 \newtoks\temp@toks
2744
2745 % \pagepoint@commands holds the commands to manage the counting of the
2746 % number of points defined on each page.
2747 \newtoks\pagepoint@commands
2748
2749 % \point@toks holds the commands to print the points at the proper
2750 % location on the page (except that it's not used by the \qformat
2751 % option).
2752 \newtoks\point@toks
2753
2754 % We'll use \greeknum to number subsubparts
2755 \def\greeknum#1{\expandafter\lc@greek\csname c@#1\endcsname}
2756 \def\lc@greek#1{%
2757   \ifcase #1\or $\alpha$\or $\beta$\or $\gamma$\or $\delta$\or
2758   $\epsilon$\or $\zeta$\or $\eta$\or $\theta$\or $\iota$\or
2759   $\kappa$\or $\lambda$\or $\mu$\or $\nu$\or $\xi$\or o\or $\pi$\or
2760   $\rho$\or $\sigma$\or $\tau$\or $\upsilon$\or $\phi$\or $\chi$\or
2761   $\psi$\or $\omega$\else \@ctrerr
2762   \fi
2763 }%
2764
2765
2766 % The following macros are a variation on a trick from Victor
2767 % Eijkhout's ``TeX by Topic'', page 142:
2768 % Both \prepend@toklist and \append@toklist take two arguments,
2769 % both of which should be token lists.
2770 % \prepend@toklist prepends #2 to #1
2771 % \append@toklist appends #2 to #1
2772
2773 \def\prepend@toklist#1#2{%
2774   \edef\do@it{\noexpand#1={\the#2\the#1}}%
2775   \do@it
2776 }%
2777
2778 \def\append@toklist#1#2{%
2779   \edef\do@it{\noexpand#1={\the#1\the#2}}%
2780   \do@it
2781 }%
2782
2783
2784 % The command \qformat is provided for the user who wants to
2785 % design a nonstandard question line.  If this command is used,
2786 % then the usual line containing the question numbers will be
2787 % replaced by the line specified by the \qformat command.
2788 % Within the argument of the \qformat command:
2789 % \thequestion will be replaced by the question number, and
2790 % \thepoints will be replaced by ``\@points \@pointname'' if the
2791 % number of points has been specified for this question, and otherwise
2792 % it inserts nothing at all.  (The conditional @placepoints is used to
2793 % determine if the number of points is nonzero.)
2794 % The argument to the \qformat command *must* contain some
2795 % stretch, i.e., at least one \hfil or \dotfill or ...
2796 \newif\if@qformat
2797 \@qformatfalse
2798
2799 \def\qformat#1{%
2800   \global\@qformattrue
2801   \gdef\@questionformat{#1}%
2802 }
2803
2804 \newcommand\noqformat{%
2805   \global\@qformatfalse
2806 }
2807
2808 \newcommand\thepoints{%
2809   \if@placepoints
2810     \@points \@pointname
2811   \fi
2812 }
2813
2814 % We define the \subpart and \subsubpart commands when we enter a
2815 % questions environment (rather than waiting until we enter a subparts
2816 % of subsubparts environment) so that we can signal an error if a
2817 % \subpart or \subsubpart command appears outside of the corresponding
2818 % environment.  (We don't do this for the \part command so that the user
2819 % can use the standard sectioning \part command outside of a parts
2820 % environment.)
2821
2822 \newenvironment{questions}{%
2823   % \@queslevel is used for two purposes:
2824   % (1) We check that every \question, \part, \subpart, and 
2825   % \subsubpart command appears inside the appropriate environment,
2826   % and generate an error if one appears in the wrong place.
2827   % (2) If a \qformat is being used and if \@queslevel tells us
2828   % that we're currently processing a question, then we set
2829   % \global \point@toks={} to avoid setting the points for a 
2830   % question other than via the qformat command.
2831   \def\@queslevel{question}%
2832   \def\question{%
2833     \if@coverpages
2834       \cover@question@error
2835     \fi
2836     \@checkqueslevel{question}%
2837     \addtocounter{numquestions}{1}%
2838     % Write the sum of points of the previous question (if any)
2839     % to the .aux file.  (At this point, the question counter
2840     % has not yet been incremented, so \arabic{question} has the
2841     % number of the question that was just completed.)
2842     \if@filesw
2843       \ifnum \arabic{question} > 0\relax
2844         \immediate\write\@mainaux
2845           {\string\gdef\string\pointsofq@
2846             \romannumeral \csname c@question\endcsname
2847               {\prtaux@hlfcntr{pointsof@thisquestion}}}%
2848         % See if this has changed from the last run of LaTeX:
2849         \@ifundefined{pointsofq@\romannumeral
2850                             \csname c@question\endcsname}%
2851           {\global\@pointschangedtrue}%
2852           {%
2853           % OK; it's defined.  See if it's changed:
2854           \begingroup
2855             \set@hlfcntr{tmp@hlfcntr}{\csname pointsofq@\romannumeral 
2856                          \csname c@question\endcsname\endcsname}%
2857             \edef\othpt@check{\prtaux@hlfcntr{tmp@hlfcntr}}%
2858             \edef\pt@check{\prtaux@hlfcntr{pointsof@thisquestion}}%
2859             \ifx \pt@check \othpt@check
2860               % Do nothing
2861             \else
2862               \global\@pointschangedtrue
2863             \fi
2864           \endgroup
2865           }%
2866       \fi
2867     \fi
2868     \set@hlfcntr{pointsof@thisquestion}{0}%
2869     % If there was a question with points immediately preceding
2870     % this question (i.e., there were no parts in the previous
2871     % question), then @placepoints will still be true, and we need to
2872     % cancel it.  (We used to do this inside of the \thepoints macro,
2873     % but that allowed for an error if the user specified points for a
2874     % question but had a \qformat that didn't mention \thepoints.)  We
2875     % also set @placepoints to be false in the \part command.
2876     \global \@placepointsfalse
2877     % point@toks will normally be empty at this point, but it might be
2878     % nonempty if there were points somewhere in the previous question
2879     % that never made it onto the page because we never entered
2880     % horizontal mode (perhaps because the user was weird and let the
2881     % text of a question (or part, etc.) consist entirely of an
2882     % enumerate environment, or description environment, or etc.).
2883     \global \point@toks={}%
2884     % Important: Don't leave any blank lines inside of
2885     % \pageinfo@commands!!  This token list will be dumped into
2886     % horizontal mode by \everypar, and so any blank lines will
2887     % cause paragraph breaks. 
2888     \pageinfo@commands={%
2889       \edef\@queslabel{question@\arabic{question}}%
2890       \PgInfo@write{\@queslabel}%
2891       \set@counter@to@pageof{Curr@Page}{\@queslabel}%
2892       \expandafter\ifx\csname Contin@\theCurr@Page\endcsname\relax
2893         % We're the first \question, \part, \subpart, or \subsubpart
2894         % on this page:
2895         \global\expandafter\edef
2896                \csname Contin@\theCurr@Page\endcsname{\relax}%
2897       \fi
2898       \the\pagepoint@commands
2899       \global \pageinfo@commands={}%
2900     }% pageinfo@commands
2901     \ifhmode
2902       % Remove any skips at the end of the previous paragraph
2903       % that might cause a blank line, and then end that paragraph:
2904       \unskip\unskip \par
2905     \fi
2906     \@doitem
2907   }% question
2908   \def\subpart{%
2909     \if@coverpages
2910       \cover@question@error
2911     \fi
2912     \@checkqueslevel{subpart}%
2913     \addtocounter{numsubparts}{1}%
2914     % Important: Don't leave any blank lines inside of
2915     % \pageinfo@commands!!  This token list will be dumped into
2916     % horizontal mode by \everypar, and so any blank lines will
2917     % cause paragraph breaks. 
2918     \temp@toks={%
2919       \edef\@subpartlabel{subpart@\arabic{question}%
2920         @\arabic{partno}@\arabic{subpart}}%
2921       \PgInfo@write{\@subpartlabel}%
2922       \set@counter@to@pageof{Curr@Page}{\@subpartlabel}%
2923       \expandafter\ifx\csname Contin@\theCurr@Page\endcsname\relax
2924         % We're the first \question, \part, \subpart, or \subsubpart
2925         % on this page:
2926         \global\expandafter\edef\csname
2927                        Contin@\theCurr@Page\endcsname{\arabic{question}}%
2928       \fi
2929       \the\pagepoint@commands
2930       \global \pageinfo@commands={}%
2931     }% temp@toks
2932     \append@toklist \pageinfo@commands \temp@toks
2933     \ifhmode
2934       % Remove any skips at the end of the previous paragraph
2935       % that might cause a blank line, and then end that paragraph:
2936       \unskip\unskip \par
2937     \fi
2938     \@doitem
2939   }% subpart
2940   \def\subsubpart{%
2941     \if@coverpages
2942       \cover@question@error
2943     \fi
2944     \@checkqueslevel{subsubpart}%
2945     \addtocounter{numsubsubparts}{1}%
2946     % Important: Don't leave any blank lines inside of
2947     % \pageinfo@commands!!  This token list will be dumped into
2948     % horizontal mode by \everypar, and so any blank lines will
2949     % cause paragraph breaks. 
2950     \temp@toks={%
2951       \edef\@subsubpartlabel{subsubpart@\arabic{question}%
2952         @\arabic{partno}@\arabic{subpart}@\arabic{subsubpart}}%
2953       \PgInfo@write{\@subsubpartlabel}%
2954       \set@counter@to@pageof{Curr@Page}{\@subsubpartlabel}%
2955       \expandafter\ifx\csname Contin@\theCurr@Page\endcsname\relax
2956         % We're the first \question, \part, \subpart, or \subsubpart
2957         % on this page:
2958         \global\expandafter\edef\csname
2959                        Contin@\theCurr@Page\endcsname{\arabic{question}}%
2960       \fi
2961       \the\pagepoint@commands
2962       \global \pageinfo@commands={}%
2963     }% temp@toks
2964     \append@toklist \pageinfo@commands \temp@toks
2965     \ifhmode
2966       % Remove any skips at the end of the previous paragraph
2967       % that might cause a blank line, and then end that paragraph:
2968       \unskip\unskip \par
2969     \fi
2970     \@doitem
2971   }% subsubpart
2972   \list{\question@number}%
2973     {\usecounter{question}%
2974     % We use the default definition of \makelabel
2975     % so as not to interfere with \qformat commands.
2976     % \def\makelabel##1{\hss\llap{##1}}%
2977     \settowidth{\leftmargin}{10.\hskip\labelsep}%
2978     \labelwidth\leftmargin\advance\labelwidth-\labelsep
2979     \partopsep=0pt
2980     }%
2981   }%
2982   {%
2983     \endlist
2984     % Write the number of points of the final question
2985     % to the .aux file:
2986     \if@filesw
2987       \ifnum \arabic{question} > 0\relax
2988         \immediate\write\@mainaux
2989           {\string\gdef\string\pointsofq@\romannumeral
2990                                 \csname c@question\endcsname
2991             {\prtaux@hlfcntr{pointsof@thisquestion}}}%
2992         % See if this has changed from the last run of LaTeX:
2993         \@ifundefined{pointsofq@\romannumeral
2994                             \csname c@question\endcsname}%
2995           {\global\@pointschangedtrue}%
2996           {%
2997           % OK; it's defined.  See if it's changed:
2998           \begingroup
2999             \set@hlfcntr{tmp@hlfcntr}{\csname pointsofq@\romannumeral 
3000                          \csname c@question\endcsname\endcsname}%
3001             \edef\othpt@check{\prtaux@hlfcntr{tmp@hlfcntr}}%
3002             \edef\pt@check{\prtaux@hlfcntr{pointsof@thisquestion}}%
3003             \ifx \pt@check \othpt@check
3004               % Do nothing
3005             \else
3006               \global\@pointschangedtrue
3007             \fi
3008           \endgroup
3009           }%
3010       \fi
3011     \fi
3012   }
3013   
3014 % \question@number is used as the label in the question list (instead
3015 % of \questionlabel) so that if the user uses a \qformat command,
3016 % we'll use the \@questionformat specified by the \qformat command:
3017 \def\question@number{%
3018   \if@qformat
3019     \makebox[\hsize][s]{\@questionformat}\hskip-\labelsep
3020   \else
3021     \questionlabel
3022   \fi
3023 }
3024 \newcommand\questionlabel{\thequestion.}
3025      
3026 % We want the \part command to be defined *only* inside of a parts
3027 % environment, so that the user can use the standard sectioning \part
3028 % command inside of a questions environment (as long as it's outside of
3029 % a parts environment).
3030
3031 \newenvironment{parts}{%
3032   \def\@queslevel{part}%
3033   % If the question numbers are being inserted via a \qformat,
3034   % and if a question is beginning with a parts environmnt, then
3035   % we need to enter horizonal mode to the the qformat printed
3036   % on the page, rather than saving up the question label (and
3037   % possible points) to be combined with the label of the first
3038   % part.  (\if@inlabel tells us if we are still waiting to enter
3039   % horizontal mode after seeing a \question command.)
3040   \if@qformat
3041     \if@inlabel
3042       \leavevmode
3043       \@inlabelfalse
3044     \fi
3045     % The following is just in case the question had points,
3046     % in which case @placepoints will still be true.
3047     % (We used to do this inside of the \thepoints macro,
3048     % but that allowed for an error if the user specified points for
3049     % a question but had a \qformat that didn't mention \thepoints.)
3050     % We also set @placepoints to be false in the \question command,
3051     % in case one queation follows a previous one that had no parts.
3052     \global \@placepointsfalse
3053   \fi
3054   \def\part{%
3055     \if@coverpages
3056       \cover@question@error
3057     \fi
3058     \@checkqueslevel{part}%
3059     \addtocounter{numparts}{1}%
3060     % Important: Don't leave any blank lines inside of
3061     % \pageinfo@commands!!  This token list will be dumped into
3062     % horizontal mode by \everypar, and so any blank lines will
3063     % cause paragraph breaks. 
3064     \temp@toks={%
3065       \edef\@partlabel{part@\arabic{question}@\arabic{partno}}%
3066       \PgInfo@write{\@partlabel}%
3067       \set@counter@to@pageof{Curr@Page}{\@partlabel}%
3068       \expandafter\ifx\csname Contin@\theCurr@Page\endcsname\relax
3069         \global\expandafter\edef\csname
3070             Contin@\theCurr@Page\endcsname{\arabic{question}}%
3071       \fi
3072       \the\pagepoint@commands
3073       \global \pageinfo@commands={}%
3074     }%
3075     \append@toklist \pageinfo@commands \temp@toks
3076     \ifhmode
3077       % Remove any skips at the end of the previous paragraph
3078       % that might cause a blank line, and then end that paragraph:
3079       \unskip\unskip \par
3080     \fi
3081     \@doitem
3082   }% part
3083   \list{\partlabel}%
3084     {%
3085     \usecounter{partno}\def\makelabel##1{\hss\llap{##1}}%
3086     \settowidth{\leftmargin}{(m)\hskip\labelsep}%
3087     \labelwidth\leftmargin\advance\labelwidth-\labelsep
3088     \topsep=0pt
3089     \partopsep=0pt
3090     }%
3091   }% newenvironment{parts}
3092   {\endlist}
3093 \newcommand\partlabel{(\thepartno)}
3094 \def\thepartno{\alph{partno}}
3095
3096 \newenvironment{subparts}{%
3097   \def\@queslevel{subpart}%
3098   \list{\subpartlabel}%
3099     {%
3100     \usecounter{subpart}\def\makelabel##1{\hss\llap{##1}}%
3101     \settowidth{\leftmargin}{vii.\hskip\labelsep}%
3102     \labelwidth\leftmargin\advance\labelwidth-\labelsep
3103     \topsep=0pt
3104     \partopsep=0pt
3105     }%
3106   }%
3107   {\endlist}
3108 \newcommand\subpartlabel{\thesubpart.}
3109 \def\thesubpart{\roman{subpart}}
3110
3111 \newenvironment{subsubparts}{%
3112   \def\@queslevel{subsubpart}%
3113   \list{\subsubpartlabel}%
3114     {%
3115     \usecounter{subsubpart}\def\makelabel##1{\hss\llap{##1}}%
3116     \settowidth{\leftmargin}{($\psi$)\hskip\labelsep}%
3117     \labelwidth\leftmargin\advance\labelwidth-\labelsep
3118     \topsep=0pt
3119     \partopsep=0pt
3120     }%
3121   }%
3122   {\endlist}
3123 \newcommand\subsubpartlabel{\thesubsubpart)}
3124 \def\thesubsubpart{\greeknum{subsubpart}}
3125
3126
3127 \pagepoint@commands={%
3128   \ifhlfcntr@pos{latest@points}%
3129     % We're putting a question (or part, etc.)
3130     % with points onto this page: 
3131     \ifnum \theCurr@Page > \thepageof@pagepoints\relax
3132       % These points go on a later page than
3133       % the points currently counted in @pagepoints:
3134       \ifnum \thepageof@pagepoints = 0\relax
3135         % Do nothing...
3136       \else
3137         \immediate\write\@mainaux
3138           {\string\gdef\string\pointsonpage@
3139            \romannumeral \csname c@pageof@pagepoints\endcsname
3140              {\prtaux@hlfcntr{@pagepoints}}}%
3141         % See if this has changed from the last run of LaTeX:
3142         \@ifundefined{pointsonpage@\romannumeral
3143                             \csname c@pageof@pagepoints\endcsname}%
3144           {\global\@pointschangedtrue}%
3145           {%
3146           % OK; it's defined.  See if it's changed:
3147           \begingroup
3148             \set@hlfcntr{tmp@hlfcntr}{\csname pointsonpage@\romannumeral 
3149                       \csname c@pageof@pagepoints\endcsname\endcsname}%
3150             \edef\othpt@check{\prtaux@hlfcntr{tmp@hlfcntr}}%
3151             \edef\pt@check{\prtaux@hlfcntr{@pagepoints}}%
3152             \ifx \pt@check \othpt@check
3153               % Do nothing
3154             \else
3155               \global\@pointschangedtrue
3156             \fi
3157           \endgroup
3158           }%
3159       \fi
3160       % The following is a macro because \theCurr@Page and
3161       % \thepageof@pagepoints might differ by more than 1:
3162       \increment@pageof@pagepoints
3163     \else
3164       % These points go on the same page as the points
3165       % currently counted in @pagepoints:
3166       \add@hlfcntrtohlfcntr{@pagepoints}{latest@points}%
3167       \set@hlfcntr{latest@points}{0}%
3168     \fi
3169   \fi
3170 }
3171 \def\increment@pageof@pagepoints{%
3172   \addtocounter{pageof@pagepoints}{1}%
3173   \ifnum \theCurr@Page > \thepageof@pagepoints\relax
3174     \immediate\write\@mainaux
3175         {\string\gdef\string\pointsonpage@
3176          \romannumeral \csname c@pageof@pagepoints\endcsname{0}}%
3177     % See if this has changed from the last run of LaTeX:
3178     \@ifundefined{pointsonpage@\romannumeral
3179                         \csname c@pageof@pagepoints\endcsname}
3180       {\global\@pointschangedtrue}%
3181       {%
3182       % OK; it's defined.  See if it's changed:
3183       \begingroup
3184         \set@hlfcntr{tmp@hlfcntr}{\csname pointsonpage@\romannumeral 
3185                   \csname c@pageof@pagepoints\endcsname\endcsname}%
3186         \edef\othpt@check{\prtaux@hlfcntr{tmp@hlfcntr}}%
3187         \def\pt@check{0}%
3188         \ifx \pt@check \othpt@check
3189           % Do nothing
3190         \else
3191           \global\@pointschangedtrue
3192         \fi
3193       \endgroup
3194       }%
3195     \let\next@incr@pageof = \increment@pageof@pagepoints
3196   \else
3197     \copy@hlfcntr{@pagepoints}{latest@points}%
3198     \set@hlfcntr{latest@points}{0}%
3199     % \page@withpoints will be used to find the last
3200     % page that has points, which will be written to
3201     % the .aux file vis \AtEndDocument:
3202     \global\edef\page@withpoints{\thepageof@pagepoints}%
3203     \let\next@incr@pageof = \relax
3204   \fi
3205   \next@incr@pageof
3206 }
3207
3208
3209
3210
3211
3212
3213
3214 \def\@checkqueslevel#1{%
3215   \begingroup
3216     \def\@temp{#1}%
3217     \ifx\@temp\@queslevel
3218       % Everything's fine; do nothing.
3219     \else
3220       \ClassError{exam}{%
3221         I found a #1 where I expected to find a
3222         \@queslevel\MessageBreak
3223       }{%
3224         Both #1 and \@queslevel \space can be used only inside the
3225         correct \MessageBreak \space \space
3226         environment and outside of any smaller environment
3227         \MessageBreak
3228       }%
3229     \fi
3230   \endgroup
3231 }
3232
3233 \def\@doitem{\@ifnextchar[{\@readpoints}%
3234                           {\item@points@pageinfo}%
3235 }
3236
3237 \def\@readpoints[#1]{%
3238 % We use \def for \@points instead of \edef because we don't want
3239 % \half (if present) to be expanded yet, so that the command \points
3240 % can figure out how to deal with it:
3241   \def\@points{#1}%
3242   \global \@placepointstrue
3243   \if@addpoints
3244     \addto@hlfcntr{numpoints}{\@points}%
3245     \addto@hlfcntr{pointsof@thisquestion}{\@points}%
3246     % latest@points is a holding area for points to be
3247     % added to @pagepoints after we check whether they're
3248     % on the same page as the points currently counted
3249     % by @pagepoints:
3250     \addto@hlfcntr{latest@points}{\@points}%
3251   \fi
3252   \item@points@pageinfo
3253 }
3254
3255
3256
3257 % do@int@lbl is the command used to create a label for every question,
3258 % part, subpart, and subsubpart.  We make no use of these labels, but we
3259 % put them there so that if a question (or part, etc.) is, e.g., moved
3260 % from one page to another, LaTeX will notice this and warn the user
3261 % that LaTeX must be run one more time to be sure everything is correct.
3262 %
3263 % We need to do this even though we've already included code to check
3264 % when point totals change because questions (and parts, etc.) know what
3265 % page they're on from reading the info written to the .aux file on the
3266 % previous run.  Thus, if a question (or part, etc.) is moved to a
3267 % different page, then the pointsonpage totals won't notice until the
3268 % *second* subsequent run of LaTeX, and so there'll be no warning to the
3269 % user on the *first* run.  Including these labels gives the user a
3270 % warning on that first run.
3271
3272 \newcounter{lbl@cntr}
3273 \def\do@int@lbl{%
3274   \addtocounter{lbl@cntr}{1}%
3275   % Looking at latex.ltx reveals that the argument to \label is
3276   % expanded, so we don't really need the \expandafter's in the
3277   % following, but I haven't seen any statement anywhere in
3278   % documentation about it being expanded, so we'll be paranoid and
3279   % protect against future changes in latex.ltx by using
3280   % \expandafter's: 
3281   \expandafter\label\expandafter{\thelbl@cntr @@exam@lbl}%
3282 }
3283
3284
3285 % Bug fix, 5 April 2004: \item@points@pageinfo
3286 % Appending \point@toks and \pageinfo@commands to \everypar:
3287 % Instead of appending the contents of \point@toks and
3288 % \pageinfo@commands to \everypar using \append@toklist,
3289 % we instead want to append only the two tokens
3290 %   \the\point@toks
3291 % and the two tokens
3292 %   \the\pageinfo@commands
3293 % to \everypar.  We need to do this because if a questions environment
3294 % immediately follows a \section command, then @nobreak will be true,
3295 % and so the \if@nobreak inside of \everypar will *not* execute the
3296 % \everypar={} that we had been counting on to keep the points from
3297 % being inserted a second time in the second paragraph of a question.
3298 % Since we've put the command \global \point@toks={} inside of 
3299 % \point@toks and the command \pageinfo@commands={} inside of
3300 % \pageinfo@commands, when the contents of \point@toks and of
3301 % \pageinfo@commands are executed when we enter horizontal mode and
3302 % \everypar is dumped in, the contents of \point@toks and
3303 % \pageinfo@commands will be made empty, and so if
3304 % the second paragraph also get \the\point@toks and
3305 % \the\pageinfo@commands, it won't matter.
3306
3307 \def\item@points@pageinfo{%
3308   \item
3309   % If @qformat is true, and if we're currently doing a question
3310   % (rather than a part, subpart, or subsubpart), then we don't want
3311   % to set the points (if any), since the points of a question will
3312   % appear only if the user chooses to cause that by putting a
3313   % \thepoints in the argument of the \qformat command.
3314   % 
3315   % Also: We need to do this here, *after* the \item command, rather
3316   % than inside the macro \@readpoints, because the \item command
3317   % puts the result of the \qformat command into an \hbox (with the
3318   % command ``\sbox\@tempboxa{\makelabel{#1}}%''), expanding the
3319   % argument of \qformat as it does so.  Thus, @placepoints will be
3320   % true when the argument of \qformat is expanded, and so if the
3321   % user put a \thepoints command inside that argument it will
3322   % correctly expand to the number of points.  (When @placepoints is
3323   % false, \thepoints expands to nothing at all).
3324   \if@qformat
3325     \ifx\ques@ref\@queslevel
3326       \global \@placepointsfalse
3327     \fi
3328   \fi
3329   \if@placepoints
3330     % \setup@point@toks defines \point@block to be a macro that prints
3331     % the points with the correct choice of parentheses, brackets, or
3332     % box, and \@pointname or \@marginpointname and puts commands into
3333     % \point@toks to place \point@block at the correct spot.  It
3334     % doesn't append anything to \everypar (we do that in this macro,
3335     % below). 
3336     \if@pointsdropped
3337       % Do nothing!
3338     \else
3339       \setup@point@toks
3340     \fi
3341     \global \@placepointsfalse
3342   \fi
3343   % We *don't* use \append@toklist; see Bug fix note above
3344   % We can append the tokens ``\the\point@toks'' whether or not we're
3345   % setting any points because if we're not setting them, \point@toks
3346   % will be empty.
3347   % Also: It's important to do this *after* the \item command above,
3348   % since the \item command discards the previous contents of
3349   % \everypar.
3350   \edef\append@everypar{\noexpand\everypar={\the\everypar
3351                         \noexpand\the \noexpand\pageinfo@commands
3352                         \noexpand\the \noexpand\point@toks}}%
3353   \append@everypar
3354   \do@int@lbl
3355 }
3356
3357
3358
3359
3360
3361
3362
3363 % Initialize \@points:
3364 % (Now that I think of it, this seems totally unnecessary,
3365 % but we're not deleting it because we're chicken.)
3366 \def\@points{0}
3367
3368
3369 \def\setup@point@toks{%
3370 % We begin by defining \point@block so that it expands to the properly
3371 % formatted points (including either \pointname or \marginpointname,
3372 % enclosed in either parentheses, brackets, or a box).  We then set
3373 % the token list \point@toks equal to the sequence of commands needed
3374 % to put \point@block at the correct location, followed by the tokens
3375 % ``\global \point@toks={}''.  The \question, \part, \subpart, or 
3376 % \subsubpart command then adds the two tokens ``\the\point@toks'' to
3377 % \everypar.
3378 %
3379 % Note: It is not the *contents* of \point@toks that is added to
3380 % \everypar; just the two tokens ``\the\point@toks''.  This difference
3381 % is the bug fix of 2 April 2004, described above (the bug was that in
3382 % earlier versions, we used to append the contents).
3383 %
3384 % The result of this is that whenever we finally enter horizontal mode
3385 % (because we finally encountered the text of a question, part,
3386 % subpart, or subsubpart) the contents of \point@toks will be dumped
3387 % into horizontal mode and executed, and so the points will be placed
3388 % and the token list \point@toks will be set to empty.  Thus, in the
3389 % occasional circumstances in which \everypar is *not* set to empty
3390 % after being added to the first paragraph (which occurs when a
3391 % questions environment immediately follows a \section command), and
3392 % so \everypar will still contain ``\the\point@toks'' when it
3393 % encounters a possible second paragraph of the first question, the
3394 % tokens ``\the\point@toks'' will insert an *empty* token list, which
3395 % will do no harm.
3396 %
3397 %
3398 % \point@block consists of \point@string surrounded by either
3399 % parentheses, brackets, or an fbox.
3400 %
3401 % \point@string is either \@points\@pointname or
3402 % \@points\@marginpointname.
3403   \setup@point@block
3404   \if@pointsinleftmargin
3405     \def\point@string{\@points\@marginpointname}%
3406     \point@toks={%
3407           \llap{\point@block 
3408                 \hskip\@totalleftmargin
3409                 \hskip\marginpointssep
3410           }%
3411           \global \point@toks={}%
3412     }%
3413   \else
3414     \if@pointsinrightmargin
3415       \def\point@string{\@points\@marginpointname}%
3416       \point@toks={%
3417             \rlap{\hskip-\@totalleftmargin
3418                   \hskip\textwidth
3419                   \hskip\@rightmargin
3420                   \hskip-\rightpointsmargin
3421                   \llap{\point@block}%
3422             }%
3423             \global \point@toks={}%
3424       }%
3425     \else
3426       % The points just go after the question number:
3427       \def\point@string{\@points\@pointname}%
3428       \point@toks={%
3429             \point@block
3430             \enspace
3431             \global \point@toks={}%
3432       }%
3433     \fi
3434   \fi
3435 }% setup@point@toks
3436
3437
3438 \def\setup@point@block{%
3439   \if@boxedpoints
3440     \def\point@block{\fbox{\point@string}}%
3441   \else
3442     \if@bracketedpoints
3443       \def\point@block{[\point@string]}%
3444     \else
3445       % plain old parentheses:
3446       \def\point@block{(\point@string)}%
3447     \fi
3448   \fi
3449 }
3450
3451 \def\droppoints{%
3452   \def\point@string{\@points\@marginpointname}%
3453   \setup@point@block
3454   \leavevmode\unskip\nobreak\hfill
3455   \rlap{\hskip\rightmargin  % Defined by the list environment
3456         \hskip\@rightmargin % Defined by exam.cls
3457         \hskip-\rightpointsmargin
3458         \llap{\point@block}%
3459   }% rlap
3460   \par
3461 }
3462
3463 % The following is the default definition.
3464 % It will be redefined if the user givea a \totalformat command.
3465 \def\setup@total@block{%
3466   \def\total@block{%
3467     Total for Question \thequestion: \totalpoints\@marginpointname
3468   }%
3469 }
3470
3471 \def\totalformat#1{%
3472   \def\setup@total@block{\def\total@block{#1}}%
3473 }
3474 % The following is for use in the argument to a \totalformat command:
3475 \def\totalpoints{\pointsofquestion{\arabic{question}}}
3476
3477 \def\droptotalpoints{%
3478   \setup@total@block
3479   \leavevmode\unskip\nobreak\hfill
3480   \rlap{\hskip\rightmargin  % Defined by the list environment
3481         \hskip\@rightmargin % Defined by exam.cls
3482         \hskip-\rightpointsmargin
3483         \llap{\total@block}%
3484   }% rlap
3485   \par
3486 }
3487
3488
3489 % @placepoints is set true when we encounter a question (or part, etc.)
3490 % that has points.  It is set to false (1) when we set \point@toks equal
3491 % to the sequence of commands required to put the properly formatted
3492 % points onto the page (this happens only if @qformat is false or if
3493 % @qformat is true but we're not doing a question), or (2) by a
3494 % \question or \part command (since if we're doing a question and
3495 % @qformat is true, we need to leave @placepoints true so that the
3496 % \thepoints command can tell if it should expand to points or to
3497 % nothing, and encountering a \question or \part command tells us that
3498 % we no longer have to deal with a possible \thepoints, since we won't
3499 % be expanding a qformat).
3500 \newif\if@placepoints
3501 \@placepointsfalse
3502
3503
3504 % \marginpointssep will be used if the user says
3505 % \pointsinleftmargin.  It will be the distance from whatever encloses
3506 % the points (parentheses, brackets, or a box) to the left margin:
3507 \newlength\marginpointssep
3508 \setlength{\marginpointssep}{5pt}
3509
3510 % \rightpointsmargin will be used if the user says \pointsinrightmargin.
3511 % It will be the distance from whatever encloses the point (parentheses,
3512 % brackets, or a box) to the right edge of the paper:
3513 \newlength\rightpointsmargin
3514 \setlength{\rightpointsmargin}{1cm}
3515
3516
3517 \newif\if@pointsdropped
3518 \newif\if@pointsinleftmargin
3519 \newif\if@pointsinrightmargin
3520 \def\pointsinleftmargin{\global\@pointsinleftmargintrue 
3521                     \global\@pointsinrightmarginfalse
3522                     \global\@pointsdroppedfalse}
3523 \def\pointsinrightmargin{\global\@pointsinrightmargintrue
3524                          \global\@pointsinleftmarginfalse
3525                          \global\@pointsdroppedfalse}
3526 \def\nopointsinmargin{\global\@pointsinleftmarginfalse
3527                       \global\@pointsinrightmarginfalse
3528                       \global\@pointsdroppedfalse}
3529 \def\pointsdroppedatright{\global\@pointsdroppedtrue
3530                           \global\@pointsinleftmarginfalse
3531                           \global\@pointsinrightmarginfalse}
3532 \let\pointsinmargin\pointsinleftmargin
3533 \let\nopointsinrightmargin\nopointsinmargin
3534 \let\nopointsinleftmargin\nopointsinmargin
3535
3536
3537 \nopointsinmargin
3538
3539
3540 % Will the points be displayed inside parentheses (the default), or
3541 % will they be boxed or bracketed:
3542 \newif\if@boxedpoints
3543 \def\boxedpoints{\global\@boxedpointstrue \global\@bracketedpointsfalse}
3544 \def\noboxedpoints{\global\@boxedpointsfalse \global\@bracketedpointsfalse}
3545 \@boxedpointsfalse
3546
3547 \newif\if@bracketedpoints
3548 \def\bracketedpoints{\global\@bracketedpointstrue \global\@boxedpointsfalse}
3549 \def\nobracketedpoints{\global\@bracketedpointsfalse \global\@boxedpointsfalse}
3550 \@bracketedpointsfalse
3551
3552
3553
3554 \def\pointname#1{\gdef\@pointname{#1}}
3555 % Initialize to leave a space, and then the word `points':
3556 %%\pointname{ points}
3557 % The following improvement was contributed by 
3558 % Mate Wierdl <mw@wierdlmpc.msci.memphis.edu> 
3559 % If the number of points is ``1'', then the default value of
3560 % \pointname will print `` point'' instead of `` points'' (and this
3561 % version of the command doesn't generate an error message if the
3562 % points entry is something other than a number):
3563 % Note the space before the \points in the following; it's
3564 % intentional!)
3565 \pointname{ \points}
3566
3567 \newcommand\point@sing{point}
3568 \newcommand\point@plur{points}
3569 \newcommand\pointpoints[2]{%
3570   \renewcommand\point@sing{#1}%
3571   \renewcommand\point@plur{#2}%
3572 }
3573
3574
3575
3576 % The command \points:
3577 % We use \ifthenelse and \equal so that if the user types something
3578 % other than a legit point value, there still won't be any error
3579 % messages.  We rig it so that if the point value looks like it's
3580 % intended to be One or one or ONE, or some strange way of attempting
3581 % one half, then it will expand to the singular value.  Alas, this is
3582 % only useful for English, but I'm hoping few or no users will try doing
3583 % this anyway.
3584
3585 % 0 points, one half point, 1 point, 1 and a half points, etc.:
3586 \newcommand\points{%
3587   \begingroup
3588     \let\half=\relax
3589     \edef\pt@string{\@points}%
3590     \ifthenelse{\equal{\pt@string}{1} \or \equal{\pt@string}{\half}}
3591           {\point@sing}{\point@plur}%
3592   \endgroup
3593 }
3594 %\newcommand\points{%
3595 %  \begingroup
3596 %    \let\half=\relax
3597 %    \edef\pt@string{\@points}%
3598 %    \ifthenelse{\equal{\pt@string}{1} \or \equal{\pt@string}{\half} \or
3599 %      \equal{\pt@string}{0\half} \or \equal{\pt@string}{0 \half}
3600 %      \equal{\pt@string}{one} \or \equal{\pt@string}{One} \or
3601 %      \equal{\pt@string}{ONE}}
3602 %        {\point@sing}{\point@plur}%
3603 %  \endgroup
3604 %}
3605
3606 %\newcommand\points{\ifthenelse{\equal{\@points}{1}}{\point@sing}{\point@plur}}
3607 % If we used the following line instead, then you'd get an error
3608 % message if the point value contained something other than a valid
3609 % integer:
3610 %\pointname{ \ifthenelse{\@points = 1}{point}{points}}
3611
3612 % We used to define a command named \marks that works like \points,
3613 % except that it expands to either ``mark'' or ``marks'', but that
3614 % conflicts with some package or other.  Thus, we'll implement
3615 % \marksnotpoints using the \pointpoints command instead:
3616 \newcommand\marksnotpoints{\pointpoints{mark}{marks}}
3617
3618
3619 % \@marginpointname is used in place of \@pointname if any of
3620 % \@pointsinmargin, \@pointsinrightmargin, and \@pointsdropped are
3621 % true:
3622 \def\marginpointname#1{\gdef\@marginpointname{#1}}
3623 \marginpointname{}
3624
3625
3626 % The following keeps track of whether the user has requested that we
3627 % add up the points on the exam.  We make the default false so that
3628 % users who put other than numbers into the points argument of a
3629 % question (or part, or subpart) won't get error messages.
3630 % We use \if@printtotalpoints as a flag to signal that we are counting
3631 % points, so that we will know to print the total on the screen (and
3632 % in the log file).  We use this separate flag so that the user can
3633 % use both \addpoints and \noaddpoints to count some points and not
3634 % others, but still have the total printed when we finish the file no
3635 % matter what the state of \if@addpoints.
3636 \newif\if@addpoints
3637 \newif\if@printtotalpoints
3638 \def\addpoints{\global\@addpointstrue\global\@printtotalpointstrue}
3639 \def\noaddpoints{\global\@addpointsfalse}
3640 \@addpointsfalse
3641 \@printtotalpointsfalse
3642
3643 %--------------------------------------------------------------------
3644 %                   choices (for multiple choice)
3645
3646
3647 \renewcommand\thechoice{\Alph{choice}}
3648 \newcommand\choicelabel{\thechoice.}
3649
3650 % Added 22 April 2004: Increased the \leftmargin by 2.5em,
3651 % so the choices will be visibly indented.
3652 \newenvironment{choices}%
3653   {\list{\choicelabel}%
3654      {\usecounter{choice}\def\makelabel##1{\hss\llap{##1}}%
3655        \settowidth{\leftmargin}{W.\hskip\labelsep\hskip 2.5em}%
3656        \let\choice=\item
3657        \labelwidth\leftmargin\advance\labelwidth-\labelsep
3658        \topsep=0pt
3659        \partopsep=0pt
3660      }%
3661   }%
3662   {\endlist}
3663
3664 \newenvironment{oneparchoices}%
3665   {%
3666     \setcounter{choice}{0}%
3667     \def\choice{%
3668                  \refstepcounter{choice}%
3669                  \ifnum\value{choice}>1
3670                    \penalty -50\hskip 1em plus 1em\relax
3671                  \fi
3672                  \choicelabel\nobreak\enskip
3673                }%
3674     \let\par\@empty
3675     % If we're continuing the paragraph containing the question,
3676     % then leave a bit of space before the first choice:
3677     \ifvmode\else\enskip\fi
3678     \ignorespaces
3679   }%
3680   {}
3681
3682
3683 %--------------------------------------------------------------------
3684 %             Answer Lines (for short answer questions)
3685
3686 % Note: \ques@ref is also used in \item@points@pageinfo
3687
3688 \def\ques@ref{question}
3689 \def\part@ref{part}
3690 \def\subpart@ref{subpart}
3691 \def\subsubpart@ref{subsubpart}
3692
3693 \newlength\answerlinelength
3694 \newlength\answerskip
3695 \setlength\answerlinelength{1in}
3696 \setlength\answerskip{2ex}
3697
3698 \def\answerline{%
3699   \ifx\@queslevel\ques@ref
3700     \let\ans@l=\questionlabel
3701   \else
3702     \ifx\@queslevel\part@ref
3703       \let\ans@l=\partlabel
3704     \else
3705       \ifx\@queslevel\subpart@ref
3706         \let\ans@l=\subpartlabel
3707       \else
3708         \ifx\@queslevel\subsubpart@ref
3709           \let\ans@l=\subsubpartlabel
3710         \else
3711           % Oops; no question level defined.
3712           % We must be outide of the questions environment.
3713           % Just leave out the label, I guess:
3714           \def\ans@l{}%
3715         \fi
3716       \fi
3717     \fi
3718   \fi
3719   \par \nobreak \vskip \answerskip
3720   \hfill \ans@l~\hbox to \answerlinelength{\hrulefill}%
3721   \par
3722 }
3723
3724 %--------------------------------------------------------------------
3725 %                            \fillwithlines
3726
3727
3728 % \fillwithlines takes one argument, which is either a length or \fill,
3729 % and it fills that much vertical space with horizontal lines that run
3730 % the length of the current line.  That is, the extend from the current
3731 % left margin (which depends on whether we're in a quesiton, parts,
3732 % subpart, or subsubpart) to the right margin.
3733 %
3734 % The distance between the lines is \linefillheight, whose default value
3735 % is set with the command
3736 %
3737 % \setlength\linefillheight{.25in}
3738 %
3739 % This value can be changed by giving a new \setlength command.
3740 %
3741 % The thickness of the lines is \linefillthickness, whose default value
3742 % is set with the command
3743 %
3744 % \setlength\linefillthickness{.2pt}
3745 %
3746 % This value can be changed by giving a new \setlength command.
3747
3748
3749 \newlength\linefillheight
3750 \newlength\linefillthickness
3751 \setlength\linefillheight{.25in}
3752 \setlength\linefillthickness{0.1pt}
3753
3754 \newcommand\linefill{\leavevmode
3755     \leaders\hrule height \linefillthickness \hfill\kern\z@}
3756
3757
3758 \def\fillwithlines#1{%
3759   \begingroup
3760   \ifhmode
3761     \par
3762   \fi
3763   \hrule height \z@
3764   \nobreak
3765   \setbox0=\hbox to \hsize{\hskip \@totalleftmargin
3766           \vrule height \linefillheight depth \z@ width \z@
3767           \linefill}%
3768   % We use \cleaders (rather than \leaders) so that a given
3769   % vertical space will always produce the same number of lines
3770   % no matter where on the page it happens to start:
3771   \cleaders \copy0 \vskip #1 \hbox{}%
3772   \endgroup
3773 }
3774
3775
3776 %--------------------------------------------------------------------
3777 %                      \uplevel and \fullwidth:
3778
3779 % \uplevel is used to print text at the indentation level of the 
3780 % enclosing environment.  For example, to precede a question with
3781 % directions about how that question should be answered, you would
3782 % say \uplevel{Answer this question correctly.}
3783
3784 % \fullwidth is similar, but uses the full page of text on the page.
3785
3786 \long\def\uplevel#1{%
3787   \par\bigskip
3788   \vbox{%
3789     % We set \leftskip to provide the correct left margin for whatever
3790     % text is in the argument of the \uplevel command:
3791     \leftskip=\@totalleftmargin
3792     \advance\leftskip-\leftmargin
3793     % We adjust \@totalleftmargin (and linewidth?) in case there's a
3794     % solution environment inside of the argument to the \uplevel:
3795     \advance\@totalleftmargin-\leftmargin
3796     \advance\linewidth\leftmargin
3797     #1%
3798   }% vbox
3799   \nobreak
3800 }
3801
3802 \long\def\fullwidth#1{%
3803   \par\bigskip
3804   \vbox{%
3805     \leftskip=0pt \rightskip=0pt
3806     \advance\linewidth\@totalleftmargin
3807     \@totalleftmargin=0pt
3808     #1%
3809   }% vbox
3810   \nobreak
3811 }
3812
3813
3814 %--------------------------------------------------------------------
3815 %--------------------------------------------------------------------
3816 %
3817 %                        ********************
3818 %                        ** GRADING TABLES **
3819 %                        ********************
3820
3821
3822
3823 \newcounter{@iterator}
3824 \newlength\@cellwidth
3825
3826 \def\cellwidth#1{\@cellwidth=#1}
3827 \def\gradetablestretch#1{\def\@gtblstretch{#1}}
3828
3829 % All of the following that begin with `h' are for horizontal tables,
3830 % and all of them that begin with `v' are for vertical tables:
3831 \def\hqword#1{\def\@hqword{#1}}
3832 \def\hpword#1{\def\@hpword{#1}}
3833 \def\hsword#1{\def\@hsword{#1}}
3834 \def\htword#1{\def\@htword{#1}}
3835 \def\vqword#1{\def\@vqword{#1}}
3836 \def\vpword#1{\def\@vpword{#1}}
3837 \def\vsword#1{\def\@vsword{#1}}
3838 \def\vtword#1{\def\@vtword{#1}}
3839
3840 \def\vpgword#1{\def\@vpgword{#1}}
3841 \def\hpgword#1{\def\@hpgword{#1}}
3842
3843 % Initialize:
3844 \cellwidth{2em}
3845 \gradetablestretch{1.5}
3846 \hpword{Points:}
3847 \hsword{Score:}
3848 \htword{Total}
3849 \vpword{Points}
3850 \vsword{Score}
3851 \vtword{Total:}
3852
3853 % For tables indexed by question number:
3854 \vqword{Question}
3855 \hqword{Question:}
3856
3857 % For tables indexed by page number:
3858 \vpgword{Page}
3859 \hpgword{Page:}
3860
3861
3862
3863 % The only command here accessible to the user is \gradetable.
3864 % The possibilities are
3865
3866 %   \gradetable[v][questions]
3867 %   \gradetable[v][pages]
3868 %   \gradetable[h][questions]
3869 %   \gradetable[h][pages]
3870
3871 % If one or both optional arguments are omitted, the defaults are `[v]'
3872 % and `[questions]'.
3873
3874 \def\gradetable{%
3875   % If the user doesn't include the optional argument
3876   % choosing between vertical and horizontal,
3877   % we give them vertical:
3878   \@ifnextchar[{\i@gtable}{\i@gtable[v]}%
3879 }
3880 \def\i@gtable[#1]{%
3881   % If the user doesn't include the optional argument
3882   % choosing between questions and pages,
3883   % we give them questions:
3884   \@ifnextchar[{\ii@gtable{#1}}{\ii@gtable{#1}[questions]}%
3885 }
3886 \def\ii@gtable#1[#2]{%
3887   \if@addpoints
3888     \@ifundefined{exam@numpoints}%
3889       {\ClassWarning{exam}%
3890         {%
3891           You must run LaTeX again to produce the grade table.
3892             \MessageBreak
3893         }%
3894         \fbox{Run \LaTeX{} again to produce the table}%
3895       }%
3896       {\do@gtable{#1}{#2}}%
3897   \else
3898     \ClassError{exam}{%
3899       You must give the command \protect\addpoints\MessageBreak
3900       \space\space in order to use the command \protect\gradetable
3901       \MessageBreak
3902       }{%
3903       If you don't give the command \protect\addpoints\MessageBreak
3904       \space\space then we're not keeping track of point values.
3905       \MessageBreak
3906       }%
3907   \fi
3908 }
3909 \def\@questionsref{questions}
3910 \def\@pagesref{pages}
3911 \def\do@gtable#1#2{%
3912   \begingroup % avoid trouble from using \@temp
3913     \def\@temp{#2}%
3914     \ifx\@temp\@questionsref
3915       \@grdtblquestions{#1}%
3916     \else
3917       \ifx\@temp\@pagesref
3918         \@grdtblpages{#1}%
3919       \else
3920         \ClassError{exam}{%
3921           The second optional argument to \protect\gradetable \MessageBreak
3922           \space \space must be either `questions' or `pages'\MessageBreak
3923         }{%
3924           Grade tables can be indexed by questions or pages;\MessageBreak
3925           \space\space for others, you're on your own.\MessageBreak
3926         }%
3927         \fbox{Error: Grade table: Invalid second optional argument `#1'.}%
3928       \fi
3929     \fi
3930   \endgroup
3931 }
3932
3933 %--------------------------------------------------------------------
3934 %--------------------------------------------------------------------
3935 % Grading tables indexed by question numbers:
3936
3937 \def\@grdtblquestions#1{%
3938   \if v#1%
3939     \@vgrdtblquestions
3940   \else
3941     \if h#1%
3942       \@hgrdtblquestions
3943     \else
3944       \ClassError{exam}{%
3945         The first optional argument to \protect\gradetable \MessageBreak
3946         \space \space must be either `h' or `v'\MessageBreak
3947       }{%
3948         Grade tables can be either horizontal or vertical;\MessageBreak
3949         \space\space no diagonals allowed.\MessageBreak
3950       }%
3951       \fbox{Error: Grade table: Invalid first optional argument `#1'.}%
3952     \fi
3953   \fi
3954 }
3955
3956 %--------------------------------------------------------------------
3957 % Vertical, indexed by question numbers:
3958
3959 \def\@vgrdtblquestions{%
3960   \begingroup
3961     % Save the current value of question in @iterator, so that
3962     % we cna restore it after doing the table:
3963     \setcounter{@iterator}{\arabic{question}}%
3964     \renewcommand\arraystretch{\@gtblstretch}%
3965     \begin{tabular}{|c|c|c|}
3966       \hline
3967       {\@vqword}& {\@vpword}& {\@vsword}\\
3968       \hline
3969       \setcounter{question}{0}\do@vloop
3970       {\@vtword}& \numpoints&\hbox to \@cellwidth{\hfill}\\
3971       \hline
3972     \end{tabular}%
3973     % Restore the saved value of question:
3974     \setcounter{question}{\arabic{@iterator}}%
3975   \endgroup
3976 }
3977 \def\do@vloop{%
3978   \addtocounter{question}{1}%
3979   \thequestion & \pointsofquestion{\arabic{question}}&\\
3980   \hline
3981   \ifnum \arabic{question} < \numquestions\relax
3982     \let\next@vloop=\do@vloop
3983   \else
3984     \let\next@vloop=\relax
3985   \fi
3986   \next@vloop
3987 }
3988
3989 %--------------------------------------------------------------------
3990 % Horizontal, indexed by question numbers:
3991
3992 \def\@hgrdtblquestions{%
3993   \begingroup
3994     % Save the current value of question in @iterator, so that
3995     % we can restore it after doing the table:
3996     \setcounter{@iterator}{\arabic{question}}%
3997     \renewcommand\arraystretch{\@gtblstretch}%
3998     \begin{tabular}{|l|*{\numquestions}{c|}c|}
3999       \hline
4000       {\@hqword}& \setcounter{question}{0}\do@qnumloop
4001       {\@htword}\\
4002       \hline
4003       {\@hpword}& \setcounter{question}{0}\do@ptloop
4004       \numpoints\\
4005       \hline
4006       {\@hsword}& \setcounter{question}{0}\do@sloop
4007       \\
4008       \hline
4009     \end{tabular}%
4010     % Restore the saved value of question:
4011     \setcounter{question}{\arabic{@iterator}}%
4012   \endgroup
4013 }
4014 \def\do@qnumloop{%
4015   \addtocounter{question}{1}%
4016   \thequestion &
4017   \ifnum \arabic{question} < \numquestions\relax
4018     \let\next@qnloop=\do@qnumloop
4019   \else
4020     \let\next@qnloop=\relax
4021   \fi
4022   \next@qnloop
4023 }
4024 \def\do@ptloop{%
4025   \addtocounter{question}{1}%
4026   \pointsofquestion{\arabic{question}}&
4027   \ifnum \arabic{question} < \numquestions\relax
4028     \let\next@ptloop=\do@ptloop
4029   \else
4030     \let\next@ptloop=\relax
4031   \fi
4032   \next@ptloop
4033 }
4034 \def\do@sloop{%
4035   \addtocounter{question}{1}%
4036   \hbox to \@cellwidth{\hfill}&
4037   \ifnum \arabic{question} < \numquestions\relax
4038     \let\next@sloop=\do@sloop
4039   \else
4040     \let\next@sloop=\relax
4041   \fi
4042   \next@sloop
4043 }
4044
4045
4046 %--------------------------------------------------------------------
4047 %--------------------------------------------------------------------
4048 % Grading tables indexed by page numbers:
4049 %
4050 % The only pages listed are those on which there is a nonzero number
4051 % of points.  We check pages 1 through \lastpage@withpoints; this way,
4052 % once we've checked that \lastpage@withpoints and
4053 % \pointsonpage@\romannumeral{\lastpage@withpoints} are defined, we
4054 % can safely (we think) check \pointsonpage@\romannumeral{n} for all n
4055 % between 1 and \lastpage@withpoints without generating errors.
4056
4057 % Check that there's enough info from the .aux file to do a page
4058 % indexed grade table:
4059 \def\@grdtblpages#1{%
4060   \@ifundefined{lastpage@withpoints}%
4061     {\ClassWarning{exam}{%
4062       You must run LaTeX twice more\MessageBreak
4063       \space\space to produce the grade table.\MessageBreak}%
4064      \fbox{Run \LaTeX{} twice more to produce the grade table}%
4065     }%
4066     {%
4067       \@ifundefined{pointsonpage@\romannumeral
4068                \csname lastpage@withpoints\endcsname}%
4069         {\ClassWarning{exam}{%
4070           You must run LaTeX again\MessageBreak
4071           \space\space to produce the grade table.\MessageBreak}%
4072          \fbox{Run \LaTeX{} again to produce the grade table}%
4073         }%
4074         {%
4075           \@whchtblpgs#1
4076         }%
4077     }%
4078 }
4079
4080 \def\@whchtblpgs#1{%
4081   \if v#1%
4082     \@vgrdtblpages
4083   \else
4084     \if h#1%
4085       \@hgrdtblpages
4086     \else
4087       \ClassError{exam}{%
4088         The first optional argument to \protect\gradetable \MessageBreak
4089         \space \space must be either `h' or `v'\MessageBreak
4090       }{%
4091         Grade tables can be either horizontal or vertical;\MessageBreak
4092         \space\space no diagonals allowed.\MessageBreak
4093       }%
4094       \fbox{Error: Grade table: Invalid first optional argument `#1'.}%
4095     \fi
4096   \fi
4097 }
4098
4099 %--------------------------------------------------------------------
4100 % Vertical, indexed by pages:
4101
4102 \def\@vgrdtblpages{%
4103   \begingroup
4104     \renewcommand\arraystretch{\@gtblstretch}%
4105     \begin{tabular}{|c|c|c|}
4106       \hline
4107       {\@vpgword}& {\@vpword}& {\@vsword}\\
4108       \hline
4109       \setcounter{@iterator}{0}\pg@vloop
4110       {\@vtword}& \numpoints&\hbox to \@cellwidth{\hfill}\\
4111       \hline
4112     \end{tabular}%
4113   \endgroup
4114 }
4115 \def\pg@vloop{%
4116   \addtocounter{@iterator}{1}%
4117   \set@hlfcntr{tmp@hlfcntr}{\csname pointsonpage@\romannumeral
4118                               \csname c@@iterator\endcsname\endcsname}%
4119 %  \set@hlfcntr{tmp@hlfcntr}{\csname pointsonpage@\roman{@iterator}\endcsname}%
4120 %  spanish.ldf redefines \@roman, so we'll avoid \roman
4121   \ifhlfcntr@pos{tmp@hlfcntr}%
4122     \pg@vloopline
4123   \fi
4124   \ifnum \the@iterator < \lastpage@withpoints\relax
4125     \let\next@pg@vloop=\pg@vloop
4126   \else
4127     \let\next@pg@vloop=\relax
4128   \fi
4129   \next@pg@vloop
4130 }
4131 \def\pg@vloopline{%
4132   % We still don't understand why we need to hide this inside of a
4133   % macro; there's some weird interaction with the \ifnum checking to
4134   % see if something is ``>0''; checking that something is ``=0''
4135   % doesn't cause the ``\ifnum incomplete'' (or whatever) error.
4136   \the@iterator & \pointsonpage{\the@iterator}&\\
4137   \hline
4138 }
4139
4140 %--------------------------------------------------------------------
4141 % Horizontal, indexed by pages:
4142
4143 % For a horizontal table, we need to know how many pages there are
4144 % with points on them:
4145 \newcounter{numpgs@withpts}
4146 \def\count@pgswpts{%
4147   \setcounter{numpgs@withpts}{0}%
4148   \setcounter{@iterator}{0}%
4149   \docount@pgswpts
4150 }
4151 \def\docount@pgswpts{%
4152   \addtocounter{@iterator}{1}%
4153   \set@hlfcntr{tmp@hlfcntr}{\csname pointsonpage@\romannumeral
4154                               \csname c@@iterator\endcsname\endcsname}%
4155 %  \set@hlfcntr{tmp@hlfcntr}{\csname pointsonpage@\roman{@iterator}\endcsname}%
4156 %  spanish.ldf redefines \@roman, so we'll avoid \roman
4157   \ifhlfcntr@pos{tmp@hlfcntr}%
4158     \addtocounter{numpgs@withpts}{1}%
4159   \fi
4160   \ifnum \the@iterator < \lastpage@withpoints\relax
4161     \let\next@docount=\docount@pgswpts
4162   \else
4163     \let\next@docount=\relax
4164   \fi
4165   \next@docount
4166 }
4167
4168
4169 \def\@hgrdtblpages{%
4170   \begingroup
4171     \renewcommand\arraystretch{\@gtblstretch}%
4172     \count@pgswpts
4173     \begin{tabular}{|l|*{\thenumpgs@withpts}{c|}c|}
4174       \hline
4175       {\@hpgword}& \setcounter{@iterator}{0}\do@pgnumloop
4176       {\@htword}\\
4177       \hline
4178       {\@hpword}& \setcounter{@iterator}{0}\do@pgptloop
4179       \numpoints\\
4180       \hline
4181       {\@hsword}& \setcounter{@iterator}{0}\do@pgsloop
4182       \\
4183       \hline
4184     \end{tabular}%
4185   \endgroup
4186 }
4187
4188 \def\do@pgnumloop{%
4189   \addtocounter{@iterator}{1}%
4190   \set@hlfcntr{tmp@hlfcntr}{\csname pointsonpage@\romannumeral
4191                              \csname c@@iterator\endcsname\endcsname}%
4192 %  \set@hlfcntr{tmp@hlfcntr}{\csname pointsonpage@\roman{@iterator}\endcsname}%
4193 %  spanish.ldf redefines \@roman, so we'll avoid \roman
4194   \ifhlfcntr@pos{tmp@hlfcntr}%
4195     \pg@line
4196   \fi
4197   \ifnum \the@iterator < \lastpage@withpoints\relax
4198     \let\next@pgnumloop=\do@pgnumloop
4199   \else
4200     \let\next@pgnumloop=\relax
4201   \fi
4202   \next@pgnumloop
4203 }
4204 \def\pg@line{%
4205   \the@iterator &
4206 }
4207
4208 \def\do@pgptloop{%
4209   \addtocounter{@iterator}{1}%
4210   \set@hlfcntr{tmp@hlfcntr}{\csname pointsonpage@\romannumeral
4211                               \csname c@@iterator\endcsname\endcsname}%
4212 %  \set@hlfcntr{tmp@hlfcntr}{\csname pointsonpage@\roman{@iterator}\endcsname}%
4213 %  spanish.ldf redefines \@roman, so we'll avoid \roman
4214   \ifhlfcntr@pos{tmp@hlfcntr}%
4215     \pgpt@line
4216   \fi
4217   \ifnum \the@iterator < \lastpage@withpoints\relax
4218     \let\next@pgptloop=\do@pgptloop
4219   \else
4220     \let\next@pgptloop=\relax
4221   \fi
4222   \next@pgptloop
4223 }
4224 \def\pgpt@line{%
4225   \csname pointsonpage@\romannumeral \csname c@@iterator\endcsname\endcsname &
4226 %  \csname pointsonpage@\roman{@iterator}\endcsname &
4227 %  spanish.ldf redefines \@roman, so we'll avoid \roman
4228 }
4229
4230 \def\do@pgsloop{%
4231   \addtocounter{@iterator}{1}%
4232 %  \ifnum \csname pointsonpage@\roman{@iterator}\endcsname > 0\relax
4233   \set@hlfcntr{tmp@hlfcntr}{\csname pointsonpage@\romannumeral
4234                               \csname c@@iterator\endcsname\endcsname}%
4235 %  \set@hlfcntr{tmp@hlfcntr}{\csname pointsonpage@\roman{@iterator}\endcsname}%
4236 %  spanish.ldf redefines \@roman, so we'll avoid \roman
4237   \ifhlfcntr@pos{tmp@hlfcntr}%
4238     \pg@sline
4239   \fi
4240   \ifnum \the@iterator < \lastpage@withpoints\relax
4241     \let\next@pgsloop=\do@pgsloop
4242   \else
4243     \let\next@pgsloop=\relax
4244   \fi
4245   \next@pgsloop
4246 }
4247 \def\pg@sline{%
4248   \hbox to \@cellwidth{\hfill}&
4249 }
4250
4251
4252 %--------------------------------------------------------------------
4253 %--------------------------------------------------------------------
4254 %
4255 %                     ***************************
4256 %                     ** SOLUTION ENVIRONMENTS **
4257 %                     ***************************
4258
4259
4260
4261 % If the documentclass options include ``answers'', then the command
4262 % \@printanswerstrue is given at the beginning of the run.
4263
4264 % If the documentclass options include ``noanswers'', then the command
4265 % \@printanswersfalse is given at the beginning of the run.
4266
4267 \def\printanswers{\@printanswerstrue}
4268 \def\noprintanswers{\@printanswersfalse}
4269
4270
4271 % If @printanswers is true, we print the solution using a TheSolution
4272 % environment.  If @printanswers is false, we insert blank vertical space
4273 % equal to the optional argument (the default value of which is 0pt).
4274 \newenvironment{solution}[1][0pt]%
4275   {%
4276     \if@printanswers
4277       \begin{TheSolution}%
4278     \else
4279       \par
4280       \vspace*{#1}%
4281       \setbox\z@\vbox\bgroup
4282     \fi
4283   }{%
4284     \if@printanswers
4285       \end{TheSolution}%
4286     \else
4287       \egroup
4288     \fi
4289   }%
4290
4291 % If @printanswers is true, we print the solution using a TheSolution
4292 % environment.  If @printanswers is false, we insert lined vertical space
4293 % equal to the optional argument (the default value of which is 0pt).
4294 \newenvironment{solutionorlines}[1][0pt]%
4295   {%
4296     \if@printanswers
4297       \begin{TheSolution}%
4298     \else
4299       \par
4300       \fillwithlines{#1}%
4301       \setbox\z@\vbox\bgroup
4302     \fi
4303   }{%
4304     \if@printanswers
4305       \end{TheSolution}%
4306     \else
4307       \egroup
4308     \fi
4309   }%
4310
4311   
4312 % The environment TheSolution is called from the solution environment
4313 % when @printanswers is true.  It uses Donald Arseneau's
4314 % framed.sty macros (included at the end if this file) to allow the
4315 % solution to be broken across pages and have each piece enclosed in
4316 % an fbox (or a colorbox, if the user has given the command
4317 % \shadedsolution).
4318 %
4319 % Of course, the user can change TheSolution with a \renewenvironment
4320 % command.
4321 \newcommand{\solutiontitle}{\noindent\textbf{Solution:}\enspace}
4322 \newenvironment{TheSolution}%
4323   {%
4324     \vspace{\parskip}%
4325     % If we don't set \leftskip and \rightskip to 0pt, then if we
4326     % appear inside of an \uplevel command we'd have indentation
4327     % inside of the solution box:
4328     \leftskip=0pt
4329     \rightskip=0pt
4330     \if@framedsolutions
4331       % Do nothing; we'll use the default \FrameCommand
4332     \else
4333       \def\FrameCommand{\colorbox{SolutionColor}}%
4334     \fi
4335     \MakeFramed{\advance\hsize-\width}%
4336     \solutiontitle
4337     \ignorespaces
4338   }%
4339   {%
4340     \unskip
4341     \endMakeFramed
4342   }%
4343
4344 \newif\if@framedsolutions
4345 \@framedsolutionstrue
4346
4347 \def\framedsolutions{\@framedsolutionstrue}
4348 \def\shadedsolutions{%
4349   \@ifundefined{definecolor}
4350   {%
4351     \ClassError{exam}{%
4352       You must load the color package with the command\MessageBreak
4353       \space\space\protect\usepackage{color}\MessageBreak
4354       in order to use the command \protect\colorsolutions
4355       \MessageBreak
4356       }{%
4357       This command makes use of the package color.sty,\MessageBreak
4358       and so you have to load color.sty before your\MessageBreak
4359       \protect\begin{document} command.\MessageBreak
4360       }%
4361   }%
4362   {%
4363     \definecolor{SolutionColor}{gray}{0.8}
4364     \@framedsolutionsfalse
4365   }%
4366 }
4367
4368 %--------------------------------------------------------------------
4369 %--------------------------------------------------------------------
4370
4371 % The following stuff is lifted from:
4372 %
4373 % framed.sty   v 0.8a   21-Jul-2003
4374 % Copyright (C) 1992-2003 by Donald Arseneau
4375 % These macros may be freely transmitted, reproduced, or modified
4376 % provided that this notice is left intact.
4377 %
4378 % The modifications I made are marked with ``psh'' in a comment:
4379
4380 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4381 % Create framed or shaded regions that can break across pages using 
4382 % \begin{framed} ... \end{framed}    -- ordinary frame box (box at margin)
4383 % \begin{shaded} ... \end{shaded}    -- shaded background (into margin)
4384 %    ... leftbar ...                 -- line on left side
4385 % \begin{MakeFramed}{settings} ... \end{MakeFramed}
4386 %                        -- generic frame (for new environments)
4387 %
4388 % The "framed" environment puts the text into "\fbox" with the
4389 % settings "\fboxrule=\FrameRule" and "\fboxsep=\FrameSep".
4390 % You can change these lengths (using "\setlength") and you
4391 % can even change the definition of "\FrameCommand" to use
4392 % much fancier boxes.
4393 %
4394 % In fact, the "shaded" environment just redefines "\FrameCommand"
4395 % to use "\colorbox{shadecolor}" (and you have to define the
4396 % color "shadecolor": \newcolor{shadecolor}...).
4397 %
4398 % A page break is allowed, and even encouraged, before the framed
4399 % environment.  If you want to attach some text (a box title) to the
4400 % frame, then the text should be inserted by \FrameCommand
4401 %
4402 % The contents of the framed regions are restricted: 
4403 % Floats, footnotes, marginpars and head-line entries will be lost.
4404 % (Some of these may be handled in a later version.)
4405 % This package will not work with the page breaking of multicol.sty,
4406 % or other systems that perform column-balancing.
4407 %
4408 % The MakeFramed environment does the work.  Its "settings" argument
4409 % should contain any adjustments to the text width (applied to \hsize,
4410 % and using the "\width" of the frame itself) as well as a `restore' 
4411 % command -- \@parboxrestore or \FrameRestore or something similar.
4412
4413 % Expert commands:
4414 % \MakeFramed, \endMakeFramed: the "MakeFramed" environment
4415 % \FrameCommand: command to draw the frame around its argument
4416 % \FrameRestore: restore some text settings, but fewer than \@parboxrestore
4417 % \FrameRule: length register; \fboxrule for default "framed".
4418 % \FrameSep: length register; \fboxsep for default "framed".
4419 % \FrameHeightAdjust: macro; height of frame above baseline at top of page
4420
4421 % This is still a `pre-production' version because I can think of many
4422 % features/improvements that should be made.  Nevertheless, starting 
4423 % with version 0.5 it should be bug-free.
4424 %
4425 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4426
4427 %psh: Commented out \ProvidesPackage:
4428 %\ProvidesPackage{framed}[2003/07/21 v 0.8a: 
4429 %   framed or shaded text with page breaks]
4430
4431 %psh: Created \saved@totalleftmargin and \@sollistdepth:
4432 \newdimen\saved@totalleftmargin
4433 \newcount\@sollistdepth
4434
4435 \newenvironment{framed}% using default \FrameCommand
4436   {\MakeFramed {\advance\hsize-\width \FrameRestore}}%
4437   {\endMakeFramed}
4438
4439 \newenvironment{shaded}{%
4440   \def\FrameCommand{\colorbox{shadecolor}}%
4441   \MakeFramed {\FrameRestore}}%
4442  {\endMakeFramed}
4443
4444 \newenvironment{leftbar}{%
4445   \def\FrameCommand{\vrule width 3pt \hspace{10pt}}%
4446   \MakeFramed {\advance\hsize-\width \FrameRestore}}%
4447  {\endMakeFramed}
4448
4449 \chardef\FrameRestore=\catcode`\| % for debug
4450 \catcode`\|=\catcode`\% % (debug: insert space after backslash)
4451
4452 \def\MakeFramed#1{\par
4453  % measure added width and height; call result \width and \height
4454  \setbox\z@\vbox{\vskip-1in \hbox{\hskip-1in 
4455    \FrameCommand{\hbox{\vrule \@height .7in \@depth.3in \@width 1in}}}%
4456    \vskip\z@skip}%
4457  \def\width{\wd\z@}\def\height{\ht\z@}%
4458  \edef\fb@frw{\the\width}\edef\fb@frh{\the\height}%
4459  % insert pre-penalties and skips
4460  \begingroup
4461  \skip@\lastskip
4462  \if@nobreak\else 
4463     \penalty9999 % updates \page parameters
4464     \ifdim\pagefilstretch=\z@ \ifdim\pagefillstretch=\z@
4465        \edef\@tempa{\the\skip@}%
4466        \ifx\@tempa\zero@glue \penalty-30
4467        \else \vskip-\skip@ \penalty-30 \vskip\skip@
4468     \fi\fi\fi
4469     \penalty\z@
4470     % Give a stretchy breakpoint that will always be taken in preference
4471     % to the \penalty 9999 used to update page parameters.  The cube root
4472     % of 10000/100 indicates a multiplier of 0.21545, but the maximum 
4473     % calculated badness is really 8192, not 10000, so the multiplier
4474     % is 0.2301. 
4475     \advance\skip@ \z@ plus-.5\baselineskip
4476     \advance\skip@ \z@ plus-.231\height
4477     \advance\skip@ \z@ plus-.231\skip@
4478     \advance\skip@ \z@ plus-.231\topsep
4479     \vskip-\skip@ \penalty 1800 \vskip\skip@
4480  \fi
4481  \addvspace{\topsep}%
4482  \endgroup
4483  % clear out pending page break
4484  \penalty\@M \vskip 2\baselineskip \vskip\height
4485  \penalty9999 \vskip -2\baselineskip \vskip-\height
4486  \penalty9999 % updates \pagetotal
4487 |\message{After clearout, \pagetotal=\the\pagetotal, \pagegoal=\the\pagegoal. }%
4488  \fb@adjheight 
4489 %psh: Added commands:
4490   \advance\hsize-\@totalleftmargin
4491   \saved@totalleftmargin=\@totalleftmargin
4492   \@totalleftmargin=0pt
4493   \parshape 0
4494   \let\@listdepth=\@sollistdepth
4495   \@sollistdepth=0
4496   \leftmargin=0pt
4497 %psh: end of added commands
4498  \setbox\@tempboxa\vbox\bgroup
4499    #1% Modifications to \hsize (can use \width and \height)
4500    \textwidth\hsize \columnwidth\hsize
4501 %psh: added one line:
4502    \linewidth=\hsize
4503 }
4504
4505 \def\endMakeFramed{\par
4506      \kern\z@ \penalty-100 % put depth into height
4507  \egroup
4508  \begingroup \put@frame \endgroup
4509 %psh: Added one line:
4510  \@totalleftmargin=\saved@totalleftmargin
4511 }
4512
4513 % \put@frame takes the contents of \@tempboxa and puts all, or a piece,
4514 % of it on the page with a frame (\FrameCommand).  It recurses until
4515 % all of \@tempboxa has been used up. (\@tempboxa must have zero depth.)
4516
4517 \def\put@frame{\relax
4518  \ifdim\pagegoal=\maxdimen \pagegoal\vsize \fi
4519 |   \message{=============== Entering putframe ====================^^J
4520 |     \pagegoal=\the\pagegoal,  \pagetotal=\the\pagetotal. }%
4521  \ifinner \else
4522     \dimen@\pagegoal \advance\dimen@-\pagetotal % natural space left on page
4523   \ifdim\dimen@<2\baselineskip 
4524 |   \message{Page has only \the\dimen@\space room left; eject. }%
4525     \eject \fb@adjheight \put@frame
4526   \else % there's appreciable room left on the page
4527 |    \message{\string\pagetotal=\the\pagetotal,
4528 |        \string\pagegoal=\the\pagegoal, 
4529 |        \string\pagestretch=\the\pagestretch,
4530 |        \string\pageshrink=\the\pageshrink,
4531 |        \string\fb@frh=\fb@frh. \space}
4532 |    \message{Box of size \the\ht\@tempboxa\space + \fb@frh}%
4533      \begingroup % temporarily set \dimen@ to be...
4534      \advance\dimen@.8\pageshrink  % maximum space available on page
4535      \advance\dimen@-\fb@frh\relax % space available for frame's contents
4536      \expandafter\endgroup
4537      % restore \dimen@ to real room left on page
4538      \ifdim\dimen@>\ht\@tempboxa % whole box does fit
4539 |       \message{fits in \the\dimen@. }%
4540      \else % box must be split
4541 |       \message{must be split to fit in \the\dimen@. }%
4542         \setbox\@tempboxa\vbox{% simulate frame and flexiblity of the page:
4543            \vskip \fb@frh \@plus\pagestretch \@minus.8\pageshrink
4544            \kern137sp\kern-137sp\penalty-30
4545            \unvbox\@tempboxa}%
4546         \edef\fb@resto@set{\boxmaxdepth\the\boxmaxdepth \splittopskip\the\splittopskip}%
4547         \boxmaxdepth\z@ \splittopskip\z@
4548         \setbox\tw@\vsplit\@tempboxa to\dimen@
4549         \setbox\tw@\vbox{\unvbox\tw@}% natural-sized
4550 |       \message{Box of size \the\ht\@tempboxa\space split to \the\dimen@. 
4551 |          Natural height of split box is \the\ht\tw@. }%
4552         % If the split-to size > (\vsize-\topskip), then set box to full size
4553         \begingroup
4554           \advance\dimen@\topskip
4555           \expandafter\endgroup
4556         \ifdim\dimen@>\pagegoal
4557 |         \message{Frame is big -- Use up the full column. }%
4558           \dimen@ii\pagegoal
4559           \advance\dimen@ii -\topskip
4560           \advance\dimen@ii \FrameHeightAdjust\relax
4561         \else  % suspect this is wrong:
4562           % If the split-to size > feasible room_on_page, rebox it smaller.
4563           \advance\dimen@.8\pageshrink
4564           \ifdim\ht\tw@>\dimen@
4565 |           \message{Box too tall; rebox it to \the\dimen@. }%
4566             \dimen@ii\dimen@
4567           \else % use natural size
4568             \dimen@ii\ht\tw@
4569           \fi
4570         \fi
4571         % Re-box contents to desired size \dimen@ii
4572         \advance\dimen@ii -\fb@frh
4573         \setbox\tw@\vbox to\dimen@ii \bgroup
4574         % remove simulated frame and page flexibility:
4575         \vskip -\fb@frh \@plus-\pagestretch \@minus-.8\pageshrink
4576         \unvbox\tw@ \unpenalty\unpenalty
4577         \ifdim\lastkern=-137sp % whole box went to next page
4578 |          \message{box split at beginning! }%
4579            \egroup \fb@resto@set \eject % (\vskip for frame size was discarded) 
4580            \fb@adjheight
4581         \else %
4582            \egroup \fb@resto@set
4583            \ifvoid\@tempboxa % it all fit after all
4584 |             \message{box split at end! }%
4585               \setbox\@tempboxa\box\tw@
4586            \else % it really did split
4587 |             \message{box split as expected. Its reboxed height is \the\ht\tw@. }%
4588               \ifdim\wd\tw@>\z@
4589 %psh: Changed the command that inserts the box:
4590 %     Instead of \centerline, we shift right by \saved@totalleftmargin:
4591 %              \centerline{\FrameCommand{\box\tw@}}%  ??? \centerline bad idea
4592        \hbox{\hskip \saved@totalleftmargin\FrameCommand{\box\tw@}}%
4593               \else
4594 |               \message{Zero width means likely blank. Don't frame it (guess)}%
4595                 \box\tw@
4596               \fi
4597               \hrule \@height\z@
4598               \eject
4599               \fb@adjheight
4600               \put@frame
4601   \fi\fi\fi\fi\fi
4602   \ifvoid\@tempboxa\else
4603 %psh: Changed the command that inserts the box:
4604 %     Instead of \centerline, we shift right by \saved@totalleftmargin:
4605 %    \centerline{\FrameCommand{\box\@tempboxa}}%
4606     \hbox{\hskip\saved@totalleftmargin\FrameCommand{\box\@tempboxa}}%
4607     \nointerlineskip \null %{\showoutput \showlists}
4608     \penalty-30 \vskip\topsep
4609   \fi}
4610
4611 \def\fb@adjheight{%
4612   \vbox to\FrameHeightAdjust{}% get proper baseline skip from above.
4613   \penalty\@M \nointerlineskip
4614   \vskip-\FrameHeightAdjust
4615   \penalty\@M} % useful for tops of pages
4616
4617 \edef\zero@glue{\the\z@skip}
4618
4619 \catcode`\|=\FrameRestore
4620
4621 % Provide configuration commands:
4622 \providecommand\FrameCommand{\fboxrule=\FrameRule \fboxsep=\FrameSep \fbox}
4623 \@ifundefined{FrameRule}{\newdimen\FrameRule \FrameRule=\fboxrule}{}
4624 \@ifundefined{FrameSep} {\newdimen\FrameSep  \FrameSep =3\fboxsep}{}
4625
4626 % Height of frame above first baseline when frame starts a page:
4627 \providecommand\FrameHeightAdjust{6pt}
4628
4629 % \FrameRestore has parts of \@parboxrestore.  See how it is used in the 
4630 % "settings" argument of \MakeFrame.  Previous behavior can be restored by 
4631 % using \@parboxrestore there, or redefining:
4632 % \makeatletter \renewcommand\FrameRestore{\@parboxrestore} \makeatother
4633 \def\FrameRestore{%
4634   \let\if@nobreak\iffalse
4635   \let\if@noskipsec\iffalse
4636 %  \let\par\@@par  ??
4637   \let\-\@dischyph
4638   \let\'\@acci\let\`\@accii\let\=\@acciii
4639 %  \parindent\z@ \parskip\z@skip    Definitely omit!
4640 %  \everypar{}%  ??
4641   \linewidth\hsize
4642 %  \@totalleftmargin\z@
4643 %  \leftskip\z@skip \rightskip\z@skip \@rightskip\z@skip
4644 %  \parfillskip\@flushglue \lineskip\normallineskip
4645 %  \baselineskip\normalbaselineskip
4646   \sloppy
4647 %  \let\\\@normalcr
4648 }
4649
4650 %  Compatibility with previous versions (temporary!):
4651 \let\fram@d=\MakeFramed  \let\endfram@d=\endMakeFramed
4652
4653 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4654
4655 % This ends the stuff that's lifted from:
4656 % % framed.sty   v 0.8a   21-Jul-2003
4657 % % Copyright (C) 1992-2003 by Donald Arseneau
4658
4659
4660 %--------------------------------------------------------------------
4661 %--------------------------------------------------------------------
4662
4663 \endinput
4664 %---------------------------------------------------------------------
4665 %---------------------------------------------------------------------
4666 %---------------------------------------------------------------------
4667 %---------------------------------------------------------------------
4668 %---------------------------------------------------------------------