3 % A LaTeX2e document class for preparing exams.
6 %% Copyright (c) 1994, 1997, 2000, 2004 Philip S. Hirschhorn
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.
16 % This work has the LPPL maintenance status "author-maintained".
18 % This work consists of the files exam.cls and examdoc.tex.
21 % The user documentation for exam.cls is in the file examdoc.tex.
25 %%% Department of Mathematics
27 %%% Wellesley, MA 02481
30 % The newest version of this documentclass should always be available
31 % from my web page: http://www-math.mit.edu/~psh/
35 \def\filedate{2004/08/14}
36 %---------------------------------------------------------------------
37 %---------------------------------------------------------------------
38 % PLEASE DO NOT MAKE ANY CHANGES TO THIS FILE!
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!
43 % If there's some feature that you'd like that this file doesn't
44 % provide, tell me about it.
52 % Piet van Oostrum, from whose excellent ``fancyheadings.sty'' we
53 % shamelessly stole most of the code for setting the headers and
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''.
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
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.)
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.)
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.
87 %--------------------------------------------------------------------
88 %--------------------------------------------------------------------
94 % Enough already with betatest.
96 %--------------------------------------------------------------------
98 % Version 2.116$\beta$:
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.
104 %--------------------------------------------------------------------
106 % Version 2.115$\beta$:
108 % New environment: oneparchoices
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.
117 %--------------------------------------------------------------------
119 % Version 2.114$\beta$:
121 % We fixed up the code for \uplevel and \fullwidth so that they work
122 % correctly if a solution environment is inside the argument.
124 %--------------------------------------------------------------------
126 % Version 2.113$\beta$:
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).
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.
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.
148 %--------------------------------------------------------------------
150 % Version 2.112$\beta$:
152 % New environment: coverpages
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
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.
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
177 % \coverrunningheader
178 % \coverfirstpageheader
185 % \coverrunningfooter
186 % \coverfirstpagefooter
192 % \coverextraheadheight
193 % \coverextrafootheight
195 %--------------------------------------------------------------------
197 % Version 2.111$\beta$:
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
205 % \roman{countername}
209 % \romannumeral \csname c@countername\endcsname
211 % for all of those command names, and now all at least seems to be
215 % The following stuff isn't really complete yet:
216 % New environment: coverpages
221 % \coverrunningheader
222 % \coverfirstpageheader
229 % \coverrunningfooter
230 % \coverfirstpagefooter
236 % \coverextraheadheight
237 % \coverextrafootheight
239 %--------------------------------------------------------------------
241 % Version 2.110$\beta$:
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:
246 % \newcommand*\usehorizontalhalf
247 % \newcommand*\useslantedhalf
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.
253 %--------------------------------------------------------------------
255 % Version 2.109$\beta$:
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:
270 %--------------------------------------------------------------------
272 % Version 2.108$\beta$:
274 % New environment: solutionorlines
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).
282 % Also: Changed the shade of gray used as the default color for
285 % Changed the default thickness of lines used by \fillwithlines.
287 %--------------------------------------------------------------------
289 % Version 2.107$\beta$:
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
298 % To use this option, the user must load the color package with the
303 % in the preamble. (If appropriate, optional arguments can be used in
304 % that command.) The user can then give the command
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
313 % \definecolor{SolutionColor}{gray}{0.9}
315 % and the user can change that by giving a \definecolor command *after*
316 % giving the command \shadedsolutions. For example, the command
318 % \definecolor{SolutionColor}{rgb}{0.8,0.9,1}
320 % sets the background color to a light blue.
322 % You can return to the default situation of having solutions printed
323 % inside an \fbox by giving the command
327 % Note added later: The default shade of gray was changed in version
330 %--------------------------------------------------------------------
332 % Version 2.106$\beta$:
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.
339 % We also changed the default definition of \solutiontitle; it's now
342 % \newcommand{\solutiontitle}{\noindent\textbf{Solution:}\enspace}
345 %--------------------------------------------------------------------
347 % Version 2.105$\beta$:
349 % We're making the thickness of the lines used by \fillwithlines
350 % changeable, and changing the default thickness.
352 % We're doing this by defining a new command:
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
361 % The default value of \linefillthickness is set by the command
363 % \setlength\linefillthickness{0.2pt}
365 % and this can be changed by giving a new \setlength command.
367 % Note added later: The default thickness was changed in version
370 %--------------------------------------------------------------------
372 % Version 2.104$\beta$:
374 % We added a new command: \fillwithlines
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.
382 % The distance between the lines is \linefillheight, whose default value
383 % is set with the command
385 % \setlength\linefillheight{.25in}
387 % This value can be changed by giving a new \setlength command.
389 %--------------------------------------------------------------------
391 % Version 2.103$\beta$:
393 % We added a new command: \answerline
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.
400 % The default values are set by the commands
402 % \setlength\answerlinelength{1in}
403 % \setlength\answerskip{2ex}
405 % and these can be changed by giving new \setlength commands.
407 %--------------------------------------------------------------------
409 % Version 2.101$\beta$:
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.
416 % We changed the default format for the \droptotalpoints command, so
419 % Total for Question 1: 25
421 % where the ``25'' is followed by \marginpointname, whose default value
424 %--------------------------------------------------------------------
426 % Version 2.098$\beta$:
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.
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.
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).
445 % We also created a new command:
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
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
458 % \setlength{\longsolutionindent}{2em}
460 % and the user can change this by giving a new \setlength command.
462 % Note added later: longsolution was eliminated in version
465 %--------------------------------------------------------------------
467 % Version 2.097$\beta$:
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
475 % a double box, if \boxedpoints is in effect,
476 % double brackets, if \bracketedpoints is in effect, or
477 % double parentheses, otherwise.
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
485 % Note added later: We changed the default format again in version
486 % 2.101$\beta$; see the notes above.
488 %--------------------------------------------------------------------
490 % Version 2.096$\beta$:
492 % The labels for questions, parts, subparts, and subsubparts can now be
493 % customized. The format now depends on the commands
500 % the default definitions of which are:
502 % \newcommand\questionlabel{\thequestion.}
503 % \newcommand\partlabel{(\thepartno)}
504 % \newcommand\subpartlabel{\thesubpart.}
505 % \newcommand\subsubpartlabel{\thesubsubpart)}
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'.
514 %--------------------------------------------------------------------
516 % Version 2.095$\beta$:
518 % Added solution and longsolution environments.
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
525 % The commands \printanswers and \noprintanswers can be given as many
526 % times as desired to switch back and forth between the two.
528 % The documentclass option ``answers'' is equivalent to giving a
529 % \printanswers command at the beginning of the file.
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.)
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.
541 % The longsolution environment prints the solution with left and right
542 % margins slightly increased, and it can be broken across pages.
544 % When printing the solution, both environments begin with
545 % \solutiontitle, the default value of which is created by the command
547 % \newcommand{\solutiontitle}{\textbf{Solution:}\enspace}
549 % This can be changed with the \renewcommand command.
551 % Note added later: solution was changed and longsolution was
552 % eliminated in version 2.106$\beta$.
554 %--------------------------------------------------------------------
556 % Version 2.094$\beta$:
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.
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.
568 % Thus: \gradetable is equivalent to \gradetable[v][questions]
570 % `[v]' and `[h]' are as before: Vertically oriented or horizontally
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
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.
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:)
595 % For tables indexed by questions, the appropriate row and column titles
596 % are set by the following commands:
601 % For tables indexed by pages, the appropriate row and column titles are
602 % set by the following commands:
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:
615 % \gradetablestretch{1.5}
617 %--------------------------------------------------------------------
619 % Version 2.093$\beta$:
621 % If the user gives the comman \addpoints, then
622 % \pointsonpage{n} expands to the number of points on page n.
624 %--------------------------------------------------------------------
626 % Version 2.092$\beta$:
628 % Increased the \leftmargin in the choices environment.
630 %--------------------------------------------------------------------
632 % Version 2.091$\beta$:
635 % \pointsdroppedatright
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
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
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.
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.
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
684 % \totalformat{[\pointsofquestion{\arabic{question}}]}
686 % will produce the same appearance as the default does when the command
687 % \bracketedpoints is in effect and \marginpointname is empty, and the
690 % \totalformat{\fbox{Total: \pointsofquestion{\arabic{question}}}}
692 % produces a box surrounding ``Total: 25''.
694 %--------------------------------------------------------------------
696 % Version 2.087$\beta$:
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.
704 % Similarly, we changed ``\pageinfo@commands={}'' to
705 % ``\global \pageinfo@commands={}''.
707 %--------------------------------------------------------------------
709 % Version 2.080$\beta$:
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.
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.
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].
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
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
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.
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:
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:
771 % \gradetablestretch{1.5}
775 % Changing the definition of \points:
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}.
784 %--------------------------------------------------------------------
786 % Version 2.070$\beta$:
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.
796 %--------------------------------------------------------------------
798 % Version 2.067$\beta$:
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
805 %--------------------------------------------------------------------
806 % For use in headers and footers:
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.
813 % \ContinuedQuestion expands to the number of the question that is
814 % being continued from an earlier page.
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.
821 % \IncompleteQuestion expands to the number of the question that is
822 % continued on the next page.
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.
829 %--------------------------------------------------------------------
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.
838 % \def\marksnotpoints
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).
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.
858 % \pointsinrightmargin
859 % \nopointsinrightmargin
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.
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}).
878 % subsubparts environment
879 % Numbered using lower case greek letters.
882 % choices environment, for multiple choice answers
885 % \qformat{Format line}
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.
894 % \noqformat returns to the standard question number formatting.
898 % The standard options
910 % Two new commands for use in \pointname, \marginpointname, and
913 % \points expands to either ``point'' or ``points'', depending on
914 % whether the number of points is 1 or other than 1.
916 % \marks expands to either ``mark'' or ``marks'', depending on
917 % whether the number of points is 1 or other than 1.
920 %--------------------------------------------------------------------
921 %--------------------------------------------------------------------
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.
927 %--------------------------------------------------------------------
928 %--------------------------------------------------------------------
930 \NeedsTeXFormat{LaTeX2e}
932 \ProvidesClass{exam}[\filedate\space Version \fileversion\space by
935 \RequirePackage{ifthen}
937 \newif\if@printanswers
939 \DeclareOption{answers}{\@printanswerstrue}
940 \DeclareOption{noanswers}{\@printanswersfalse}
943 \PassOptionsToClass{\CurrentOption}{article}%
945 \ProcessOptions\relax
956 % We set the parameters in terms of \paperwidth and \paperheight
957 % so that the options
969 \setlength{\textwidth}{\paperwidth}
970 \addtolength{\textwidth}{-2in}
971 \setlength{\oddsidemargin}{0pt}
972 \setlength{\evensidemargin}{0pt}
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}
983 \setlength{\marginparwidth}{.5in}
984 \setlength{\marginparsep}{5pt}
990 %--------------------------------------------------------------------
996 \newlength\@extrawidth
998 % \@rightmargin is needed for \pointsinrightmargin and
999 % \pointsdroppedatright, so that we can right justify the points:
1000 \newlength\@rightmargin
1001 \setlength{\@rightmargin}{1in}
1003 % We put the argument of \extrawidth into a length so that it will
1004 % work correctly even if it's negative:
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
1020 %--------------------------------------------------------------------
1021 %--------------------------------------------------------------------
1022 % Making room for large headers and footers
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:
1030 \newlength\@extrahead
1031 \newlength\@extrafoot
1032 \setlength{\@extrahead}{0in}
1033 \setlength{\@extrafoot}{0in}
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:
1042 \newlength\covrun@exhd
1043 \newlength\covfp@exhd
1044 \newlength\covrun@exft
1045 \newlength\covfp@exft
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}
1057 \newcommand*\adj@hdht@ftht{%
1059 \ifnum\value{page}=1
1060 \@setheadheight{\covfp@exhd}%
1061 \@setfootheight{\covfp@exft}%
1063 \@setheadheight{\covrun@exhd}%
1064 \@setfootheight{\covrun@exft}%
1067 \ifnum\value{page}=1
1068 \@setheadheight{\fp@exhd}%
1069 \@setfootheight{\fp@exft}%
1071 \@setheadheight{\run@exhd}%
1072 \@setfootheight{\run@exft}%
1078 \newcommand*\extraheadheight{%
1079 \@ifnextchar[{\@xtrahd}{\@ytrahd}%
1082 \def\@xtrahd[#1]#2{%
1083 \setlength{\fp@exhd}{#1}%
1084 \setlength{\run@exhd}{#2}%
1089 \setlength{\fp@exhd}{#1}%
1090 \setlength{\run@exhd}{#1}%
1094 \newcommand*\extrafootheight{%
1095 \@ifnextchar[{\@xtraft}{\@ytraft}%
1098 \def\@xtraft[#1]#2{%
1099 \setlength{\fp@exft}{#1}%
1100 \setlength{\run@exft}{#2}%
1105 \setlength{\fp@exft}{#1}%
1106 \setlength{\run@exft}{#1}%
1111 \newcommand*\coverextraheadheight{%
1112 \@ifnextchar[{\cov@xtrahd}{\cov@ytrahd}%
1115 \def\cov@xtrahd[#1]#2{%
1116 \setlength{\covfp@exhd}{#1}%
1117 \setlength{\covrun@exhd}{#2}%
1122 \setlength{\covfp@exhd}{#1}%
1123 \setlength{\covrun@exhd}{#1}%
1127 \newcommand*\coverextrafootheight{%
1128 \@ifnextchar[{\cov@xtraft}{\cov@ytraft}%
1131 \def\cov@xtraft[#1]#2{%
1132 \setlength{\covfp@exft}{#1}%
1133 \setlength{\covrun@exft}{#2}%
1138 \setlength{\covfp@exft}{#1}%
1139 \setlength{\covrun@exft}{#1}%
1143 \def\@appendoutput#1{%
1144 \output=\expandafter{\the\output #1}%
1147 \@appendoutput{\adj@hdht@ftht}
1149 %--------------------------------------------------------------------
1150 % \setheadheight and \setfootheight:
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:
1161 \global\@extrahead=0in
1164 \global\@extrahead=0in
1166 \global\@extrahead=#1
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
1178 \global\@colht=\textheight
1179 \global\@colroom=\textheight
1180 \global\vsize=\textheight
1181 \global\pagegoal=\textheight
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:
1193 \global\@extrafoot=0in
1196 \global\@extrafoot=0in
1198 \global\@extrafoot=#1
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
1209 \global\@colht=\textheight
1210 \global\@colroom=\textheight
1211 \global\vsize=\textheight
1212 \global\pagegoal=\textheight
1219 %---------------------------------------------------------------------
1221 % *************************
1222 % ** HEADERS AND FOOTERS **
1223 % *************************
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.
1234 \newcommand*\ps@head{%
1239 \newcommand*\ps@headandfoot{%
1244 \newcommand*\ps@foot{%
1249 % \ps@empty is already defined by article.cls, so we'll
1250 % say \def instead of \newcommand*:
1256 \newif\if@coverpages
1259 \newenvironment{coverpages}{%
1260 \ifnum \value{numquestions}>0
1262 Coverpages cannot be used after questions have begun.\MessageBreak
1264 All question, part, subpart, and subsubpart environments
1266 must begin after the cover pages are complete.\MessageBreak
1270 \pagenumbering{roman}%
1274 \pagenumbering{arabic}%
1278 \newcommand*\cover@question@error{%
1280 No questions are allowed in the cover pages.\MessageBreak
1282 All question, part, subpart, and subsubpart environments
1284 must begin after the cover pages are complete.\MessageBreak
1290 \newcommand*\@dohead{%
1293 \ifnum\value{page}=1
1299 \ifnum\value{page}=1
1306 \let\@evenhead=\@oddhead
1309 \newcommand*\@dofoot{%
1312 \ifnum\value{page}=1
1318 \ifnum\value{page}=1
1325 \let\@evenfoot=\@oddfoot
1328 \newcommand*\@nohead{%
1330 \let\@evenhead=\@oddhead
1333 \newcommand*\@nofoot{%
1335 \let\@evenfoot=\@oddfoot
1341 %--------------------------------------------------------------------
1342 % \@fullhead, \run@fullhead, \@fullfoot, and \run@fullfoot:
1344 \newcommand*\@fullhead{%
1345 \vbox to \headheight{%
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}}%
1355 % an invisible hrule, to keep positioning constant:
1362 \newcommand*\run@fullhead{%
1363 \vbox to \headheight{%
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}}%
1373 % an invisible hrule, to keep positioning constant:
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
1385 \newcommand*\@fullfoot{%
1390 % an invisible hrule, to keep positioning constant:
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}}%
1404 \newcommand*\run@fullfoot{%
1409 % an invisible hrule, to keep positioning constant:
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}}%
1422 %--------------------------------------------------------------------
1423 % \cov@fullhead, \covrun@fullhead, \cov@fullfoot, and
1426 \newcommand*\cov@fullhead{%
1427 \vbox to \headheight{%
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}}%
1437 % an invisible hrule, to keep positioning constant:
1444 \newcommand*\covrun@fullhead{%
1445 \vbox to \headheight{%
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}}%
1455 % an invisible hrule, to keep positioning constant:
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
1467 \newcommand*\cov@fullfoot{%
1472 % an invisible hrule, to keep positioning constant:
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}}%
1486 \newcommand*\covrun@fullfoot{%
1491 % an invisible hrule, to keep positioning constant:
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}}%
1505 %--------------------------------------------------------------------
1506 %--------------------------------------------------------------------
1508 % ********************************************
1509 % ** COMMANDS TO DEFINE HEADERS AND FOOTERS **
1510 % ********************************************
1512 % \lhead[#1]{#2} sets the first page left head to #1, and the
1513 % running left head to #2
1515 % \lhead{#1} sets both the first page left head and the running
1518 % \chead, \rhead, \lfoot, \cfoot, and \rfoot work similarly.
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)
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)
1531 % Alternative commands are:
1532 % \firstpageheader{LEFT}{CENTER}{RIGHT}
1533 % \runningheader{LEFT}{CENTER}{RIGHT}
1535 % \header{LEFT}{CENTER}{RIGHT}
1536 % which is equivalent to the two commands
1537 % \firstpageheader{LEFT}{CENTER}{RIGHT}
1538 % \runningheader{LEFT}{CENTER}{RIGHT}
1540 % Alternative commands are:
1541 % \firstpagefooter{LEFT}{CENTER}{RIGHT}
1542 % \runningfoother{LEFT}{CENTER}{RIGHT}
1544 % \footer{LEFT}{CENTER}{RIGHT}
1545 % which is equivalent to the two commands
1546 % \firstpagefooter{LEFT}{CENTER}{RIGHT}
1547 % \runningfoother{LEFT}{CENTER}{RIGHT}
1549 \def\firstpageheader#1#2#3{%
1555 \def\runningheader#1#2#3{%
1562 \firstpageheader{#1}{#2}{#3}%
1563 \runningheader{#1}{#2}{#3}%
1567 \def\firstpagefooter#1#2#3{%
1573 \def\runningfooter#1#2#3{%
1580 \firstpagefooter{#1}{#2}{#3}%
1581 \runningfooter{#1}{#2}{#3}%
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}}
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}}
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}}
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}}
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}}
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}}
1611 % Initialize head and foot:
1615 \pagestyle{headandfoot}
1621 \cfoot[]{Page \thepage}
1624 %--------------------------------------------------------------------
1625 % Coverpage headers and footers
1627 % \coverlhead[#1]{#2} sets the first cover page left head to #1, and the
1628 % running cover left head to #2
1630 % \coverlhead{#1} sets both the first cover page left head and the running
1631 % cover left head to #1
1633 % \coverchead, \coverrhead, \coverlfoot, \covercfoot, and \coverrfoot
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)
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)
1647 % Alternative commands are:
1648 % \coverfirstpageheader{LEFT}{CENTER}{RIGHT}
1649 % \coverrunningheader{LEFT}{CENTER}{RIGHT}
1651 % \coverheader{LEFT}{CENTER}{RIGHT}
1652 % which is equivalent to the two commands
1653 % \coverfirstpageheader{LEFT}{CENTER}{RIGHT}
1654 % \coverrunningheader{LEFT}{CENTER}{RIGHT}
1656 % Alternative commands are:
1657 % \coverfirstpagefooter{LEFT}{CENTER}{RIGHT}
1658 % \coverrunningfoother{LEFT}{CENTER}{RIGHT}
1660 % \coverfooter{LEFT}{CENTER}{RIGHT}
1661 % which is equivalent to the two commands
1662 % \coverfirstpagefooter{LEFT}{CENTER}{RIGHT}
1663 % \coverrunningfoother{LEFT}{CENTER}{RIGHT}
1665 \def\coverfirstpageheader#1#2#3{%
1671 \def\coverrunningheader#1#2#3{%
1672 \def\covrun@lhead{#1}%
1673 \def\covrun@chead{#2}%
1674 \def\covrun@rhead{#3}%
1677 \def\coverheader#1#2#3{%
1678 \coverfirstpageheader{#1}{#2}{#3}%
1679 \coverrunningheader{#1}{#2}{#3}%
1683 \def\coverfirstpagefooter#1#2#3{%
1689 \def\coverrunningfooter#1#2#3{%
1690 \def\covrun@lfoot{#1}%
1691 \def\covrun@cfoot{#2}%
1692 \def\covrun@rfoot{#3}%
1695 \def\coverfooter#1#2#3{%
1696 \coverfirstpagefooter{#1}{#2}{#3}%
1697 \coverrunningfooter{#1}{#2}{#3}%
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}}
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}}
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}}
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}}
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}}
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}}
1727 % Initialize coverpage head and foot:
1740 %--------------------------------------------------------------------
1741 %--------------------------------------------------------------------
1743 % Headrules and footrules:
1746 \newif\ifrun@headrule
1748 \def\firstpageheadrule{\@headruletrue}
1749 \def\nofirstpageheadrule{\@headrulefalse}
1751 \def\runningheadrule{\run@headruletrue}
1752 \def\norunningheadrule{\run@headrulefalse}
1754 \def\headrule{\@headruletrue\run@headruletrue}
1755 \def\noheadrule{\@headrulefalse\run@headrulefalse}
1760 \newif\ifrun@footrule
1762 \def\firstpagefootrule{\@footruletrue}
1763 \def\nofirstpagefootrule{\@footrulefalse}
1765 \def\runningfootrule{\run@footruletrue}
1766 \def\norunningfootrule{\run@footrulefalse}
1768 \def\footrule{\@footruletrue\run@footruletrue}
1769 \def\nofootrule{\@footrulefalse\run@footrulefalse}
1779 % Cover page headrules and footrules:
1781 \newif\ifcov@headrule
1782 \newif\ifcovrun@headrule
1784 \def\coverfirstpageheadrule{\cov@headruletrue}
1785 \def\nocoverfirstpageheadrule{\cov@headrulefalse}
1787 \def\coverrunningheadrule{\covrun@headruletrue}
1788 \def\nocoverrunningheadrule{\covrun@headrulefalse}
1790 \def\coverheadrule{\cov@headruletrue\covrun@headruletrue}
1791 \def\nocoverheadrule{\cov@headrulefalse\covrun@headrulefalse}
1795 \newif\ifcov@footrule
1796 \newif\ifcovrun@footrule
1798 \def\coverfirstpagefootrule{\cov@footruletrue}
1799 \def\nocoverfirstpagefootrule{\cov@footrulefalse}
1801 \def\coverrunningfootrule{\covrun@footruletrue}
1802 \def\nocoverrunningfootrule{\covrun@footrulefalse}
1804 \def\coverfootrule{\cov@footruletrue\covrun@footruletrue}
1805 \def\nocoverfootrule{\cov@footrulefalse\covrun@footrulefalse}
1816 %--------------------------------------------------------------------
1817 %--------------------------------------------------------------------
1819 % \numpages, \iflastpage, and \oddeven
1820 % Also: \numpoints, \numquestions, \numparts, and \numsubparts
1821 % Also also: \pointsofquestion
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}}
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:
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.
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).
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.
1851 \def\numpages{\@ifundefined{exam@lastpage}%
1852 {\mbox{\normalfont\bf ??}}%
1856 \def\numpoints{\@ifundefined{exam@numpoints}%
1857 {\mbox{\normalfont\bf ??}}%
1861 \def\numquestions{\@ifundefined{exam@numquestions}%
1862 {\mbox{\normalfont\bf ??}}%
1866 \def\numparts{\@ifundefined{exam@numparts}%
1867 {\mbox{\normalfont\bf ??}}%
1871 \def\numsubparts{\@ifundefined{exam@numsubparts}%
1872 {\mbox{\normalfont\bf ??}}%
1876 \def\numsubsubparts{\@ifundefined{exam@numsubsubparts}%
1877 {\mbox{\normalfont\bf ??}}%
1878 \exam@numsubsubparts
1881 \def\pointsofquestion#1{\@ifundefined{pointsofq@\romannumeral #1}%
1882 {\mbox{\normalfont\bf ??}}%
1883 {\csname pointsofq@\romannumeral #1\endcsname}%
1886 \def\pointsonpage#1{\@ifundefined{pointsonpage@\romannumeral #1}%
1887 {\mbox{\normalfont\bf ??}}%
1888 {\csname pointsonpage@\romannumeral #1\endcsname}%
1892 \newif\if@pointschanged
1893 \@pointschangedfalse
1897 %%%\let\@realenddocument=\enddocument
1898 %%%\def\enddocument{\clearpage
1900 %%% {\advance\c@page-1 \immediate\write\@mainaux
1901 %%% {\string\newlabel{@lastpage}{{}{\arabic{page}}}}%
1904 %%% \@realenddocument
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}%
1921 % OK; it's defined. See if it's changed:
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
1929 \global\@pointschangedtrue
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}%
1951 % OK; it's defined. See if it's changed:
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
1960 \global\@pointschangedtrue
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}%
1971 % OK; it's defined. See if it's changed:
1973 \edef\othpt@check{\page@withpoints}%
1974 \edef\pt@check{\lastpage@withpoints}%
1975 \ifx \pt@check \othpt@check
1978 \global\@pointschangedtrue
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
1996 \typeout{This exam has a total of \typ@expnd\space points.}
2000 \ClassWarningNoLine{exam}{Point totals have changed.
2001 Rerun to get point totals right}%
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
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
2032 %--------------------------------------------------------------------
2033 %--------------------------------------------------------------------
2034 % \ifcontinuation, \ContinuedQuestion,
2035 % \ifincomplete, and \IncompleteQuestion
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.)
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.)
2050 % We use \PgInfo, \PgInfo@write, and \PgInfo@get to know on which page
2051 % each question, part, subpart, and subsubpart appears.
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.
2057 % The label for a question is of the form `question@2' (if it's question
2060 % The label for a part is of the form `part@2@1' (if it's part a of
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).
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).
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
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}.
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{%
2096 \edef\reserved@a{\write\@mainaux
2097 {\string\PgInfo{#1}{\noexpand\thepage}}}%
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}}
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}
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
2120 \def\set@counter@to@pageof#1#2{%
2121 \@ifundefined{Pg@#2}%
2122 {\setcounter{#1}{-1}}%
2123 {\setcounter{#1}{\csname Pg@#2\endcsname}}%
2127 %--------------------------------------------------------------------
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.
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
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
2153 \ifnum \thepage < \csname Pg@question@1\endcsname\relax
2154 % We're before the page with question 1:
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
2165 % See if we're after a \nomorequestions command:
2166 \@ifundefined{Pg@@endquestions}%
2168 {\ifnum \thepage > \PgInfo@get{@endquestions}\relax
2169 % We're after a \nomorequestions:
2172 % We actually are incomplete:
2181 \def\nomorequestions{
2182 \PgInfo@write{@endquestions}%
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
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
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
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).
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.
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
2226 \def\ref@relax{\relax}
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
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.
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
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
2268 \newcounter{latest@ques}
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
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}%
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}%
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}}%
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
2325 \let\next@dlq=\decr@latest@ques
2328 % latest@ques starts on this page or earlier, so
2329 % that's the correct question number! Exit:
2330 \let\next@dlq=\relax
2337 %--------------------------------------------------------------------
2338 %--------------------------------------------------------------------
2339 %--------------------------------------------------------------------
2340 \newcounter{ques@end}
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
2346 % Set latest@ques equal to the correct question number:
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}%
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}%
2358 \setcounter{ques@end}{\PgInfo@get{question@\thelatest@ques}}%
2364 \newcounter{last@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}%
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}%
2377 % Nope; no subparts.
2378 \setcounter{ques@end}{\PgInfo@get{part@\thelatest@ques
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
2392 {\addtocounter{last@part}{1}%
2393 \let\nextfind@lastpart=\find@lastpart
2398 \newcounter{last@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}%
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}%
2412 % Nope; no subsubparts
2413 \setcounter{ques@end}{\PgInfo@get{subpart@\thelatest@ques
2414 @\thelast@part @\thelast@subpart}}%
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
2428 {\addtocounter{last@subpart}{1}%
2429 \let\nextfind@lastsubpart=\find@lastsubpart
2431 \nextfind@lastsubpart
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}}%
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
2456 {\addtocounter{last@subsubpart}{1}%
2457 \let\nextfind@lastsubsubpart=\find@lastsubsubpart
2459 \nextfind@lastsubsubpart
2463 %--------------------------------------------------------------------
2464 \newcounter{incmp@ques}
2466 \def\IncompleteQuestion{%
2471 \def\Find@Incmp@ques{%
2472 \iflastpage{\setcounter{incmp@ques}{-1}}{\chk@incomp}%
2474 \newcounter{next@ques}
2475 \newcounter{nextq@page}
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}}%
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}%
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}%
2494 \setcounter{incmp@ques}{-1}%
2501 \def\ifincomplete#1#2{%
2502 \def\incomp@first{#1}%
2503 \def\incomp@second{#2}%
2505 \ifnum \theincmp@ques < 0\relax
2508 \@ifundefined{Pg@@endquestions}%
2510 {\ifnum \thepage < \PgInfo@get{@endquestions}%
2522 %---------------------------------------------------------------------
2524 % ***************************
2525 % ** QUESTION ENVIRONMENTS **
2526 % ***************************
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.
2540 %--------------------------------------------------------------------
2541 % These are the commands for dealing with hlfcntr's, i.e., the things
2542 % used to count points.
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''.
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}
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
2564 % Examples of valid values:
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
2579 % A scratch hlfcntr:
2580 \newcounter{tmp@hlfcntr}
2581 \newif\iftmp@hlfcntr@half
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$}$%
2588 \newcommand*\useslantedhalf{\let\half\slanted@half}
2589 \newcommand*\usehorizontalhalf{\let\half\horiz@half}
2590 \newcommand*\half{\slanted@half}
2593 \newcommand*\set@hlfcntr[2]{%
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.
2600 \expandafter\global\csname #1@halftrue\endcsname
2602 % We insert a `0' in case there are no digits present:
2603 \setcounter{#1}{0#2}\relax
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
2613 \expandafter\global\csname #1@halffalse\endcsname
2617 \newcommand*\addto@hlfcntr[2]{%
2618 % We add the valueandhalf #2 to hlfcntr #1
2620 \def\half{\add@half{#1}}%
2621 % We insert a `0' in case there are no digits present:
2622 \addtocounter{#1}{0#2}\relax
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
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
2640 \expandafter\global\csname #1@halftrue\endcsname
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}%
2653 \ifnum \value{ifpos@cntr} > 0
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}%
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}%
2674 \newcommand*\prtaux@halforzero[1]{%
2675 \csname if#1@half\endcsname
2681 \newcommand*\prtaux@halforblank[1]{%
2682 \csname if#1@half\endcsname
2686 %--------------------------------------------------------------------
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
2695 \newcounter{question}
2697 \newcounter{subpart}
2698 \newcounter{subsubpart}
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}
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}
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}
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}%
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
2745 % \pagepoint@commands holds the commands to manage the counting of the
2746 % number of points defined on each page.
2747 \newtoks\pagepoint@commands
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
2754 % We'll use \greeknum to number subsubparts
2755 \def\greeknum#1{\expandafter\lc@greek\csname c@#1\endcsname}
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
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
2773 \def\prepend@toklist#1#2{%
2774 \edef\do@it{\noexpand#1={\the#2\the#1}}%
2778 \def\append@toklist#1#2{%
2779 \edef\do@it{\noexpand#1={\the#1\the#2}}%
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 ...
2800 \global\@qformattrue
2801 \gdef\@questionformat{#1}%
2804 \newcommand\noqformat{%
2805 \global\@qformatfalse
2808 \newcommand\thepoints{%
2810 \@points \@pointname
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
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}%
2834 \cover@question@error
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.)
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}%
2853 % OK; it's defined. See if it's changed:
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
2862 \global\@pointschangedtrue
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
2895 \global\expandafter\edef
2896 \csname Contin@\theCurr@Page\endcsname{\relax}%
2898 \the\pagepoint@commands
2899 \global \pageinfo@commands={}%
2900 }% pageinfo@commands
2902 % Remove any skips at the end of the previous paragraph
2903 % that might cause a blank line, and then end that paragraph:
2910 \cover@question@error
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.
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
2926 \global\expandafter\edef\csname
2927 Contin@\theCurr@Page\endcsname{\arabic{question}}%
2929 \the\pagepoint@commands
2930 \global \pageinfo@commands={}%
2932 \append@toklist \pageinfo@commands \temp@toks
2934 % Remove any skips at the end of the previous paragraph
2935 % that might cause a blank line, and then end that paragraph:
2942 \cover@question@error
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.
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
2958 \global\expandafter\edef\csname
2959 Contin@\theCurr@Page\endcsname{\arabic{question}}%
2961 \the\pagepoint@commands
2962 \global \pageinfo@commands={}%
2964 \append@toklist \pageinfo@commands \temp@toks
2966 % Remove any skips at the end of the previous paragraph
2967 % that might cause a blank line, and then end that paragraph:
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
2984 % Write the number of points of the final question
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}%
2997 % OK; it's defined. See if it's changed:
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
3006 \global\@pointschangedtrue
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{%
3019 \makebox[\hsize][s]{\@questionformat}\hskip-\labelsep
3024 \newcommand\questionlabel{\thequestion.}
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).
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.)
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
3056 \cover@question@error
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.
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}}%
3072 \the\pagepoint@commands
3073 \global \pageinfo@commands={}%
3075 \append@toklist \pageinfo@commands \temp@toks
3077 % Remove any skips at the end of the previous paragraph
3078 % that might cause a blank line, and then end that paragraph:
3085 \usecounter{partno}\def\makelabel##1{\hss\llap{##1}}%
3086 \settowidth{\leftmargin}{(m)\hskip\labelsep}%
3087 \labelwidth\leftmargin\advance\labelwidth-\labelsep
3091 }% newenvironment{parts}
3093 \newcommand\partlabel{(\thepartno)}
3094 \def\thepartno{\alph{partno}}
3096 \newenvironment{subparts}{%
3097 \def\@queslevel{subpart}%
3098 \list{\subpartlabel}%
3100 \usecounter{subpart}\def\makelabel##1{\hss\llap{##1}}%
3101 \settowidth{\leftmargin}{vii.\hskip\labelsep}%
3102 \labelwidth\leftmargin\advance\labelwidth-\labelsep
3108 \newcommand\subpartlabel{\thesubpart.}
3109 \def\thesubpart{\roman{subpart}}
3111 \newenvironment{subsubparts}{%
3112 \def\@queslevel{subsubpart}%
3113 \list{\subsubpartlabel}%
3115 \usecounter{subsubpart}\def\makelabel##1{\hss\llap{##1}}%
3116 \settowidth{\leftmargin}{($\psi$)\hskip\labelsep}%
3117 \labelwidth\leftmargin\advance\labelwidth-\labelsep
3123 \newcommand\subsubpartlabel{\thesubsubpart)}
3124 \def\thesubsubpart{\greeknum{subsubpart}}
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
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}%
3146 % OK; it's defined. See if it's changed:
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
3155 \global\@pointschangedtrue
3160 % The following is a macro because \theCurr@Page and
3161 % \thepageof@pagepoints might differ by more than 1:
3162 \increment@pageof@pagepoints
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}%
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}%
3182 % OK; it's defined. See if it's changed:
3184 \set@hlfcntr{tmp@hlfcntr}{\csname pointsonpage@\romannumeral
3185 \csname c@pageof@pagepoints\endcsname\endcsname}%
3186 \edef\othpt@check{\prtaux@hlfcntr{tmp@hlfcntr}}%
3188 \ifx \pt@check \othpt@check
3191 \global\@pointschangedtrue
3195 \let\next@incr@pageof = \increment@pageof@pagepoints
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
3214 \def\@checkqueslevel#1{%
3217 \ifx\@temp\@queslevel
3218 % Everything's fine; do nothing.
3221 I found a #1 where I expected to find a
3222 \@queslevel\MessageBreak
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
3233 \def\@doitem{\@ifnextchar[{\@readpoints}%
3234 {\item@points@pageinfo}%
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:
3242 \global \@placepointstrue
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
3250 \addto@hlfcntr{latest@points}{\@points}%
3252 \item@points@pageinfo
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.
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.
3272 \newcounter{lbl@cntr}
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
3281 \expandafter\label\expandafter{\thelbl@cntr @@exam@lbl}%
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
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.
3307 \def\item@points@pageinfo{%
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.
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).
3325 \ifx\ques@ref\@queslevel
3326 \global \@placepointsfalse
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,
3341 \global \@placepointsfalse
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
3347 % Also: It's important to do this *after* the \item command above,
3348 % since the \item command discards the previous contents of
3350 \edef\append@everypar{\noexpand\everypar={\the\everypar
3351 \noexpand\the \noexpand\pageinfo@commands
3352 \noexpand\the \noexpand\point@toks}}%
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.)
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
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).
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
3398 % \point@block consists of \point@string surrounded by either
3399 % parentheses, brackets, or an fbox.
3401 % \point@string is either \@points\@pointname or
3402 % \@points\@marginpointname.
3404 \if@pointsinleftmargin
3405 \def\point@string{\@points\@marginpointname}%
3408 \hskip\@totalleftmargin
3409 \hskip\marginpointssep
3411 \global \point@toks={}%
3414 \if@pointsinrightmargin
3415 \def\point@string{\@points\@marginpointname}%
3417 \rlap{\hskip-\@totalleftmargin
3420 \hskip-\rightpointsmargin
3421 \llap{\point@block}%
3423 \global \point@toks={}%
3426 % The points just go after the question number:
3427 \def\point@string{\@points\@pointname}%
3431 \global \point@toks={}%
3438 \def\setup@point@block{%
3440 \def\point@block{\fbox{\point@string}}%
3443 \def\point@block{[\point@string]}%
3445 % plain old parentheses:
3446 \def\point@block{(\point@string)}%
3452 \def\point@string{\@points\@marginpointname}%
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}%
3463 % The following is the default definition.
3464 % It will be redefined if the user givea a \totalformat command.
3465 \def\setup@total@block{%
3467 Total for Question \thequestion: \totalpoints\@marginpointname
3471 \def\totalformat#1{%
3472 \def\setup@total@block{\def\total@block{#1}}%
3474 % The following is for use in the argument to a \totalformat command:
3475 \def\totalpoints{\pointsofquestion{\arabic{question}}}
3477 \def\droptotalpoints{%
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}%
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
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}
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}
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
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}
3547 \newif\if@bracketedpoints
3548 \def\bracketedpoints{\global\@bracketedpointstrue \global\@boxedpointsfalse}
3549 \def\nobracketedpoints{\global\@bracketedpointsfalse \global\@boxedpointsfalse}
3550 \@bracketedpointsfalse
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
3565 \pointname{ \points}
3567 \newcommand\point@sing{point}
3568 \newcommand\point@plur{points}
3569 \newcommand\pointpoints[2]{%
3570 \renewcommand\point@sing{#1}%
3571 \renewcommand\point@plur{#2}%
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
3585 % 0 points, one half point, 1 point, 1 and a half points, etc.:
3586 \newcommand\points{%
3589 \edef\pt@string{\@points}%
3590 \ifthenelse{\equal{\pt@string}{1} \or \equal{\pt@string}{\half}}
3591 {\point@sing}{\point@plur}%
3594 %\newcommand\points{%
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}%
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
3610 %\pointname{ \ifthenelse{\@points = 1}{point}{points}}
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}}
3619 % \@marginpointname is used in place of \@pointname if any of
3620 % \@pointsinmargin, \@pointsinrightmargin, and \@pointsdropped are
3622 \def\marginpointname#1{\gdef\@marginpointname{#1}}
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.
3637 \newif\if@printtotalpoints
3638 \def\addpoints{\global\@addpointstrue\global\@printtotalpointstrue}
3639 \def\noaddpoints{\global\@addpointsfalse}
3641 \@printtotalpointsfalse
3643 %--------------------------------------------------------------------
3644 % choices (for multiple choice)
3647 \renewcommand\thechoice{\Alph{choice}}
3648 \newcommand\choicelabel{\thechoice.}
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}%
3657 \labelwidth\leftmargin\advance\labelwidth-\labelsep
3664 \newenvironment{oneparchoices}%
3666 \setcounter{choice}{0}%
3668 \refstepcounter{choice}%
3669 \ifnum\value{choice}>1
3670 \penalty -50\hskip 1em plus 1em\relax
3672 \choicelabel\nobreak\enskip
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
3683 %--------------------------------------------------------------------
3684 % Answer Lines (for short answer questions)
3686 % Note: \ques@ref is also used in \item@points@pageinfo
3688 \def\ques@ref{question}
3690 \def\subpart@ref{subpart}
3691 \def\subsubpart@ref{subsubpart}
3693 \newlength\answerlinelength
3694 \newlength\answerskip
3695 \setlength\answerlinelength{1in}
3696 \setlength\answerskip{2ex}
3699 \ifx\@queslevel\ques@ref
3700 \let\ans@l=\questionlabel
3702 \ifx\@queslevel\part@ref
3703 \let\ans@l=\partlabel
3705 \ifx\@queslevel\subpart@ref
3706 \let\ans@l=\subpartlabel
3708 \ifx\@queslevel\subsubpart@ref
3709 \let\ans@l=\subsubpartlabel
3711 % Oops; no question level defined.
3712 % We must be outide of the questions environment.
3713 % Just leave out the label, I guess:
3719 \par \nobreak \vskip \answerskip
3720 \hfill \ans@l~\hbox to \answerlinelength{\hrulefill}%
3724 %--------------------------------------------------------------------
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.
3734 % The distance between the lines is \linefillheight, whose default value
3735 % is set with the command
3737 % \setlength\linefillheight{.25in}
3739 % This value can be changed by giving a new \setlength command.
3741 % The thickness of the lines is \linefillthickness, whose default value
3742 % is set with the command
3744 % \setlength\linefillthickness{.2pt}
3746 % This value can be changed by giving a new \setlength command.
3749 \newlength\linefillheight
3750 \newlength\linefillthickness
3751 \setlength\linefillheight{.25in}
3752 \setlength\linefillthickness{0.1pt}
3754 \newcommand\linefill{\leavevmode
3755 \leaders\hrule height \linefillthickness \hfill\kern\z@}
3758 \def\fillwithlines#1{%
3765 \setbox0=\hbox to \hsize{\hskip \@totalleftmargin
3766 \vrule height \linefillheight depth \z@ width \z@
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{}%
3776 %--------------------------------------------------------------------
3777 % \uplevel and \fullwidth:
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.}
3784 % \fullwidth is similar, but uses the full page of text on the page.
3786 \long\def\uplevel#1{%
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
3802 \long\def\fullwidth#1{%
3805 \leftskip=0pt \rightskip=0pt
3806 \advance\linewidth\@totalleftmargin
3807 \@totalleftmargin=0pt
3814 %--------------------------------------------------------------------
3815 %--------------------------------------------------------------------
3817 % ********************
3818 % ** GRADING TABLES **
3819 % ********************
3823 \newcounter{@iterator}
3824 \newlength\@cellwidth
3826 \def\cellwidth#1{\@cellwidth=#1}
3827 \def\gradetablestretch#1{\def\@gtblstretch{#1}}
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}}
3840 \def\vpgword#1{\def\@vpgword{#1}}
3841 \def\hpgword#1{\def\@hpgword{#1}}
3845 \gradetablestretch{1.5}
3853 % For tables indexed by question number:
3857 % For tables indexed by page number:
3863 % The only command here accessible to the user is \gradetable.
3864 % The possibilities are
3866 % \gradetable[v][questions]
3867 % \gradetable[v][pages]
3868 % \gradetable[h][questions]
3869 % \gradetable[h][pages]
3871 % If one or both optional arguments are omitted, the defaults are `[v]'
3872 % and `[questions]'.
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]}%
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]}%
3886 \def\ii@gtable#1[#2]{%
3888 \@ifundefined{exam@numpoints}%
3889 {\ClassWarning{exam}%
3891 You must run LaTeX again to produce the grade table.
3894 \fbox{Run \LaTeX{} again to produce the table}%
3896 {\do@gtable{#1}{#2}}%
3899 You must give the command \protect\addpoints\MessageBreak
3900 \space\space in order to use the command \protect\gradetable
3903 If you don't give the command \protect\addpoints\MessageBreak
3904 \space\space then we're not keeping track of point values.
3909 \def\@questionsref{questions}
3910 \def\@pagesref{pages}
3911 \def\do@gtable#1#2{%
3912 \begingroup % avoid trouble from using \@temp
3914 \ifx\@temp\@questionsref
3915 \@grdtblquestions{#1}%
3917 \ifx\@temp\@pagesref
3921 The second optional argument to \protect\gradetable \MessageBreak
3922 \space \space must be either `questions' or `pages'\MessageBreak
3924 Grade tables can be indexed by questions or pages;\MessageBreak
3925 \space\space for others, you're on your own.\MessageBreak
3927 \fbox{Error: Grade table: Invalid second optional argument `#1'.}%
3933 %--------------------------------------------------------------------
3934 %--------------------------------------------------------------------
3935 % Grading tables indexed by question numbers:
3937 \def\@grdtblquestions#1{%
3945 The first optional argument to \protect\gradetable \MessageBreak
3946 \space \space must be either `h' or `v'\MessageBreak
3948 Grade tables can be either horizontal or vertical;\MessageBreak
3949 \space\space no diagonals allowed.\MessageBreak
3951 \fbox{Error: Grade table: Invalid first optional argument `#1'.}%
3956 %--------------------------------------------------------------------
3957 % Vertical, indexed by question numbers:
3959 \def\@vgrdtblquestions{%
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|}
3967 {\@vqword}& {\@vpword}& {\@vsword}\\
3969 \setcounter{question}{0}\do@vloop
3970 {\@vtword}& \numpoints&\hbox to \@cellwidth{\hfill}\\
3973 % Restore the saved value of question:
3974 \setcounter{question}{\arabic{@iterator}}%
3978 \addtocounter{question}{1}%
3979 \thequestion & \pointsofquestion{\arabic{question}}&\\
3981 \ifnum \arabic{question} < \numquestions\relax
3982 \let\next@vloop=\do@vloop
3984 \let\next@vloop=\relax
3989 %--------------------------------------------------------------------
3990 % Horizontal, indexed by question numbers:
3992 \def\@hgrdtblquestions{%
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|}
4000 {\@hqword}& \setcounter{question}{0}\do@qnumloop
4003 {\@hpword}& \setcounter{question}{0}\do@ptloop
4006 {\@hsword}& \setcounter{question}{0}\do@sloop
4010 % Restore the saved value of question:
4011 \setcounter{question}{\arabic{@iterator}}%
4015 \addtocounter{question}{1}%
4017 \ifnum \arabic{question} < \numquestions\relax
4018 \let\next@qnloop=\do@qnumloop
4020 \let\next@qnloop=\relax
4025 \addtocounter{question}{1}%
4026 \pointsofquestion{\arabic{question}}&
4027 \ifnum \arabic{question} < \numquestions\relax
4028 \let\next@ptloop=\do@ptloop
4030 \let\next@ptloop=\relax
4035 \addtocounter{question}{1}%
4036 \hbox to \@cellwidth{\hfill}&
4037 \ifnum \arabic{question} < \numquestions\relax
4038 \let\next@sloop=\do@sloop
4040 \let\next@sloop=\relax
4046 %--------------------------------------------------------------------
4047 %--------------------------------------------------------------------
4048 % Grading tables indexed by page numbers:
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.
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}%
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}%
4080 \def\@whchtblpgs#1{%
4088 The first optional argument to \protect\gradetable \MessageBreak
4089 \space \space must be either `h' or `v'\MessageBreak
4091 Grade tables can be either horizontal or vertical;\MessageBreak
4092 \space\space no diagonals allowed.\MessageBreak
4094 \fbox{Error: Grade table: Invalid first optional argument `#1'.}%
4099 %--------------------------------------------------------------------
4100 % Vertical, indexed by pages:
4102 \def\@vgrdtblpages{%
4104 \renewcommand\arraystretch{\@gtblstretch}%
4105 \begin{tabular}{|c|c|c|}
4107 {\@vpgword}& {\@vpword}& {\@vsword}\\
4109 \setcounter{@iterator}{0}\pg@vloop
4110 {\@vtword}& \numpoints&\hbox to \@cellwidth{\hfill}\\
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}%
4124 \ifnum \the@iterator < \lastpage@withpoints\relax
4125 \let\next@pg@vloop=\pg@vloop
4127 \let\next@pg@vloop=\relax
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}&\\
4140 %--------------------------------------------------------------------
4141 % Horizontal, indexed by pages:
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}%
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}%
4160 \ifnum \the@iterator < \lastpage@withpoints\relax
4161 \let\next@docount=\docount@pgswpts
4163 \let\next@docount=\relax
4169 \def\@hgrdtblpages{%
4171 \renewcommand\arraystretch{\@gtblstretch}%
4173 \begin{tabular}{|l|*{\thenumpgs@withpts}{c|}c|}
4175 {\@hpgword}& \setcounter{@iterator}{0}\do@pgnumloop
4178 {\@hpword}& \setcounter{@iterator}{0}\do@pgptloop
4181 {\@hsword}& \setcounter{@iterator}{0}\do@pgsloop
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}%
4197 \ifnum \the@iterator < \lastpage@withpoints\relax
4198 \let\next@pgnumloop=\do@pgnumloop
4200 \let\next@pgnumloop=\relax
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}%
4217 \ifnum \the@iterator < \lastpage@withpoints\relax
4218 \let\next@pgptloop=\do@pgptloop
4220 \let\next@pgptloop=\relax
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
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}%
4240 \ifnum \the@iterator < \lastpage@withpoints\relax
4241 \let\next@pgsloop=\do@pgsloop
4243 \let\next@pgsloop=\relax
4248 \hbox to \@cellwidth{\hfill}&
4252 %--------------------------------------------------------------------
4253 %--------------------------------------------------------------------
4255 % ***************************
4256 % ** SOLUTION ENVIRONMENTS **
4257 % ***************************
4261 % If the documentclass options include ``answers'', then the command
4262 % \@printanswerstrue is given at the beginning of the run.
4264 % If the documentclass options include ``noanswers'', then the command
4265 % \@printanswersfalse is given at the beginning of the run.
4267 \def\printanswers{\@printanswerstrue}
4268 \def\noprintanswers{\@printanswersfalse}
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]%
4277 \begin{TheSolution}%
4281 \setbox\z@\vbox\bgroup
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]%
4297 \begin{TheSolution}%
4301 \setbox\z@\vbox\bgroup
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
4319 % Of course, the user can change TheSolution with a \renewenvironment
4321 \newcommand{\solutiontitle}{\noindent\textbf{Solution:}\enspace}
4322 \newenvironment{TheSolution}%
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:
4331 % Do nothing; we'll use the default \FrameCommand
4333 \def\FrameCommand{\colorbox{SolutionColor}}%
4335 \MakeFramed{\advance\hsize-\width}%
4344 \newif\if@framedsolutions
4345 \@framedsolutionstrue
4347 \def\framedsolutions{\@framedsolutionstrue}
4348 \def\shadedsolutions{%
4349 \@ifundefined{definecolor}
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
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
4363 \definecolor{SolutionColor}{gray}{0.8}
4364 \@framedsolutionsfalse
4368 %--------------------------------------------------------------------
4369 %--------------------------------------------------------------------
4371 % The following stuff is lifted from:
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.
4378 % The modifications I made are marked with ``psh'' in a comment:
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)
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.
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}...).
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
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.
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.
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
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.
4425 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4427 %psh: Commented out \ProvidesPackage:
4428 %\ProvidesPackage{framed}[2003/07/21 v 0.8a:
4429 % framed or shaded text with page breaks]
4431 %psh: Created \saved@totalleftmargin and \@sollistdepth:
4432 \newdimen\saved@totalleftmargin
4433 \newcount\@sollistdepth
4435 \newenvironment{framed}% using default \FrameCommand
4436 {\MakeFramed {\advance\hsize-\width \FrameRestore}}%
4439 \newenvironment{shaded}{%
4440 \def\FrameCommand{\colorbox{shadecolor}}%
4441 \MakeFramed {\FrameRestore}}%
4444 \newenvironment{leftbar}{%
4445 \def\FrameCommand{\vrule width 3pt \hspace{10pt}}%
4446 \MakeFramed {\advance\hsize-\width \FrameRestore}}%
4449 \chardef\FrameRestore=\catcode`\| % for debug
4450 \catcode`\|=\catcode`\% % (debug: insert space after backslash)
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}}}%
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
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@
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
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@
4481 \addvspace{\topsep}%
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. }%
4489 %psh: Added commands:
4490 \advance\hsize-\@totalleftmargin
4491 \saved@totalleftmargin=\@totalleftmargin
4492 \@totalleftmargin=0pt
4494 \let\@listdepth=\@sollistdepth
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:
4505 \def\endMakeFramed{\par
4506 \kern\z@ \penalty-100 % put depth into height
4508 \begingroup \put@frame \endgroup
4509 %psh: Added one line:
4510 \@totalleftmargin=\saved@totalleftmargin
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.)
4517 \def\put@frame{\relax
4518 \ifdim\pagegoal=\maxdimen \pagegoal\vsize \fi
4519 | \message{=============== Entering putframe ====================^^J
4520 | \pagegoal=\the\pagegoal, \pagetotal=\the\pagetotal. }%
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
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
4554 \advance\dimen@\topskip
4555 \expandafter\endgroup
4556 \ifdim\dimen@>\pagegoal
4557 | \message{Frame is big -- Use up the full column. }%
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@. }%
4567 \else % use natural size
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)
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@. }%
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@}}%
4594 | \message{Zero width means likely blank. Don't frame it (guess)}%
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
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
4617 \edef\zero@glue{\the\z@skip}
4619 \catcode`\|=\FrameRestore
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}{}
4626 % Height of frame above first baseline when frame starts a page:
4627 \providecommand\FrameHeightAdjust{6pt}
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
4634 \let\if@nobreak\iffalse
4635 \let\if@noskipsec\iffalse
4638 \let\'\@acci\let\`\@accii\let\=\@acciii
4639 % \parindent\z@ \parskip\z@skip Definitely omit!
4642 % \@totalleftmargin\z@
4643 % \leftskip\z@skip \rightskip\z@skip \@rightskip\z@skip
4644 % \parfillskip\@flushglue \lineskip\normallineskip
4645 % \baselineskip\normalbaselineskip
4650 % Compatibility with previous versions (temporary!):
4651 \let\fram@d=\MakeFramed \let\endfram@d=\endMakeFramed
4653 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
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
4660 %--------------------------------------------------------------------
4661 %--------------------------------------------------------------------
4664 %---------------------------------------------------------------------
4665 %---------------------------------------------------------------------
4666 %---------------------------------------------------------------------
4667 %---------------------------------------------------------------------
4668 %---------------------------------------------------------------------