summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/tex/latex/exam
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2011-05-23 22:02:31 +0000
committerKarl Berry <karl@freefriends.org>2011-05-23 22:02:31 +0000
commit8186542aa5c83c77e3aabe6d3cea54f249423472 (patch)
tree9e1fd1b366ebe0417ada420160c1c0d60b3aa0e5 /Master/texmf-dist/tex/latex/exam
parent34d7e56054b6d2467c604600a95907f198bfd7ee (diff)
exam 2.4 (23may11)
git-svn-id: svn://tug.org/texlive/trunk@22585 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/tex/latex/exam')
-rw-r--r--Master/texmf-dist/tex/latex/exam/exam.cls2674
1 files changed, 1766 insertions, 908 deletions
diff --git a/Master/texmf-dist/tex/latex/exam/exam.cls b/Master/texmf-dist/tex/latex/exam/exam.cls
index ea3516cbb46..1f4fc6358fc 100644
--- a/Master/texmf-dist/tex/latex/exam/exam.cls
+++ b/Master/texmf-dist/tex/latex/exam/exam.cls
@@ -18,7 +18,7 @@
% This work consists of the files exam.cls and examdoc.tex.
-% The user documentation for exam.cls is in the file examdoc.tex.
+% The user's guide for exam.cls is in the file examdoc.tex.
%%% Philip Hirschhorn
@@ -31,8 +31,8 @@
% from my web page: http://www-math.mit.edu/~psh/
-\def\fileversion{2.3}
-\def\filedate{2008/07/19}
+\def\fileversion{2.4}
+\def\filedate{2011/05/22}
%---------------------------------------------------------------------
%---------------------------------------------------------------------
%
@@ -82,681 +82,460 @@
%
%--------------------------------------------------------------------
%--------------------------------------------------------------------
-% Changelog since version 2.2:
+% Changelog since version 2.3:
%--------------------------------------------------------------------
-% Version 2.3, 2008/07/16:
+% Version 2.4, 2011/05/22:
%
-% Minor typographic corrections to comments.
+% No longer betatest.
%
%--------------------------------------------------------------------
-% Version 2.222$\beta$, 2008/07/13:
+% Version 2.321$\beta$, 2011/05/15:
%
-% Corrected a typo in the error message displayed when
-% \shadedsolutions is used without having said \usepackage{color}.
+% New environments: EnvUplevel and EnvFullwidth
%
-%--------------------------------------------------------------------
-% Version 2.221$\beta$, 2008/07/03:
+% The EnvUplevel environment is similar to the command \uplevel,
+% except that \uplevel is a command taking one argument. The
+% EnvUplevel environment has the advantage that you can include
+% verbatim material (using, e.g., the \verb command) in the
+% environment. (You can't include verbatim material in the argument
+% of an \uplevel command.)
%
-% \themarginpoints used to expand to
-% \@points \@marginpointname
-% whether the points were bonus or non-bonus. We fixed that, so that
-% it expands to either
-% \@points \@marginbonuspointname
-% or
-% \@points \@marginpointname
-% depending on whether or not the points are bonus points.
+% The EnvFullwidth environment is similar to the command \fullwidth,
+% except that \fullwidth is a command taking one argument. The
+% EnvFullwidth environment has the advantage that you can include
+% verbatim material (using, e.g., the \verb command) in the
+% environment. (You can't include verbatim material in the argument
+% of a \fullwidth command.)
%
%--------------------------------------------------------------------
-% Version 2.220$\beta$, 2008/05/24:
+% Version 2.320$\beta$, 2011/04/16:
%
-% New command: \fillwithdottedlines
-% New environment: solutionordottedlines
+% New document class options: cancelspace
+% nocancelspace
+% New commands: \cancelspace
+% \nocancelspace
%
+% Using the document class option cancelspace is equivalent to giving
+% the command \cancelspace at the beginning of the file. The default is
+% \nocancelspace. Thus, the document class option nocancelspace has no
+% effect, but is there to avoid errors if a user is confused.
%
-% \fillwithdottedlines is similar to \fillwithlines except that it
-% inserts dotted lines (created by \dotfill) instead of solid lines.
+% If the user uses the document class option cancelspace and if
+% solutions are not being printed, then any space that would be added by
+% an optional argument to the solution, solutionorbox, solutionorlines,
+% or solutionordottedlines environments will not be added.
%
-% \fillwithdottedlines takes one argument, which is either a length or
-% \fill, and it fills that much vertical space with dotted horizontal
-% lines that run the length of the current line. That is, they extend
-% from the current left margin (which depends on whether we're in a
-% question, part, subpart, or subsubpart) to the right margin.
+% If solutions are being printed (because the user used the document
+% class option answers or gave the command \printanswers), then the
+% option cancelspace (and the command \cancelspace) will have no
+% effect.
%
-% The distance between the lines is \dottedlinefillheight, whose
-% default value is set with the command
+%--------------------------------------------------------------------
+% Version 2.319$\beta$, 2011/04/11:
%
-% \setlength\dottedlinefillheight{.25in}
+% We fixed an obscure bug, in which if the user gives a \qformat
+% command, in which case they shouldn't want to give a \droppoints
+% command, but they *do* give a \droppoints command, there is an
+% error (\padded@point@block undefined).
%
-% This value can be changed by giving a new \setlength command.
+%--------------------------------------------------------------------
+% Version 2.318$\beta$, 2011/04/05:
%
-% The solutionordottedlines environment is almost identical to the
-% solutionorlines environment, except that when solutions are not
-% being printed and an optional argument appears specifying an amount
-% of space to be left for answers, that space is filled with dotted
-% lines (created by \dotfill), rather than filled with solid lines (as
-% it is by the solutionorlines environment).
+% \qformat and \bonusqformat are now totally independent.
+% That is: \qformat doesn't affect bonus questions, and \noqformat
+% no longer cancels \bonusqformat.
%
-%--------------------------------------------------------------------
-% Version 2.219$\beta$, 2007/11/24:
-%
-% There can now be partial grade tables and point tables, either bonus
-% or non-bonus.
-%
-% New commands:
-%
-% \partialgradetable
-% \partialbonusgradetable
-% \partialpointtable
-% \partialbonuspointtable
-% \begingradingrange
-% \endgradingrange
-%
-% The user defines a grading range by saying
-%
-% \begingradingrange{whatever}
-%
-% to start the range and
-%
-% \endgradingrange{whatever}
-%
-% to end the range (where ``whatever'' is a name chosen by the user).
-% To create the table, the user says, e.g.,
-%
-% \partialgradetable{whatever}[v][questions]
-%
-% That is, each of \partialgradetable, \partialbonusgradetable,
-% \partialpointtable, and \partialbonuspointtable takes
-%
-% one required argument (the name of the grading range) and
-%
-% two optional arguments, the first being either ``[v]'' or ``[h]'',
-% the second being either ``[questions]'' or ``[pages]''.
-%
-% If either or both of the optional arguments are omitted, [questions]
-% and [v] will be used.
-%
-% If the table is indexed by questions, then it will include all
-% questions following the \begingradingrange{whatever} and preceding the
-% \endgradingrange{whatever}.
-%
-% If the table is indexed by pages, then it will include all pages with
-% points starting with the page containing the
-% \begingradingrange{whatever} and ending with the page containing the
-% \endgradingrange{whatever}.
-%
-% Otherwise,
-%
-% \partialgradetable is similar to \gradetable
-% \partialbonsugradetable is similar to \bonusgradetable
-% \partialpointtable is similar to \pointtable
-% \partialbonuspointtable is similar to \bonuspointtable
-%
-%--------------------------------------------------------------------
-% Version 2.218$\beta$, 2007/10/31:
-%
-% Instead of appending
-% \the \pageinfo@commands \the \point@toks
-% to \everypar, we insert them into the box \@labels. This corrects the
-% problem that arose when a question (or part, etc.) begins with a list
-% environment (including verbatim, flushleft, center, flushright, and
-% possibly others that are implemented as trivlist environments). The
-% \item command in those environments throws away the previous contents
-% of \everypar, and so the tokens
-% \the \pageinfo@commands \the \point@toks
-% didn't get inserted where we expected. List environments *do*
-% preserve the contents of the box \@labels, though.
-
-% This version of exam.cls is not completely backward compatible with
-% older versions. The changes only affect documents in which the user
-% was doing something that probably should not have been done with the
-% older versions, though. This new version does something useful in
-% situations in which older versions did something not very useful:
-
-% This change introduces a change in behavior for documents in which a
-% question with points begins with a parts environment, so that the
-% points for the first part (if any) would appear on the same line as
-% the points for the question. In earlier versions of exam.cls, the
-% points for the question would not be printed if there are points for
-% the part that begins on the same line. In this version of exam.cls,
-% all points will be printed. If they're both printed in the left
-% margin, or both in the right margin, then they'll be printed directly
-% on top of one another, which is not what you want. (You can use
-% \pointsinmargin, \pointsinrightmargin, and \nopointsinmargin to print
-% them in different places.) If points are being printed right in the
-% text (i.e., \nopointsinmargin), then the points for the question will
-% be printed *before* the label (a) for the first part is printed.
-
-% The behavior of this new version of exam.cls seems clearly preferable
-% to the old behavior, but it is a change!
+% New command: \nobonusqformat
+% \nobonusqformat does for \bonusqformat what \noqformat does for
+% \qformat.
%
%--------------------------------------------------------------------
-% Version 2.217$\beta$, 2007/10/22:
-%
-% We changed things so that we're now compatible with calc.sty
+% Version 2.317$\beta$, 2011/04/02:
%
-% calc.sty redefines \setcounter and \addtocounter in a way that
-% conflicts with a trick we were using to deal with \half points.
+% We changed the definition of \numcoverpages so that on the first run
+% of latex (when \exam@lastcoverpage isn't yet defined), \numcoverpages
+% will expand to
+% 0\mbox{\normalfont\bf ??}
+% instead of
+% \mbox{\normalfont\bf ??}
+% so that the construction \romannumeral\numcoverpages will not generate
+% an error on the first run of latex.
%
-% We replaced one \setcounter command with
+% We also made changes and corrections to comments.
%
-% \global\csname c@#1\endcsname 0#2\relax
-%
-% and one \addtocounter command with
+%--------------------------------------------------------------------
+% Version 2.316$\beta$, 2010/12/22:
%
-% \global\advance\csname c@#1\endcsname 0#2\relax
%
-%--------------------------------------------------------------------
-% Version 2.216$\beta$, 2007/08/27:
-%
-% The command \answerline now takes an optional argument. If the
-% optional argument appears, then when \printanswers is true the
-% argument will be printed on the answer line. When \printanswers is
-% false, the optional argument is ignored.
-%
-% When the argument is printed, it is printed with
-% \CorrectChoiceEmphasis and it is a distance of \answerclearance above
-% the line. The default value of \answerclearance is set with the
-% command
-%
-% \setlength\answerclearance{0.2ex}
-%
-% and it can be changed with a \setlength command.
-%
-% The optional argument is centered on the answer line unless it is too
-% long, in which case it extends to the right of the answer line.
-%
-%--------------------------------------------------------------------
-% Version 2.215$\beta$, 2007/08/24:
-%
% New commands:
-%
-% \pointtable
-% \bonuspointtable
-%
-% Both of these take up to two optional arguments:
-%
-% The first can be either [v] or [h].
-% The second can be either [questions] or [pages].
-%
-% These commands are similar to the commands
-%
-% \gradetable
-% \bonusgradetable
-%
-% except that the new commands print only two columns (or rows),
-% omitting the column (or row) for the score.
-%
+%
+% \pointsinrange{rangename}
+% \bonuspointsinrange{rangename}
+%
+% If `rangename' is the name of a grading range defined using
+% \begingradingrange{rangename} and \endgradingrange{rangename}, then
+% \pointsinrange{rangename} expands to the number of points in that
+% grading range and \bonuspointsinrange{rangename} expands to the number
+% of bonus points in that grading range.
+
+% We also changed the checkboxes and oneparcheckboxes environments so
+% that, when solutions are being printed, a \CorrectChoice will be
+% printed with \CorrectChoiceEmphasis (along with the \checkedchar
+% that marks the \CorrectChoice). This brings the behavior in line
+% with that of the choices and oneparchoices environments.
+%
%--------------------------------------------------------------------
-% Version 2.214$\beta$, 2007/07/19:
+% Version 2.315$\beta$, 2010/12/21:
%
% New commands:
%
-% \questionshook
-% \partshook
-% \subpartshook
-% \subsubpartshook
-% \choiceshook
+% \settabletotalpoints
+% \settabletotalbonuspoints
%
-% These are for advanced users who want to customize the list
-% parameters (\topsep, \partopsep, \itemsep, \parsep, etc.) for the
-% lists that these environments create. They are all defined to be
-% empty, but the user can change them using \renewcommand.
+% Each of those takes one argument. After giving the command
+% \settabletotalpoints{numpoints}, any grade or point table (partial
+% or full) will list the total points as numpoints instead of the
+% actual total number of points in the table.
%
-%--------------------------------------------------------------------
-% Version 2.213$\beta$, 2006/11/27:
-%
-% New documentclass option: addpoints
-% Using this option is equivalent to giving the command
-% \addpoints
-% at the beginning of the document.
-%
-% New commands:
-%
-% \bonusquestion
-% \bonustitledquestion
-% \bonuspart
-% \bonussubpart
-% \bonussubsubpart
-%
-% \bonuspointsofquestion
-% \bonuspointsonpage
-%
-% \numbonuspoints
-%
-% \bonuspointpoints
-% \bonuspointformat
-% \thebonuspoints
-% \bonuspoints
-% \bonuspointname
-% \marginbonuspointname
-%
-% \bonusgradetable
-%
-% \bhqword
-% \bhpword
-% \bhsword
-% \bhtword
-% \bvqword
-% \bvpword
-% \bvsword
-% \bvtword
-%
-% \bvpgword
-% \bhpgword
-%
-%
-% The commands
-%
-% \bonusquestion
-% \bonustitledquestion
-% \bonuspart
-% \bonussubpart
-% \bonussubsubpart
-%
-% are the same as the commands
-%
-% \question
-% \titledquestion
-% \part
-% \subpart
-% \subsubpart
-%
-% except that any points assigned become ``bonus points'', which by
-% default are typeset in the form
-%
-% 1. (1 point (bonus))
-%
-% or
-%
-% 1. (2 points (bonus))
-%
-% If no points are assigned, then these ``bonus'' versions of the
-% commands are equivalent to the non-bonus versions.
-%
-% The command
-%
-% \bonusgradetable
-%
-% is analogous to the command \gradetable; it can be used in any of the
-% four forms
-%
-% \bonusgradetable[v][questions]
-% \bonusgradetable[h][questions]
-% \bonusgradetable[v][pages]
-% \bonusgradetable[h][pages]
-%
-% and it counts only bonus points, while \gradetable counts only
-% non-bonus points.
-%
-% The commands
-%
-% \bonuspointsofquestion
-% \bonuspointsonpage
-% \numbonuspoints
-%
-% are analogous to the commands
-%
-% \pointsofquestion
-% \pointsonpage
-% \numpoints
-%
-% The remaining new commands are for customizing the appearance of bonus
-% points and bonusgradetable. The command
-%
-% \bonuspointpoints
-%
-% is analogous to the command \pointpoints; it takes two arguments, the
-% first of which will appear after 1 or \half points the second to
-% appear after any other number of points. The default was created by
-% the equivalent of the command
-%
-% \bonuspointpoints{point (bonus)}{points (bonus)}
-%
-% If, for example, you give the command
-%
-% \bonuspointpoints{bonus point}{bonus points}
-%
-% then bonus points will look like
-%
-% 1. (1 bonus point)
-%
-% or
-%
-% 1. (2 bonus points)
-%
-% (The commands \bracketedpoints, \boxedpoints, and \nobracketedpoints
-% have the same effect on bonus points that they have on non-bonus
-% points, and the command \marksnotpionts replaces ``point'' with
-% ``mark'' in all of these cases.)
-%
-% \bonuspointname is analogous to \pointname, and the defaults were
-% created by the commands
-%
-% \pointname{ \points}
-% \bonuspointname{ \bonuspoints}
-%
-% (Note the intentional space in each of those commands.)
-%
-% \marginbonuspointname is analogous to \marginpointname, and the
-% default was created by the command
-%
-% \marginbonuspointname{ (bonus)}
-%
-% \bonuspointformat is analogous to \pointformat.
-%
-%
-% The commands for customizing the words used in \bonusgradetable are
-% analogous to those used for customizing the words used in \gradetable,
-% except that they begin with a ``b'':
-%
-% \bhqword is analogous to \hqword
-% \bhpword is analogous to \hpword
-% \bhsword is analogous to \hsword
-% \bhtword is analogous to \htword
-% \bvqword is analogous to \vqword
-% \bvpword is analogous to \vpword
-% \bvsword is analogous to \vsword
-% \bvtword is analogous to \vtword
-% is analogous to
-% \bvpgword is analogous to \vpgword
-% \bhpgword is analogous to \hpgword
-%
+% After giving the command \settabletotalbonuspoints{numbonuspoints},
+% any grade or point table will list the total bonus points as
+% numbonuspoints instead of the actual total number of bonus points in
+% the table.
%
-%--------------------------------------------------------------------
-% Version 2.212$\beta$, 2006/11/13:
+% These commands are intended for exams in which students are asked to
+% do some subset of the problems, but not all of them, and so the
+% total number of points possible is less than the sum of the points
+% for all of the questions.
%
-% Made \useslantedhalf and \usehorizontalhalf global.
%
-%--------------------------------------------------------------------
-% Version 2.211$\beta$, 2006/10/29:
+% To have one of these commands affect only a single table, confine the
+% command and the \gradetable command inside of a group, as in
%
-% New commands:
+% \begingroup
+% \settabletotalpoints{100}
+% \gradetable[v][questions]
+% \endgroup
%
-% \pointformat
-% \themarginpoints
+% or even just
%
-% An old command that's also useful here is
+% \begin{center}
+% \settabletotalpoints{100}
+% \gradetable[v][questions]
+% \end{center}
%
-% \thepoints
+%--------------------------------------------------------------------
+% Version 2.314$\beta$, 2010/12/01:
%
-% \pointformat: The \pointformat command allows you to change the
-% format used to print the points. It takes one argument, and that
-% argument becomes the command to print the points, whether the points
-% are being printed at the beginning of the question, in the left
-% margin (because of \pointsinmargin), in the right margin (because of
-% \pointsinrightmargin), or dropped in the right margin at the end of
-% the question (because of \pointsdroppedatright).
+% New user command:
%
-% The argument to \pointformat should contain either the command
+% \addquestionobject
%
-% \thepoints
+% This is for when some of a question spills onto the next page, but
+% that page doesn't have any parts, subparts, subsubparts, or choices
+% beginning on theat page (which means that the \ifincomplete command
+% won't know that any of that question is on that page). If you say
+% \addquestionobject at the very end of the question, it will write a
+% questionobject to the .aux file so that \ifincomplete will work
+% correctly.
%
-% which expands to the number of points followed by the argument to
-% the last \pointname command, or the command
+% New commands used only internally:
%
-% \themarginpoints
+% \first@questionobject
+% \questionobject@pluspagecheck
%
-% which expands to the number of points followed by the argument to
-% the last \marginpointname command.
+% These were just to clean up some of the internal code.
%
-% For example, the command \bracketedpoints is equivalent to
+%--------------------------------------------------------------------
+% Version 2.313$\beta$, 2010/02/18:
%
-% \pointformat{[\thepoints]}
+% Bug fix: When solutions are not being printed, the solution,
+% solutionorlines, and solutionordottedlines environments disallow
+% pagebreaks before the environment, which can pull the last line of
+% the question (or part, or etc.) preceding the environment onto the
+% next page, even when leaving a rather large space before the
+% pagebreak. We insert
%
-% if points are not being printed in the margin and to
+% \penalty 0
%
-% \pointformat{[\themarginpoints]}
+% to allow a pagebreak before the environment. We make no change to
+% the solutionorbox environment, since it didn't have this problem.
%
-% if points are being printed in the margin.
+%--------------------------------------------------------------------
+% Version 2.312$\beta$, 2010/01/17:
%
-% For another example, the command \boxedpoints is equivalent to
+% New commands:
+%
+% \combinedgradetable
+% \combinedpointtable
+% \partialcombinedgradetable
+% \partialcombinedpointtable
+%
+% These are similar to \gradetable, \pointable, \bonusgradetable,
+% \bonuspointtable, \partialgradetable, \partialpointtable,
+% \partialbonusgradetable, and \partialbonuspointtable except that
+% these new commands list both the points and the bonus points.
+%
+% \partialcombinedgradetable and \partialcombinedpointtable take one
+% required argument, which is the name of the grading range. All four
+% of these commands take two optional arguments, the first being either
+% ``v'' or ``h'' and the second being either ``questions'' or
+% ``pages''. The possibilities are thus
+%
+% \combinedgradetable[v][questions]
+% \combinedgradetable[v][pages]
+% \combinedgradetable[h][questions]
+% \combinedgradetable[h][pages]
+% \partialcombinedgradetable{rangename}[v][questions]
+% \partialcombinedgradetable{rangename}[v][pages]
+% \partialcombinedgradetable{rangename}[h][questions]
+% \partialcombinedgradetable{rangename}[h][pages]
+%
+% The defaults are ``v'' and ``questions''.
+%
+% The horizontal tables have separate rows for the points and bonus
+% points. The vertical tables have separate columns for the points and
+% bonus points.
+%
+% The default values for the words that appear in the tables are set by
+% the commands
+%
+% \chqword{Question:}
+% \chpgword{Page:}
+% \chpword{Points:}
+% \chbpword{Bonus Points:}
+% \chsword{Score:}
+% \chtword{Total}
+% \cvqword{Question}
+% \cvpgword{Page}
+% \cvpword{Points}
+% \cvbpword{Bonus Points}
+% \cvsword{Score}
+% \cvtword{Total:}
+%
+% The words in the table can be changed by giving any of these
+% commands with the desired word as argument.
%
-% \pointformat{\fbox{\thepoints}}
+%--------------------------------------------------------------------
+% Version 2.311$\beta$, 2010/01/10:
%
-% if points are not being printed in the margin and to
+% New environment: oneparcheckboxes
%
-% \pointformat{\fbox{\themarginpoints}}
+% The oneparcheckboxes environment is to the checkboxes environment as
+% the oneparchoices environment is to the choices environment. That is,
+% each choice is begun with either a \choice or a \correctchoice
+% command, and these will all be printed as a single paragraph. When
+% answers are not being printed, each choice will have a label
+% consisting of a box that the student can check, created by the
+% argument to the last \checkboxchar command. The default value is
+% created by the command
%
-% if points are being printed in the margin.
+% \checkboxchar{$\bigcirc$}
%
-% For another example, if you give the commands
+% (Note the dollar signs, since \bigcirc can appear only in math
+% mode.) When answers are being printed, then any choice created
+% using the \correctchoice command will be labelled by the argument to
+% the last \checkedchar command, the default value of which is created
+% by the command
%
-% \pointsinmargin
-% \marginpointname{\%}
-% \pointformat{\slshape (\themarginpoints)}
+% \checkedchar{$\surd$}
%
-% then the points will be printed in the left margin, followed by the
-% symbol `%', surrounded by parentheses, all in slanted type.
+%--------------------------------------------------------------------
+% Version 2.310$\beta$, 2010/01/09:
%
-% For another example, if you give the commands
+% New command: \bonusqformat
%
-% \pointsinrightmargin
-% \marginpointname{\%}
-% \pointformat{\fbox{\bfseries \boldmath \themarginpoints}}
+% The \bonusqformat command takes one argument, with the same
+% description as for the argument of the \qformat command.
%
-% then the points will be printed in the right margin, followed by the
-% symbol `%', all in bold and surrounded by a box. (Note: The commands
-% \bfseries and \boldmath are needed here because the ``one half''
-% printed when you use half points is printed in math mode while the
-% rest of the points are printed in text mode.)
+% Note added 2011/04/05: Version 2.318$\beta$ changes the behavior so
+% that \qformat and \bonusqformat are now completely independent!
%
-%--------------------------------------------------------------------
-% Version 2.210$\beta$, 2006/09/28:
+% If the user gives a \qformat command, then the argument of that
+% command is used to format both questions and bonusquestions. If,
+% after giving the \qformat command, the user gives a \bonusqformat
+% command, then the argument of the \bonusqformat command will be used
+% to format bonus questions.
%
-% Fixed the bug that prevented having two consecutive \correctchoice's
-% in a choices or oneparchoices environment.
+% Note: The \bonusqformat command must be given *after* the \qformat
+% command, or else the \bonusqformat command will have no effect.
%
-%--------------------------------------------------------------------
-% Version 2.209$\beta$, 2006/05/26:
+% Note: If the user hasn't given a \qformat command, then a
+% \bonusqformat command will have no effect.
%
-% We corrected the problem that \ifcontinuation and \ifincomplete paid
-% attention only to parts, subparts, and subsubparts when deciding on
-% which page a question ended, but ignored choices. We corrected this,
-% so that a question is now thought to end on the page on which its last
-% part, subpart, subsubpart, or choice begins.
+% Note: If the user gives a \qformat command and a \bonusqformat
+% command, and then later says \noqformat, then the arguments of both
+% the \qformat and \bonusqformat commands are no longer usable. That
+% is, if the user later on once again says \qformat, and wants the bonus
+% questions to have a different format from the questions, then another
+% \bonusqformat command must be given.
%
-%--------------------------------------------------------------------
-% Version 2.208$\beta$, 2006/01/30:
-%
-% We corrected the description of the usage of \ifthenelse in the
-% comments describing what's new in version 2.207beta.
+% Note added 2011/04/05:: The above is changed in version 2.318$\beta$.
+% \qformat and \bonusqformat are now completely independent.
+% \noqformat cancels only \qformat, and the new command
+% \nobonusqformat cancels \bonusqformat.
%
%--------------------------------------------------------------------
-% Version 2.207$\beta$, 2006/01/29:
-%
-% New feature: It's possible to say
-%
-% \ifprintanswers
-% Some stuff
-% \fi
-%
-% to insert ``Some stuff'' only when answers are being printed. It's
-% also possible to say
-%
-% \ifprintanswers
-% Some stuff
-% \else
-% Other stuff
-% \fi
-%
-% to insert ``Some stuff'' when answers are being printed and ``Other
-% stuff'' when answers aren't being printed.
-%
-% Alternatively, it's possible to accomplish the same thing by saying
-%
-% \ifthenelse{\boolean{printanswers}}{Some stuff}{Other stuff}
-%
-% If you want to ``Stuff'' only when answers aren't being printed, you
-% can say either
-%
-% \ifprintanswers
-% \else
-% Stuff
-% \fi
-%
-% or
-%
-% \ifthenelse{\boolean{printanswers}}{}{Stuff}
-%
-% We accomplished this by changing all uses of \if@printanswers,
-% \@printanswerstrue, and \@printanswersfalse to \ifprintanswers,
-% \printanswerstrue, and \printanswersfalse.
-%
+% Version 2.309$\beta$, 2009/11/30:
+%
+% New environment: checkboxes
+% New commands: \checkboxeshook
+% \checkboxchar
+% \checkedchar
+%
+% The checkboxes environment is similar to the choices environment,
+% except that choices are not numbered. Instead of numbers, each
+% choice has a label consisting of a box that the student can check,
+% created by the argument to the last \checkboxchar command. The
+% default value is created by the command
+%
+% \checkboxchar{$\bigcirc$}
+%
+% (Note the dollar signs, since \bigcirc can appear only in math
+% mode.) When answers are being printed, then any choice created
+% using the \correctchoice command will be labelled by the argument to
+% the last \checkedchar command, the default value of which is created
+% by the command
+%
+% \checkedchar{$\surd$}
+%
+% The list parameters used in the checkboxes environment can be
+% customized by redefining \checkboxeshook, the default value of which
+% is empty. (This is similar to using \choiceshook to alter the
+% choices environment.)
+%
%--------------------------------------------------------------------
-% Version 2.206$\beta$, 2005/08/24:
-%
-% New feature: When using a grading table indexed by questions, it's
-% possible to replace the question numbers in the table with titles
-% for the questions.
+% Version 2.308$\beta$, 2009/11/26:
%
-%
-% There are two new commands: \titledquestion and \thequestiontitle.
-%
-%
-% \titledquestion is a replacement for \question; it has one required
-% argument (the title) and one optional argument (the point value), as
-% in
-%
-% \titledquestion{Question \thequestion: Concepts}
-%
-% which sets the question title to ``Question 2: Concepts'' (if this
-% is the second question) and doesn't set any pointvalues, or
-%
-% \titledquestion{Design}[10]
-%
-% which sets the question title to ``Design'' and sets the pointvalue
-% to ``10''. (Note that the question title doesn't include the number
-% of the question unless you put it there using the \thequestion
-% command.)
-%
-% The title of the question then automatically replaces the question
-% number in a grading table indexed by question numbers.
-%
-%
-%
+% We fixed a bug that caused \bonussubpart to act like \subpart and
+% \bonussubsubpart to act like \subsubpart.
%
-%
-% \thequestiontitle: This command expands to the question title. This
-% is for use in the argument of a \qformat command, so that you can make
-% the question title appear in the actual question.
-%
-% If a question is begun with \question (instead of \titledquestion),
-% then the value of \thequestiontitle will automatically be set to the
-% number of the question.
-%
-% Note: The contents of \thequestiontitle don't appear anywhere in the
-% actual question unless you do something to make it appear. For
-% example, the command
-%
-% \qformat{\textbf{Question \thequestion: \thequestiontitle}\dotfill\thepoints}
-%
-% would insert the number of the question along with the title of the
-% question and the point value at the beginning of the question.
-%
-%
-% Note: If you use a grading table indexed by questions and you use the
-% \titledquestion command, then the number of the question won't appear
-% in the grading table unless you include \thequestion in the title of
-% the question.
-%
+%--------------------------------------------------------------------
+% Version 2.307$\beta$, 2009/06/11:
%
-% Note: If \thequestion appears in both the argument to \qformat and the
-% title of the question, then the question number will be printed
-% twice.
-%
-%
-% If the command \thequestiontitle is never used, then the only effect
-% of using the command \titledquestion is that in a grading table
-% indexed by question number, this question will be indexed by the
-% number of the question, rather than by the argument to
-% \titledquestion, and the title of the question would never appear
-% except in the grading table.
+% We fixed a bug that arose only when there were cover pages and the
+% first page of the cover pages used a different extraheadheight or
+% extrafootheight from that used on the first page of the regular pages.
+% The bug caused the first page of the regular pages to use the
+% extraheadheight and extrafootheight intended only for the first cover
+% page.
%
-%
%--------------------------------------------------------------------
+% Version 2.306$\beta$, 2009/03/28:
%
-% Version 2.205$\beta$, 2005/08/22:
+% We fixed a bug that arose only when the user used a figure or
+% table environment that floated to the top of a page. If that
+% happened, then a full page's worth of text was placed below
+% the figure or table, makeing the text run over the footline and off
+% the bottom of the page.
%
-% Bug fix: If a question began with a parts environment (i.e., if the
-% parts environment began before we entered horizontal mode in the
-% question), then a grading table indexed by questions would get the
-% part number instead of the question number. That's fixed now.
+% We fixed this by commenting out several lines at the end of
+% \@setheadheight and @setfootheight.
%
%--------------------------------------------------------------------
+% Version 2.305$\beta$, 2009/01/30:
%
-% Version 2.204$\beta$, 2005/08/21:
+% We fixed a bug to keep page breaks from occurring inside of
+% \makeemptybox. We also added \begingroup \endgroup for the off
+% chance that someone was using box0 and didn't want us to change it.
%
-% Bug fix: Hyperlinks didn't work on page numbers for horizontal
-% grading tables indexed by page numbers. They do now.
+% We also fixed a bug in the solutionorbox environment that showed
+% itself when the user used \stretch in the optional argument.
%
%--------------------------------------------------------------------
+% Version 2.304$\beta$, 2009/01/22:
%
-% Version 2.203$\beta$, 2005/08/20:
+% We rewrote the definition of \makeemptybox and the solutionorbox
+% environment (created in version 2.303).
%
-% Eliminated \do@int@lbl, and replaced it with labels for each
-% question, part, subpart, and subsubpart the names of which
-% tell you what they're labelling.
+% The argument to \makeemptybox can now be either a length, or \fill, or
+% \stretch{number}.
%
-% That allowed us to rewrite the grade table stuff so that, for tables
-% indexed by question numbers, the question numbers are inserted with a
-% \ref, so that if \usepackage{hyperref} and pdflatex are used, those
-% question numbers will be clickable links that take you to the relevant
-% question.
+% The optional argument to the solutionorbox environment can also be
+% either a length, or \fill, or \stretch{number}. If the optional
+% argument is omitted, then no box is printed when printanswers is
+% false.
%
-% We also added a label for the first points to appear on each page, and
-% rewrote the grade table stuff for tables indexed by page number so
-% that the page numbers are inserted with a \pageref, so that if
-% \usepackage{hyperref} and pdflatex are used, those page numbers will
-% be clickable links that take you to the relevant page.
+% The minimum box height is \minboxheight, whose value is set by the
+% command
+%
+% \setlength\minboxheight{.1in}
+%
+% This can be changed by giving a new setlength command, but it's not
+% likely that anyone actually wants a box of height less than .1 inch.
%
%--------------------------------------------------------------------
+% Version 2.303$\beta$, 2009/01/21:
%
-% Version 2.202$\beta$, 2005/08/10:
+% New command: \makeemptybox
+% New environment: solutionorbox
%
-% Created \correctchoice as a synonym for \CorrectChoice
+% \makeemptybox takes one argument, which is a length, and it creates
+% an empty box of width the length of the current line and of height
+% equal to the argument. That is, the box extends from the current
+% left margin (which depends on whether we're in a question, part,
+% subpart, or subsubpart) to the right margin.
%
-% Changed \CorrectChoiceDeclarations to \CorrectChoiceEmphasis,
-% and created \correctchoiceemphasis as a synonym for that.
+% The solutionorbox environment is similar to the solution
+% environment, except that if printanswers is false and an optional
+% argument is specified, then instead of leaving that much blank space
+% we print an empty box of that height. The optional argument must be
+% a dimension; it can not be \fill. If the optional argument is
+% missing or equal to 0pt, then when printanswers is false we print
+% nothing at all.
+%
+% Note: This is changed in version 2.304. As of that version, the
+% argument can be a length, or \fill, or \stretch{number}.
%
%--------------------------------------------------------------------
+% Version 2.302$\beta$, 2008/10/18:
%
-% Version 2.201$\beta$, 2005/08/09:
+% New commands: \numcoverpages and \totalnumpages
%
-% We created a \CorrectChoice command for use in the choices and
-% oneparchoices environments.
+% \numcoverpages inserts the number of pages occupied by the
+% coverpages environment. If there is no coverpages environment,
+% it inserts 0.
%
-% When solutions are not being printed, \CorrectChoice is equivalent to
-% \choice.
+% \totalnumpages inserts the sum of \numcoverpages and \numpages.
+% Note that if there are pages preceding a coverpages environment, then
+% those pages will not be counted by \totalnumpages.
%
-% When solutions *are* being printed, the choice that was created with
-% \CorrectChoice (rather than with \choice) will be printed subject to
-% the declarations in the argument of the
+% We also added \relax after some \ifnum comparisons and commented
+% out some line endings to remove, e.g., an unwanted space inserted
+% by \ifcontinuation when the page is a continuation.
%
-% \CorrectChoiceDeclarations
+%--------------------------------------------------------------------
+% Version 2.301$\beta$, 2008/09/22:
%
-% command. The default is
+% All solution, solutionorlines, and solutionordotteslines
+% environments are now enclosed in a group which is begun
+% with the argument of the command
%
-% \CorrectChoiceDeclarations{\bfseries}
+% \SolutionEmphasis
%
-% and so, when solutions are being printed, the correct choice is
-% printed in boldface by default. If, e.g., you give the command
+% the default value of which is determined by the command
%
-% \usepackage{color}
+% \SolutionEmphasis{}
%
-% after the \documentclass command and then give the command
+% That is, the default is that nothing is inserted.
+% For example, if the command
%
-% \CorrectChoiceDeclarations{\color{red}}
+% \SolutionEmphasis{\itshape\small}
%
-% then the correct choice will be printed in red. If, e.g., you give
-% the command
+% is used, the solutions will be set in italics, in small type.
%
-% \CorrectChoiceDeclarations{\color{red}\bfseries}
%
-% then the correct choice will be printed in red and in boldface.
+% New command: \unframedsolutions
%
-% Note added later: \CorrectChoiceDeclarations was changed
-% to \CorrectChoiceEmphasis in version 2.202$\beta$.
+% This causes solutions to be printed as normal text, without any
+% framing or shading. Anyone using this command should use the
+% \SolutionEmphasis command so that the solutions will be
+% distinguishable from the rest of the exam.
+%
+%--------------------------------------------------------------------
+% Version 2.3, 2008/07/16:
+%
+% Minor typographic corrections to comments.
%
%--------------------------------------------------------------------
%--------------------------------------------------------------------
@@ -774,6 +553,11 @@
\DeclareOption{answers}{\printanswerstrue}
\DeclareOption{noanswers}{\printanswersfalse}
+\newif\ifcancelspace
+\cancelspacefalse
+\DeclareOption{cancelspace}{\cancelspacetrue}
+\DeclareOption{nocancelspace}{\cancelspacefalse}
+
% The following keeps track of whether the user has requested that we
% add up the points on the exam. We make the default false so that
% users who put other than numbers into the points argument of a
@@ -902,7 +686,7 @@
\newcommand*\adj@hdht@ftht{%
\if@coverpages
- \ifnum\value{page}=1
+ \ifnum\value{page}=1\relax
\@setheadheight{\covfp@exhd}%
\@setfootheight{\covfp@exft}%
\else
@@ -910,7 +694,7 @@
\@setfootheight{\covrun@exft}%
\fi
\else
- \ifnum\value{page}=1
+ \ifnum\value{page}=1\relax
\@setheadheight{\fp@exhd}%
\@setfootheight{\fp@exft}%
\else
@@ -991,7 +775,7 @@
\@appendoutput{\adj@hdht@ftht}
%--------------------------------------------------------------------
-% \setheadheight and \setfootheight:
+% \@setheadheight and \@setfootheight:
\def\@setheadheight#1{%
\begingroup % Avoid trouble from using \@temp and \@spaces
@@ -1018,11 +802,22 @@
% executed only in the preamble or as we return from the output
% routine, but we're leaving it in so that this will still work if
% we use this at some random point in the middle of composing a
- % page).
+ % page).
+ % Bugfix, Version 2.306beta, 2009/03/28:
+ % We don't do this!!
+ % If the user had a figure environment that floated to the
+ % top of a page, then this would cause that page to run
+ % over the footer and off the bottom of the page, because
+ % this somehow caused a full page's worth of stuff to be
+ % placed after the figure, as if the figure wasn't taking
+ % up space on the page.
+ % We *do* need to put \@colht at the correct new value, though,
+ % apparently because \@colht is set near the end of the
+ % output routine.
\global\@colht=\textheight
- \global\@colroom=\textheight
- \global\vsize=\textheight
- \global\pagegoal=\textheight
+% \global\@colroom=\textheight
+% \global\vsize=\textheight
+% \global\pagegoal=\textheight
\endgroup
}
@@ -1050,10 +845,21 @@
% routine, but we're leaving it in so that this will still work if
% we use this at some random point in the middle of composing a
% page).
+ % Bugfix, Version 2.306beta, 2009/03/28:
+ % We don't do this!!
+ % If the user had a figure environment that floated to the
+ % top of a page, then this would cause that page to run
+ % over the footer and off the bottom of the page, because
+ % this somehow caused a full page's worth of stuff to be
+ % placed after the figure, as if the figure wasn't taking
+ % up space on the page.
+ % We *do* need to put \@colht at the correct new value, though,
+ % apparently because \@colht is set near the end of the
+ % output routine.
\global\@colht=\textheight
- \global\@colroom=\textheight
- \global\vsize=\textheight
- \global\pagegoal=\textheight
+% \global\@colroom=\textheight
+% \global\vsize=\textheight
+% \global\pagegoal=\textheight
\endgroup
}
@@ -1100,8 +906,12 @@
\newif\if@coverpages
\@coverpagesfalse
+\newcounter{num@coverpages}
+% We'll set this to zero in case there is no coverpages environment:
+\setcounter{num@coverpages}{0}
+
\newenvironment{coverpages}{%
- \ifnum \value{numquestions}>0
+ \ifnum \value{numquestions}>0\relax
\ClassError{exam}{%
Coverpages cannot be used after questions have begun.\MessageBreak
}{%
@@ -1115,7 +925,16 @@
\adj@hdht@ftht
}{%
\clearpage
+ \setcounter{num@coverpages}{\value{page}}%
+ \addtocounter{num@coverpages}{-1}%
\pagenumbering{arabic}%
+ % Bugfix, Version 2.307\beta, 2009/06/11:
+ % We have to say \@coverpagesfalse before \adj@hdht@ftht
+ % because we're still inside the group created by the
+ % coverpages environment and we want to set the
+ % extraheadheight and extrafootheight to the values correct
+ % for the first non-cover page:
+ \@coverpagesfalse
\adj@hdht@ftht
}
@@ -1132,13 +951,13 @@
\newcommand*\@dohead{%
\def\@oddhead{%
\if@coverpages
- \ifnum\value{page}=1
+ \ifnum\value{page}=1\relax
\cov@fullhead
\else
\covrun@fullhead
\fi
\else
- \ifnum\value{page}=1
+ \ifnum\value{page}=1\relax
\@fullhead
\else
\run@fullhead
@@ -1151,13 +970,13 @@
\newcommand*\@dofoot{%
\def\@oddfoot{%
\if@coverpages
- \ifnum\value{page}=1
+ \ifnum\value{page}=1\relax
\cov@fullfoot
\else
\covrun@fullfoot
\fi
\else
- \ifnum\value{page}=1
+ \ifnum\value{page}=1\relax
\@fullfoot
\else
\run@fullfoot
@@ -1629,6 +1448,7 @@
% \numpages, \iflastpage, and \oddeven
% Also: \numpoints, \numquestions, \numparts, and \numsubparts
% Also also: \pointsofquestion
+% Also: \numcoverpages and \totalnumpages
% Make the number of pages available as the macro \numpages,
% the number of points as \numpoints,
@@ -1660,6 +1480,20 @@
\exam@lastpage
}% numpages
+% Change 2011/04/01: We added a ``0'' in front of the
+% mbox when \exam@lastcoverpage isn't defined. This is
+% so that the construction \romannumeral\numcoverpages
+% won't generate an error on the first run of latex.
+\def\numcoverpages{\@ifundefined{exam@lastcoverpage}%
+ {0\mbox{\normalfont\bf ??}}%
+ \exam@lastcoverpage
+}% numpages
+
+\def\totalnumpages{\@ifundefined{exam@totalpages}%
+ {\mbox{\normalfont\bf ??}}%
+ \exam@totalpages
+}% numpages
+
\def\numpoints{\@ifundefined{exam@numpoints}%
{\mbox{\normalfont\bf ??}}%
\exam@numpoints
@@ -1698,12 +1532,30 @@
{\csname bonuspointsofq@\romannumeral #1\endcsname}%
}% bonuspointsofquestion
+% For use in \combinedgradetable and \combinedpointtable, we're
+% changing the defintions of \pointsonpage and \bonuspointsonpage
+% so that when, e.g., pointsonpage@ii is undefined, we just produce
+% 0. This comes up because the final page of the exam may have either
+% points with no bonus point or bonus points with no points, in which
+% case the combined table will try to list both points and bonus points
+% for that last page, and one of those will be undefined.
+%
+% \def\pointsonpage#1{\@ifundefined{pointsonpage@\romannumeral #1}%
+% {\mbox{\normalfont\bf ??}}%
+% {\csname pointsonpage@\romannumeral #1\endcsname}%
+% }% pointsonpage
+% \def\bonuspointsonpage#1{\@ifundefined{bonuspointsonpage@\romannumeral #1}%
+% {\mbox{\normalfont\bf ??}}%
+% {\csname bonuspointsonpage@\romannumeral #1\endcsname}%
+% }% bonuspointsonpage
+%
+% spanish.ldf redefines \@roman, so we'll avoid using \roman:
\def\pointsonpage#1{\@ifundefined{pointsonpage@\romannumeral #1}%
- {\mbox{\normalfont\bf ??}}%
+ {0}%
{\csname pointsonpage@\romannumeral #1\endcsname}%
}% pointsonpage
\def\bonuspointsonpage#1{\@ifundefined{bonuspointsonpage@\romannumeral #1}%
- {\mbox{\normalfont\bf ??}}%
+ {0}%
{\csname bonuspointsonpage@\romannumeral #1\endcsname}%
}% bonuspointsonpage
@@ -1750,7 +1602,14 @@
\advance\c@page-1
\immediate\write\@mainaux
{\string\gdef\string\exam@lastpage{\arabic{page}}}%
+ \immediate\write\@mainaux
+ {\string\gdef\string\exam@lastcoverpage{\arabic{num@coverpages}}}%
+ % We can now trash the value of num@coverpages:
+ \addtocounter{num@coverpages}{\value{page}}%
+ \immediate\write\@mainaux
+ {\string\gdef\string\exam@totalpages{\arabic{num@coverpages}}}%
\advance\c@page+1 % In case some other package looks at \c@page
+ %
\immediate\write\@mainaux
{\string\gdef\string\exam@numpoints{%
\prtaux@hlfcntr{numpoints}}}%
@@ -1869,9 +1728,9 @@
% argument.
\def\oddeven#1#2{%
\ifodd\value{page}%
- #1
+ #1%
\else
- #2
+ #2%
\fi
}% oddeven
@@ -2018,10 +1877,10 @@
{#1}%
{\ifnum \thepage > \PgInfo@get{@endquestions}\relax
% We're after a \nomorequestions:
- #2
+ #2%
\else
% We actually are incomplete:
- #1
+ #1%
\fi
}%
\fi
@@ -2129,7 +1988,7 @@
% \find@quesend, which is why it has to find the last question
% begun on or before the current page, rather than just before
% the current page.
- \ifnum 1 > \arabic{question}\relax
+ \ifnum 1 > \value{question}\relax
% Oops; probably because we're before the first question
% Just set latest@ques to -1:
\setcounter{latest@ques}{-1}%
@@ -2152,7 +2011,7 @@
% then call \decr@latest@ques to recursively decrement
% latest@ques as needed to find a question that begins on
% or before the current page:
- \setcounter{latest@ques}{\arabic{question}}%
+ \setcounter{latest@ques}{\value{question}}%
\decr@latest@ques
\fi
\fi
@@ -2277,7 +2136,7 @@
\else
\@ifundefined{Pg@@endquestions}%
{\incomp@first}%
- {\ifnum \thepage < \PgInfo@get{@endquestions}%
+ {\ifnum \thepage < \PgInfo@get{@endquestions}\relax
\incomp@first
\else
\incomp@second
@@ -2415,7 +2274,7 @@
\csname if#1@half\endcsname
\addtocounter{ifpos@cntr}{1}%
\fi
- \ifnum \value{ifpos@cntr} > 0
+ \ifnum \value{ifpos@cntr} > 0\relax
}% ifhlfnctr@pos
% \prtaux@hlfcntr is used inside the argument of a \write command for
@@ -2614,27 +2473,38 @@
% determine if there were points specified for this question.)
% The argument to the \qformat command *must* contain some
% stretch, i.e., at least one \hfil or \dotfill or ...
+%
+% The command \noqformat cancels the effect of \qformat and returns us
+% to the default situation.
+%
+% The commands \bonusqformat and \nobonusformat are analogous.
\newif\if@qformat
\@qformatfalse
+\newif\if@bonusqformat
+\@bonusqformatfalse
\def\qformat#1{%
\global\@qformattrue
\gdef\@questionformat{#1}%
}% qformat
+\def\bonusqformat#1{%
+ \global\@bonusqformattrue
+ \gdef\@bonusquestionformat{#1}%
+}% bonusqformat
\newcommand\noqformat{%
\global\@qformatfalse
}% noqformat
+\newcommand\nobonusqformat{%
+ \global\@bonusqformatfalse
+}% nobonusqformat
+
% \thepoints is for use in either a \qformat command
-% or a \pointformat command. It needs to have the
+% or a \pointformat command (or a \bonusqformat command).
+% It needs to have the
% \if@placepoints so that if it's used in a \qformat command
% it won't print anything if there are no points:
-%\newcommand\thepoints{%
-% \if@placepoints
-% \@points \@pointname
-% \fi
-%}
\newcommand\thepoints{%
\if@placepoints
\if@bonus
@@ -2647,9 +2517,6 @@
% \themarginpoints is for use only in a \pointformat command,
% and so it doesn't need the \if@placepoints bit in \thepoints:
-%\newcommand\themarginpoints{%
-% \@points \@marginpointname
-%}% themarginpoints
\newcommand\themarginpoints{%
\if@bonus
\@points \@marginbonuspointname
@@ -2673,10 +2540,54 @@
% begun on or before the current page:
\newcounter{ques@object}
+% \first@questionobject will be used by the \question command.
+% That is, it will be used only once, but we want to keep its
+% definition here, near the definitions of \addquestionobject and
+% \questionobject@pluspagecheck.
+\newcommand{\first@questionobject}{%
+ \setcounter{ques@object}{1}%
+ \edef\q@object@label{%
+ question\arabic{question}@object\arabic{ques@object}}%
+ \PgInfo@write{\q@object@label}%
+}% first@questionobject
+
+% \addquestionobject will be used by each part, subpart, and
+% subsubpart, and can also be used by the user to mark the end of a
+% question that spills over onto the next page without any part,
+% subpart, etc. starting on that page:
+\newcommand{\addquestionobject}{%
+ \addtocounter{ques@object}{1}%
+ \edef\q@object@label{%
+ question\arabic{question}@object\arabic{ques@object}}%
+ \PgInfo@write{\q@object@label}%
+}% addquestionobject
+
+% \questionobject@pluspagecheck will be used by each choice. It uses
+% the questionobject to check if we're the first one on the current
+% page, since choices don't have labels the way that questions, parts,
+% subparts, and subsubparts do (those things use the label to check if
+% they're the first thing on the page).
+\newcommand{\questionobject@pluspagecheck}{%
+ \addtocounter{ques@object}{1}%
+ \edef\q@object@label{%
+ question\arabic{question}@object\arabic{ques@object}}%
+ \PgInfo@write{\q@object@label}%
+ \set@counter@to@pageof{Curr@Page}{\q@object@label}%
+ \expandafter\ifx\csname Contin@\theCurr@Page\endcsname\relax
+ % We're the first \question, \part, \subpart, \subsubpart,
+ % or choice on this page:
+ \global\expandafter\edef\csname
+ Contin@\theCurr@Page\endcsname{\arabic{question}}%
+ \fi
+}% questionobject@pluspagecheck
+
+
+
% if@bonus will be true when we're doing a bonusquestion or bonuspart
% or etc., and it will also be used also to distinguish between
% \gradetable and \bonusgradetable (and between \pointtable and
-% \bonuspointtable, etc.):
+% \bonuspointtable, etc.), and also to distinguish between
+% \pointsinrange and \bonuspointsinrange:
\newif\if@bonus
\@bonusfalse
@@ -2689,6 +2600,7 @@
\newcommand\subpartshook{}
\newcommand\subsubpartshook{}
\newcommand\choiceshook{}
+\newcommand\checkboxeshook{}
\newenvironment{questions}{%
@@ -2731,10 +2643,10 @@
\addtocounter{numquestions}{1}%
% Write the sum of points of the previous question (if any)
% to the .aux file. (At this point, the question counter
- % has not yet been incremented, so \arabic{question} has the
+ % has not yet been incremented, so \value{question} is the
% number of the question that was just completed.)
\if@filesw
- \ifnum \arabic{question} > 0\relax
+ \ifnum \value{question} > 0\relax
% First do regular points:
\immediate\write\@mainaux
{\string\gdef\string\pointsofq@
@@ -2779,10 +2691,7 @@
\pageinfo@commands={%
\edef\@queslabel{question@\arabic{question}}%
\PgInfo@write{\@queslabel}%
- \setcounter{ques@object}{1}%
- \edef\q@object@label{%
- question\arabic{question}@object\arabic{ques@object}}%
- \PgInfo@write{\q@object@label}%
+ \first@questionobject
% In addition to the \PgInfo@write we use an actual \label
% command. We do this in order to make the question numbers in
% the grade tables into \ref's, so that if the user says
@@ -2842,7 +2751,6 @@
\process@subpart
}%
\def\process@subpart{%
- \@bonusfalse
\if@coverpages
\cover@question@error
\fi
@@ -2856,10 +2764,7 @@
\edef\@subpartlabel{subpart@\arabic{question}%
@\arabic{partno}@\arabic{subpart}}%
\PgInfo@write{\@subpartlabel}%
- \addtocounter{ques@object}{1}%
- \edef\q@object@label{%
- question\arabic{question}@object\arabic{ques@object}}%
- \PgInfo@write{\q@object@label}%
+ \addquestionobject
% In addition to the \PgInfo@write we use an actual \label
% command. We do this in order to make the question numbers in
% the grade tables into \ref's, so that if the user says
@@ -2908,7 +2813,6 @@
\process@subsubpart
}%
\def\process@subsubpart{%
- \@bonusfalse
\if@coverpages
\cover@question@error
\fi
@@ -2922,10 +2826,7 @@
\edef\@subsubpartlabel{subsubpart@\arabic{question}%
@\arabic{partno}@\arabic{subpart}@\arabic{subsubpart}}%
\PgInfo@write{\@subsubpartlabel}%
- \addtocounter{ques@object}{1}%
- \edef\q@object@label{%
- question\arabic{question}@object\arabic{ques@object}}%
- \PgInfo@write{\q@object@label}%
+ \addquestionobject
% In addition to the \PgInfo@write we use an actual \label
% command. We do this in order to make the question numbers in
% the grade tables into \ref's, so that if the user says
@@ -2981,7 +2882,7 @@
% Write the number of points of the final question
% to the .aux file:
\if@filesw
- \ifnum \arabic{question} > 0\relax
+ \ifnum \value{question} > 0\relax
% First do the regular points:
\immediate\write\@mainaux
{\string\gdef\string\pointsofq@\romannumeral
@@ -3007,11 +2908,20 @@
% \question@number is used as the label in the question list (instead
% of \questionlabel) so that if the user uses a \qformat command,
% we'll use the \@questionformat specified by the \qformat command:
+
\def\question@number{%
- \if@qformat
- \makebox[\hsize][s]{\@questionformat}\hskip-\labelsep
+ \if@bonus
+ \if@bonusqformat
+ \makebox[\hsize][s]{\@bonusquestionformat}\hskip-\labelsep
+ \else
+ \questionlabel
+ \fi
\else
- \questionlabel
+ \if@qformat
+ \makebox[\hsize][s]{\@questionformat}\hskip-\labelsep
+ \else
+ \questionlabel
+ \fi
\fi
}
\newcommand\questionlabel{\thequestion.}
@@ -3030,19 +2940,36 @@
% possible points) to be combined with the label of the first
% part. (\if@inlabel tells us if we are still waiting to enter
% horizontal mode after seeing a \question command.)
- \if@qformat
- \if@inlabel
- \leavevmode
- \@inlabelfalse
+ \if@bonus
+ \if@bonusqformat
+ \if@inlabel
+ \leavevmode
+ \@inlabelfalse
+ \fi
+ % The following is just in case the question had points,
+ % in which case @placepoints will still be true.
+ % (We used to do this inside of the \thepoints macro,
+ % but that allowed for an error if the user specified points for
+ % a question but had a \qformat that didn't mention \thepoints.)
+ % We also set @placepoints to be false in the \question command,
+ % in case one queation follows a previous one that had no parts.
+ \global \@placepointsfalse
+ \fi
+ \else
+ \if@qformat
+ \if@inlabel
+ \leavevmode
+ \@inlabelfalse
+ \fi
+ % The following is just in case the question had points,
+ % in which case @placepoints will still be true.
+ % (We used to do this inside of the \thepoints macro,
+ % but that allowed for an error if the user specified points for
+ % a question but had a \qformat that didn't mention \thepoints.)
+ % We also set @placepoints to be false in the \question command,
+ % in case one queation follows a previous one that had no parts.
+ \global \@placepointsfalse
\fi
- % The following is just in case the question had points,
- % in which case @placepoints will still be true.
- % (We used to do this inside of the \thepoints macro,
- % but that allowed for an error if the user specified points for
- % a question but had a \qformat that didn't mention \thepoints.)
- % We also set @placepoints to be false in the \question command,
- % in case one queation follows a previous one that had no parts.
- \global \@placepointsfalse
\fi
\def\part{%
\@bonusfalse
@@ -3065,10 +2992,7 @@
\temp@toks={%
\edef\@partlabel{part@\arabic{question}@\arabic{partno}}%
\PgInfo@write{\@partlabel}%
- \addtocounter{ques@object}{1}%
- \edef\q@object@label{%
- question\arabic{question}@object\arabic{ques@object}}%
- \PgInfo@write{\q@object@label}%
+ \addquestionobject
% In addition to the \PgInfo@write we use an actual \label
% command. We do this in order to make the question numbers in
% the grade tables into \ref's, so that if the user says
@@ -3378,12 +3302,6 @@
\def\item@points@pageinfo{%
\item
- % If @qformat is true, and if we're currently doing a question
- % (rather than a part, subpart, or subsubpart), then we don't want
- % to set the points (if any), since the points of a question will
- % appear only if the user chooses to cause that by putting a
- % \thepoints in the argument of the \qformat command.
- %
% Also: We need to do this here, *after* the \item command, rather
% than inside the macro \@readpoints, because the \item command
% puts the result of the \qformat command into an \hbox (with the
@@ -3393,11 +3311,12 @@
% user put a \thepoints command inside that argument it will
% correctly expand to the number of points. (When @placepoints is
% false, \thepoints expands to nothing at all).
- \if@qformat
- \ifx\ques@ref\@queslevel
- \global \@placepointsfalse
- \fi
- \fi
+ %
+ % We also want to define \padded@point@block when @placepoints is
+ % true even if qformat and bonusqformat are true just in case the
+ % user, for some deranged reason, says \droppoints immediately
+ % following a \question.
+ %
\if@placepoints
% Since we want the user to be able to say \thepoints in the
% argument to a \pointformat command, we need \@placepointstrue
@@ -3435,24 +3354,60 @@
% \setup@point@toks puts commands into \point@toks to place
% \padded@point@block at the correct spot. It doesn't append
% anything to \everypar (we do that in this macro, below).
+ %
+ % If @qformat is true, and if we're currently doing a question (or
+ % if @bonusqformat is true and we're doing a bonusquestion)
+ % (rather than a part, subpart, or subsubpart), then we don't want
+ % to set the points (if any), since the points of a question will
+ % appear only if the user chooses to cause that by putting a
+ % \thepoints in the argument of the \qformat command.
\if@pointsdropped
% Do nothing!
\else
- \setup@point@toks
+ \if@bonus
+ \if@bonusqformat
+ \ifx\ques@ref\@queslevel
+ % Do nothing
+ \else
+ \setup@point@toks
+ \fi
+ \else
+ \setup@point@toks
+ \fi
+ \else
+ \if@qformat
+ \ifx\ques@ref\@queslevel
+ % Do nothing
+ \else
+ \setup@point@toks
+ \fi
+ \else
+ \setup@point@toks
+ \fi
+ \fi
\fi
\global \@placepointsfalse
\fi
- % We *don't* use \append@toklist; see Bug fix note above
+ % We *don't* use \append@toklist; see the Bug fixnote above
+ % (Bug fix, 5 April 2004).
% We can append the tokens ``\the\point@toks'' whether or not we're
% setting any points because if we're not setting them, \point@toks
% will be empty.
% Also: It's important to do this *after* the \item command above,
% since the \item command discards the previous contents of
% \everypar.
- % Version 2.217-beta changes:
- % Instead of appending stuff to \everypar, we insert
- % \the \pageinfo@commands and \the \point@toks
- % into the box \@labels:
+ % Version 2.218$\beta$, 2007/10/31 changes:
+ % Instead of appending
+ % \the \pageinfo@commands \the \point@toks
+ % to \everypar, we insert them into the box \@labels. This corrects
+ % the problem that arose when a question (or part, etc.) begins with
+ % a list environment (including verbatim, flushleft, center,
+ % flushright, and possibly others that are implemented as trivlist
+ % environments). The \item command in those environments throws
+ % away the previous contents of \everypar, and so the tokens \the
+ % \pageinfo@commands \the \point@toks didn't get inserted where we
+ % expected. List environments *do* preserve the contents of the box
+ % \@labels, though.
\global\setbox\@labels\hbox{\unhbox\@labels
\the \pageinfo@commands
\the \point@toks}%
@@ -3776,7 +3731,7 @@
%--------------------------------------------------------------------
-% choices (for multiple choice)
+% choices (for multiple choice) and checkboxes
\renewcommand\thechoice{\Alph{choice}}
@@ -3798,21 +3753,12 @@
\CorrectChoiceEmphasis{\bfseries}
\let\correctchoiceemphasis\CorrectChoiceEmphasis
-
+% Note: \do@choice@pageinfo is used in both the choices and
+% the checkboxes environments.
\newtoks\choice@toks
\def\do@choice@pageinfo{%
\choice@toks={%
- \addtocounter{ques@object}{1}%
- \edef\q@object@label{%
- question\arabic{question}@object\arabic{ques@object}}%
- \PgInfo@write{\q@object@label}%
- \set@counter@to@pageof{Curr@Page}{\q@object@label}%
- \expandafter\ifx\csname Contin@\theCurr@Page\endcsname\relax
- % We're the first \question, \part, \subpart, \subsubpart,
- % or choice on this page:
- \global\expandafter\edef\csname
- Contin@\theCurr@Page\endcsname{\arabic{question}}%
- \fi
+ \questionobject@pluspagecheck
\choice@toks={}%
}%
% Version 2.217-beta changes:
@@ -3869,25 +3815,15 @@
\def\choice{%
\if@correctchoice \endgroup \fi
\refstepcounter{choice}%
- \ifnum\value{choice}>1
+ \ifnum\value{choice}>1\relax
\penalty -50\hskip 1em plus 1em\relax
\fi
\choicelabel
% No need to put the following into a token string; we just put
% the choicelabel onto the page, so we're at the spot whose page
% number we want to record:
- \addtocounter{ques@object}{1}%
- \edef\q@object@label{%
- question\arabic{question}@object\arabic{ques@object}}%
- \PgInfo@write{\q@object@label}%
- \set@counter@to@pageof{Curr@Page}{\q@object@label}%
- \expandafter\ifx\csname Contin@\theCurr@Page\endcsname\relax
- % We're the first \question, \part, \subpart, \subsubpart,
- % or choice on this page:
- \global\expandafter\edef\csname
- Contin@\theCurr@Page\endcsname{\arabic{question}}%
- \fi
- \nobreak\enskip
+ \questionobject@pluspagecheck
+ \nobreak\enskip
}% choice
\def\CorrectChoice{%
\if@correctchoice \endgroup \fi
@@ -3896,25 +3832,105 @@
\begingroup \@correctchoicetrue
\CorrectChoice@Emphasis
\fi
- \ifnum\value{choice}>1
+ \ifnum\value{choice}>1\relax
\penalty -50\hskip 1em plus 1em\relax
\fi
\choicelabel
% No need to put the following into a token string; we just put
% the choicelabel onto the page, so we're at the spot whose page
% number we want to record:
- \addtocounter{ques@object}{1}%
- \edef\q@object@label{%
- question\arabic{question}@object\arabic{ques@object}}%
- \PgInfo@write{\q@object@label}%
- \set@counter@to@pageof{Curr@Page}{\q@object@label}%
- \expandafter\ifx\csname Contin@\theCurr@Page\endcsname\relax
- % We're the first \question, \part, \subpart, \subsubpart,
- % or choice on this page:
- \global\expandafter\edef\csname
- Contin@\theCurr@Page\endcsname{\arabic{question}}%
- \fi
- \nobreak\enskip
+ \questionobject@pluspagecheck
+ \nobreak\enskip
+ }% CorrectChoice
+ \let\correctchoice\CorrectChoice
+ \let\par\@empty
+ % If we're continuing the paragraph containing the question,
+ % then leave a bit of space before the first choice:
+ \ifvmode\else\enskip\fi
+ \ignorespaces
+ }%
+ {\if@correctchoice \endgroup \fi}
+
+\newcommand{\checkboxchar}[1]{\def\checkbox@char{#1}}
+\newcommand{\checkedchar}[1]{\def\checked@char{#1}}
+\checkboxchar{$\bigcirc$}
+\checkedchar{$\surd$}
+
+\newenvironment{checkboxes}%
+ {\list{\checkbox@char}%
+ {%
+ \settowidth{\leftmargin}{W.\hskip\labelsep\hskip 2.5em}%
+ \def\choice{%
+ \if@correctchoice
+ \endgroup
+ \fi
+ \item
+ \do@choice@pageinfo
+ } % choice
+ \def\CorrectChoice{%
+ \if@correctchoice
+ \endgroup
+ \fi
+ \ifprintanswers
+ % We can't say \choice here, because that would
+ % insert an \endgroup:
+ \begingroup \@correctchoicetrue
+ \CorrectChoice@Emphasis
+ \item[\checked@char]
+ \else
+ \item
+ \fi
+ \do@choice@pageinfo
+ } % CorrectChoice
+ \let\correctchoice\CorrectChoice
+ \labelwidth\leftmargin\advance\labelwidth-\labelsep
+ \topsep=0pt
+ \partopsep=0pt
+ \checkboxeshook
+ }%
+ }%
+ {\if@correctchoice \endgroup \fi \endlist}
+
+\newenvironment{oneparcheckboxes}%
+ {%
+ % Although we're not printing numbers for the choices, we use the
+ % choice counter to keep track of whether a choice is the first
+ % one (in which case we don't leave any additional space) or a
+ % later one (in which case we do leave additional space):
+ \setcounter{choice}{0}%
+ \def\choice{%
+ \if@correctchoice \endgroup \fi
+ \stepcounter{choice}%
+ \ifnum\value{choice}>1\relax
+ \penalty -50\hskip 1em plus 1em\relax
+ \fi
+ \checkbox@char
+ % No need to put the following into a token string; we just put
+ % \checkbox@char onto the page, so we're at the spot whose page
+ % number we want to record:
+ \questionobject@pluspagecheck
+ \nobreak\enskip
+ }% choice
+ \def\CorrectChoice{%
+ \if@correctchoice \endgroup \fi
+ \stepcounter{choice}%
+ \ifprintanswers
+ \begingroup \@correctchoicetrue
+ \CorrectChoice@Emphasis
+ \fi
+ \ifnum\value{choice}>1\relax
+ \penalty -50\hskip 1em plus 1em\relax
+ \fi
+ \ifprintanswers
+ \checked@char
+ \else
+ \checkbox@char
+ \fi
+ % No need to put the following into a token string; we just put
+ % the choicelabel onto the page, so we're at the spot whose page
+ % number we want to record:
+ \questionobject@pluspagecheck
+ \nobreak\enskip
}% CorrectChoice
\let\correctchoice\CorrectChoice
\let\par\@empty
@@ -4070,7 +4086,58 @@
}
%--------------------------------------------------------------------
-% \uplevel and \fullwidth:
+% \makeemptybox
+
+% \makeemptybox takes one argument, which is a length, and it creates
+% an empty box of width the length of the current line and of height
+% equal to the argument. That is, the box extends from the current
+% left margin (which depends on whether we're in a question, part,
+% subpart, or subsubpart) to the right margin.
+
+% As of version 2.304, the argument of \makeemptybox can be either
+% a length, or \fill, or \stretch{number}.
+
+% \newcommand\makeemptybox[1]{
+% \par
+% \begingroup
+% \setlength{\fboxsep}{0pt}%
+% \framebox[\linewidth]{%
+% \vrule height 0pt depth #1 width 0pt
+% }%
+% \endgroup
+% }
+
+\newlength\minboxheight
+\setlength\minboxheight{.1in}
+
+\newcommand\makeemptybox[1]{%
+ \par
+ \hbox to \hsize{\hskip\@totalleftmargin \leaders\hrule\hfill}%
+ \nointerlineskip
+ \begingroup
+ \setbox0=\hbox to \hsize{\hskip\@totalleftmargin
+ \vrule height\minboxheight \hfill \vrule}%
+ % The vertical size desired may not be an exact multiple of
+ % \minboxheight, and so \cleaders might leave a gap between the
+ % vertical lines and the horizontal lines above and below it.
+ % Thus, we put a single copy of \box0 immediately below the
+ % horizontal line above and we'll also put a single copy of \box0
+ % immediately above the horizontal line below.
+ \copy0
+ \nobreak
+ \vskip -\minboxheight
+ \cleaders \copy0 \vskip #1
+ \vskip -\minboxheight
+ \nointerlineskip
+ \copy0
+ \endgroup
+ \nointerlineskip
+ \hbox to \hsize{\hskip\@totalleftmargin \leaders\hrule\hfill}%
+}
+
+%--------------------------------------------------------------------
+% \uplevel and \fullwidth
+% and the EnvUplevel and EnvFullwidth environments:
% \uplevel is used to print text at the indentation level of the
% enclosing environment. For example, to precede a question with
@@ -4079,14 +4146,26 @@
%
% \fullwidth is similar, but uses the full page of text on the page.
+% The EnvUplevel environment is similar to the \uplevel command, but it
+% has the advantage that you can include verbatim material (using, e.g.,
+% the \verb command) in the environment. (You can't include verbatim
+% material in the argument of an \uplevel command.)
+
+% The EnvFullwidth environment is similar to the \fullwidth command, but
+% it has the advantage that you can include verbatim material (using,
+% e.g., the \verb command) in the environment. (You can't include
+% verbatim material in the argument of an \fullwidth command.)
+
+
\long\def\uplevel#1{%
\par\bigskip
\vbox{%
+ % We entered internal vertical mode, and so we get \parshape=0.
% We set \leftskip to provide the correct left margin for whatever
- % text is in the argument of the \uplevel command:
+ % is in the argument of the \uplevel command:
\leftskip=\@totalleftmargin
\advance\leftskip-\leftmargin
- % We adjust \@totalleftmargin (and linewidth?) in case there's a
+ % We adjust \@totalleftmargin and linewidth in case there's a
% solution environment inside of the argument to the \uplevel:
\advance\@totalleftmargin-\leftmargin
\advance\linewidth\leftmargin
@@ -4095,9 +4174,24 @@
\nobreak
}
+\newenvironment{EnvUplevel}
+ {\par\bigskip\vbox\bgroup
+ % We set \leftskip to provide the correct left margin for whatever
+ % is inside of the environment:
+ \leftskip=\@totalleftmargin
+ \advance\leftskip-\leftmargin
+ % We adjust \@totalleftmargin (and linewidth?) in case there's a
+ % solution environment inside of the environment:
+ \advance\@totalleftmargin-\leftmargin
+ \advance\linewidth\leftmargin
+ }
+ {\egroup\nobreak}
+
+
\long\def\fullwidth#1{%
\par\bigskip
\vbox{%
+ % We entered internal vertical mode, and so we get \parshape=0.
\leftskip=0pt \rightskip=0pt
\advance\linewidth\@totalleftmargin
\@totalleftmargin=0pt
@@ -4106,6 +4200,17 @@
\nobreak
}
+\newenvironment{EnvFullwidth}
+ {\par\bigskip\vbox\bgroup
+ % We entered internal vertical mode, and so we get \parshape=0.
+ \leftskip=0pt \rightskip=0pt
+ % We adjust \@totalleftmargin (and linewidth?) in case there's a
+ % solution environment inside of the environment:
+ \advance\linewidth\@totalleftmargin
+ \@totalleftmargin=0pt
+ }
+ {\egroup\nobreak}
+
%--------------------------------------------------------------------
%--------------------------------------------------------------------
@@ -4122,69 +4227,112 @@
\def\cellwidth#1{\@cellwidth=#1}
\def\gradetablestretch#1{\def\@gtblstretch{#1}}
+% \settabletotalpoints allows the user to specify a total
+% number of points to appear in a table that may be different
+% from the sum of the points in the table:
+\newcommand\prt@tablepoints{\prt@hlfcntr{tbl@points}}
+\newcommand\settabletotalpoints[1]{%
+ \def\prt@tablepoints{#1}%
+}% \settabletotalpoints
+
+% \settabletotalbonuspoints is similar to \settabletotalpoints:
+\newcommand\prt@tablebonuspoints{\prt@hlfcntr{tbl@bonuspoints}}
+\newcommand\settabletotalbonuspoints[1]{%
+ \def\prt@tablebonuspoints{#1}%
+}% \settabletotalbonuspoints
+
% All of the following that begin with `h' are for horizontal tables,
% and all of them that begin with `v' are for vertical tables:
\def\hqword#1{\def\@hqword{#1}}
\def\hpword#1{\def\@hpword{#1}}
\def\hsword#1{\def\@hsword{#1}}
\def\htword#1{\def\@htword{#1}}
+\def\hpgword#1{\def\@hpgword{#1}}
+
\def\vqword#1{\def\@vqword{#1}}
\def\vpword#1{\def\@vpword{#1}}
\def\vsword#1{\def\@vsword{#1}}
\def\vtword#1{\def\@vtword{#1}}
-
\def\vpgword#1{\def\@vpgword{#1}}
-\def\hpgword#1{\def\@hpgword{#1}}
+
% The following are the versions for bonusgradetable:
\def\bhqword#1{\def\@bhqword{#1}}
\def\bhpword#1{\def\@bhpword{#1}}
\def\bhsword#1{\def\@bhsword{#1}}
\def\bhtword#1{\def\@bhtword{#1}}
+\def\bhpgword#1{\def\@bhpgword{#1}}
+
\def\bvqword#1{\def\@bvqword{#1}}
\def\bvpword#1{\def\@bvpword{#1}}
\def\bvsword#1{\def\@bvsword{#1}}
\def\bvtword#1{\def\@bvtword{#1}}
-
\def\bvpgword#1{\def\@bvpgword{#1}}
-\def\bhpgword#1{\def\@bhpgword{#1}}
+
+% The following are the versions for combinedgradetable:
+\def\chqword#1{\def\@chqword{#1}}
+\def\chpword#1{\def\@chpword{#1}}
+\def\chbpword#1{\def\@chbpword{#1}}
+\def\chsword#1{\def\@chsword{#1}}
+\def\chtword#1{\def\@chtword{#1}}
+\def\chpgword#1{\def\@chpgword{#1}}
+
+\def\cvqword#1{\def\@cvqword{#1}}
+\def\cvpword#1{\def\@cvpword{#1}}
+\def\cvbpword#1{\def\@cvbpword{#1}}
+\def\cvsword#1{\def\@cvsword{#1}}
+\def\cvtword#1{\def\@cvtword{#1}}
+\def\cvpgword#1{\def\@cvpgword{#1}}
+
% Initialize:
\cellwidth{2em}
\gradetablestretch{1.5}
+
+\hqword{Question:}
+\hpgword{Page:}
\hpword{Points:}
\hsword{Score:}
\htword{Total}
\vpword{Points}
\vsword{Score}
\vtword{Total:}
+\vqword{Question}
+\vpgword{Page}
+\bhqword{Question:}
+\bhpgword{Page:}
\bhpword{Bonus Points:}
\bhsword{Score:}
\bhtword{Total}
+\bvqword{Question}
+\bvpgword{Page}
\bvpword{Bonus Points}
\bvsword{Score}
\bvtword{Total:}
-% For tables indexed by question number:
-\vqword{Question}
-\hqword{Question:}
-\bvqword{Question}
-\bhqword{Question:}
-
-% For tables indexed by page number:
-\vpgword{Page}
-\hpgword{Page:}
-\bvpgword{Page}
-\bhpgword{Page:}
-
+\chqword{Question:}
+\chpgword{Page:}
+\chpword{Points:}
+\chbpword{Bonus Points:}
+\chsword{Score:}
+\chtword{Total}
+\cvqword{Question}
+\cvpgword{Page}
+\cvpword{Points}
+\cvbpword{Bonus Points}
+\cvsword{Score}
+\cvtword{Total:}
% The only commands here accessible to the user are \gradetable,
-% \bonusgradetable, \pointtable, \bonuspointtable, \partialgradetable,
-% \partialbonusgradetable, \partialpointtable,
-% \partialbonuspointtable, \begingradingrange, and \endgradingrange.
+% \bonusgradetable, \combinedgradetable, \pointtable,
+% \bonuspointtable, \combinedpointtable, \partialgradetable,
+% \partialbonusgradetable, \partialcombinedtable, \partialpointtable,
+% \partialbonuspointtable, \partialcombinedpointtable,
+% \begingradingrange, \endgradingrange, \pointsinrange, and
+% \bonuspointsinrange.
% The possibilities are
@@ -4198,6 +4346,11 @@
% \bonusgradetable[h][questions]
% \bonusgradetable[h][pages]
+% \combinedgradetable[v][questions]
+% \combinedgradetable[v][pages]
+% \combinedgradetable[h][questions]
+% \combinedgradetable[h][pages]
+
% \pointtable[v][questions]
% \pointtable[v][pages]
% \pointtable[h][questions]
@@ -4208,6 +4361,11 @@
% \bonuspointtable[h][questions]
% \bonuspointtable[h][pages]
+% \combinedpointtable[v][questions]
+% \combinedpointtable[v][pages]
+% \combinedpointtable[h][questions]
+% \combinedpointtable[h][pages]
+
% \partialgradetable{whatever}[v][questions]
% \partialgradetable{whatever}[v][pages]
% \partialgradetable{whatever}[h][questions]
@@ -4218,6 +4376,11 @@
% \partialbonusgradetable{whatever}[h][questions]
% \partialbonusgradetable{whatever}[h][pages]
+% \partialcombinedgradetable{whatever}[v][questions]
+% \partialcombinedgradetable{whatever}[v][pages]
+% \partialcombinedgradetable{whatever}[h][questions]
+% \partialcombinedgradetable{whatever}[h][pages]
+
% \partialpointtable{whatever}[v][questions]
% \partialpointtable{whatever}[v][pages]
% \partialpointtable{whatever}[h][questions]
@@ -4228,9 +4391,17 @@
% \partialbonuspointtable{whatever}[h][questions]
% \partialbonuspointtable{whatever}[h][pages]
+% \partialcombinedpointtable{whatever}[v][questions]
+% \partialcombinedpointtable{whatever}[v][pages]
+% \partialcombinedpointtable{whatever}[h][questions]
+% \partialcombinedpointtable{whatever}[h][pages]
+
% \begingradingrange{whatever}
% \endgradingrange{whatever}
%
+% \pointsinrange{whatever}
+% \bonuspointsinrange{whatever}
+%
% where ``whatever'' is a label chosen by the user.
% If one or both optional arguments are omitted, the defaults are
@@ -4241,10 +4412,14 @@
\newif\if@scores
% \@partialtrue means we're doing \partialgradetable,
-% \partialbonusgradetable, \partialpointtable, or
-% \partialbonuspointtable:
+% \partialbonusgradetable, \partialcombinedgradetable,
+% \partialpointtable, \partialbonuspointtable, or
+% \partialcombinedpointtable:
\newif\if@partial
+% \@combinedtrue means we're doing \combinedgradetable
+% or \combinedpointtable:
+\newif\if@combined
% It's OK to use the counter num@cols as a scratch counter
% in \begingradingrange and \endgradingrange because
@@ -4282,11 +4457,16 @@
% for the questions (or pages) that appear on the table:
\new@hlfcntr{tbl@points}
+% We'll use the counter tbl@bonuspoints to add up the total bonus
+% points for the questions (or pages) that appear on the table:
+\new@hlfcntr{tbl@bonuspoints}
+
\def\partialgradetable#1{%
\@scorestrue
\@bonusfalse
\@partialtrue
+ \@combinedfalse
\def\tbl@range{#1}%
% If the user doesn't include the optional argument
% choosing between vertical and horizontal,
@@ -4298,6 +4478,7 @@
\@scorestrue
\@bonustrue
\@partialtrue
+ \@combinedfalse
\def\tbl@range{#1}%
% If the user doesn't include the optional argument
% choosing between vertical and horizontal,
@@ -4305,10 +4486,23 @@
\@ifnextchar[{\i@gtable}{\i@gtable[v]}%
}% partialbonusgradetable
+\def\partialcombinedgradetable#1{%
+ \@scorestrue
+ \@bonusfalse
+ \@partialtrue
+ \@combinedtrue
+ \def\tbl@range{#1}%
+ % If the user doesn't include the optional argument
+ % choosing between vertical and horizontal,
+ % we give them vertical:
+ \@ifnextchar[{\i@gtable}{\i@gtable[v]}%
+}% partialcombinedgradetable
+
\def\partialpointtable#1{%
\@scoresfalse
\@bonusfalse
\@partialtrue
+ \@combinedfalse
\def\tbl@range{#1}%
% If the user doesn't include the optional argument
% choosing between vertical and horizontal,
@@ -4320,6 +4514,7 @@
\@scoresfalse
\@bonustrue
\@partialtrue
+ \@combinedfalse
\def\tbl@range{#1}%
% If the user doesn't include the optional argument
% choosing between vertical and horizontal,
@@ -4327,12 +4522,25 @@
\@ifnextchar[{\i@gtable}{\i@gtable[v]}%
}% partialbonuspointtable
+\def\partialcombinedpointtable#1{%
+ \@scoresfalse
+ \@bonusfalse
+ \@partialtrue
+ \@combinedtrue
+ \def\tbl@range{#1}%
+ % If the user doesn't include the optional argument
+ % choosing between vertical and horizontal,
+ % we give them vertical:
+ \@ifnextchar[{\i@gtable}{\i@gtable[v]}%
+}% partialcombinedpointtable
+
%--------------------------------------------------------------------
\def\gradetable{%
\@scorestrue
\@bonusfalse
\@partialfalse
+ \@combinedfalse
% If the user doesn't include the optional argument
% choosing between vertical and horizontal,
% we give them vertical:
@@ -4343,6 +4551,18 @@
\@scorestrue
\@bonustrue
\@partialfalse
+ \@combinedfalse
+ % If the user doesn't include the optional argument
+ % choosing between vertical and horizontal,
+ % we give them vertical:
+ \@ifnextchar[{\i@gtable}{\i@gtable[v]}%
+}% bonusgradetable
+
+\def\combinedgradetable{%
+ \@scorestrue
+ \@bonusfalse
+ \@partialfalse
+ \@combinedtrue
% If the user doesn't include the optional argument
% choosing between vertical and horizontal,
% we give them vertical:
@@ -4353,6 +4573,7 @@
\@scoresfalse
\@bonusfalse
\@partialfalse
+ \@combinedfalse
% If the user doesn't include the optional argument
% choosing between vertical and horizontal,
% we give them vertical:
@@ -4363,6 +4584,18 @@
\@scoresfalse
\@bonustrue
\@partialfalse
+ \@combinedfalse
+ % If the user doesn't include the optional argument
+ % choosing between vertical and horizontal,
+ % we give them vertical:
+ \@ifnextchar[{\i@gtable}{\i@gtable[v]}%
+}% bonuspointtable
+
+\def\combinedpointtable{%
+ \@scoresfalse
+ \@bonusfalse
+ \@partialfalse
+ \@combinedtrue
% If the user doesn't include the optional argument
% choosing between vertical and horizontal,
% we give them vertical:
@@ -4416,6 +4649,8 @@
\def\@questionsref{questions}
\def\@pagesref{pages}
\def\do@table#1#2{%
+ % The first argument is ``v'' or ``h'';
+ % the second argument is ``questions'' or ``pages''.
% See whether we're doing a table indexed by
% questions or by pages:
\begingroup % avoid trouble from using \@temp
@@ -4459,10 +4694,14 @@
%--------------------------------------------------------------------
% Grade and point tables indexed by question numbers:
+% We get to \find@qrange if we know we're doing a table indexed
+% by question numbers. The argument is either ``v'' or ``h''.
+% If we're not doing a partial table, then \find@qrange sets
+% \tbl@firstq to 1 and \tbl@lastq to \numquestions. Otherwise,
% \find@qrange makes sure the grading range is defined and that
% its last question isn't before its first question.
-% \@tblquestions branches, depending on whether the user
-% selected [v] or [h].
+% \find@qrange then calls \@tblquestions, passing along the argument
+% that is either ``v'' or ``h''.
\def\find@qrange#1{%
% We're doing a table indexed by question numbers.
@@ -4480,7 +4719,7 @@
\edef\tbl@firstq{\csname tbl@\tbl@range @firstq\endcsname}%
\edef\tbl@lastq{\csname tbl@\tbl@range @lastq\endcsname}%
% Check that firstq precedes or equals lastq:
- \ifnum \tbl@firstq > \tbl@lastq
+ \ifnum \tbl@firstq > \tbl@lastq\relax
\fbox{Error: Grading Range `\tbl@range ':
Last question precedes first question.}%
\ClassError{exam}{%
@@ -4509,6 +4748,8 @@
}% find@qrange
\def\@tblquestions#1{%
+ % \tbl@firstq and \tbl@lastq have already been set.
+ % The argument is either ``v'' or ``h', and we branch accordingly.
\if v#1%
\@vtblquestions
\else
@@ -4552,8 +4793,9 @@
\def\@vtblquestions{%
% The table is vertical and indexed by question numbers.
- % See whether it's bonus or non-bonus, and
- % gradetable or pointtable:
+ % The question range has already been determined.
+ % Branch according to whether it's bonus, non-bonus, or combined,
+ % and gradetable or pointtable:
\begingroup
% Save the current value of question in @iterator, so that
% we can restore it after doing the table:
@@ -4566,10 +4808,18 @@
\@bvpttblquestions
\fi
\else
- \if@scores
- \@vgrdtblquestions
+ \if@combined
+ \if@scores
+ \@cvgrdtblquestions
+ \else
+ \@cvpttblquestions
+ \fi
\else
- \@vpttblquestions
+ \if@scores
+ \@vgrdtblquestions
+ \else
+ \@vpttblquestions
+ \fi
\fi
\fi
% Restore the saved value of question:
@@ -4577,16 +4827,95 @@
\endgroup
}% @vtblquestions
+\def\@cvgrdtblquestions{%
+ % Vertical combined gradetable, indexed by questions
+ \set@hlfcntr{tbl@points}{0}%
+ \set@hlfcntr{tbl@bonuspoints}{0}%
+ \begin{tabular}{|c|c|c|c|}
+ \hline
+ {\@cvqword}& {\@cvpword}& {\@cvbpword}& {\@cvsword}\\
+ \hline
+ \setcounter{question}{\tbl@firstq}%
+ \addtocounter{question}{-1}\do@cvloop
+ {\@cvtword}& \prt@tablepoints&
+ \prt@tablebonuspoints&
+ \hbox to \@cellwidth{\hfill}\\
+ \hline
+ \end{tabular}%
+}
+\def\do@cvloop{%
+ % \do@cvloop is used by \@cvgrdtblquestions
+ \addtocounter{question}{1}%
+ \ref{question@\arabic{question}} &
+ \pointsofquestion{\arabic{question}}&
+ \bonuspointsofquestion{\arabic{question}}&\\
+ \hline
+ \@ifundefined{pointsofq@\romannumeral \c@question}%
+ {}%
+ {\addto@hlfcntr{tbl@points}
+ {\csname pointsofq@\romannumeral \c@question\endcsname}}%
+ \@ifundefined{bonuspointsofq@\romannumeral \c@question}%
+ {}%
+ {\addto@hlfcntr{tbl@bonuspoints}
+ {\csname bonuspointsofq@\romannumeral \c@question\endcsname}}%
+ \ifnum \value{question} < \tbl@lastq\relax
+ \let\next@cvloop=\do@cvloop
+ \else
+ \let\next@cvloop=\relax
+ \fi
+ \next@cvloop
+}% do@cvloop
+
+
+\def\@cvpttblquestions{%
+ % Vertical combined pointtable, indexed by questions
+ \set@hlfcntr{tbl@points}{0}%
+ \set@hlfcntr{tbl@bonuspoints}{0}%
+ \begin{tabular}{|c|c|c|}
+ \hline
+ {\@cvqword}& {\@cvpword}& {\@cvbpword}\\
+ \hline
+ \setcounter{question}{\tbl@firstq}%
+ \addtocounter{question}{-1}\do@cvptloop
+ {\@cvtword}& \prt@tablepoints&
+ \prt@tablebonuspoints\\
+ \hline
+ \end{tabular}%
+}
+\def\do@cvptloop{%
+ % \do@cvptloop is used by \@cvpttblquestions
+ \addtocounter{question}{1}%
+ \ref{question@\arabic{question}} &
+ \pointsofquestion{\arabic{question}}&
+ \bonuspointsofquestion{\arabic{question}}\\
+ \hline
+ \@ifundefined{pointsofq@\romannumeral \c@question}%
+ {}%
+ {\addto@hlfcntr{tbl@points}
+ {\csname pointsofq@\romannumeral \c@question\endcsname}}%
+ \@ifundefined{bonuspointsofq@\romannumeral \c@question}%
+ {}%
+ {\addto@hlfcntr{tbl@bonuspoints}
+ {\csname bonuspointsofq@\romannumeral \c@question\endcsname}}%
+ \ifnum \value{question} < \tbl@lastq\relax
+ \let\next@cvptloop=\do@cvptloop
+ \else
+ \let\next@cvptloop=\relax
+ \fi
+ \next@cvptloop
+}% do@cvptloop
+
+
\def\@bvgrdtblquestions{%
% Vertical bonus gradetable, indexed by questions:
- \set@hlfcntr{tbl@points}{0}%
+ \set@hlfcntr{tbl@bonuspoints}{0}%
\begin{tabular}{|c|c|c|}
\hline
{\@bvqword}& {\@bvpword}& {\@bvsword}\\
\hline
\setcounter{question}{\tbl@firstq}%
\addtocounter{question}{-1}\do@bvloop
- {\@bvtword}& \prt@hlfcntr{tbl@points}&\hbox to \@cellwidth{\hfill}\\
+ {\@bvtword}& \prt@tablebonuspoints&\hbox to \@cellwidth{\hfill}\\
\hline
\end{tabular}%
}% @bvgrdtblquestions
@@ -4598,7 +4927,7 @@
\hline
\@ifundefined{bonuspointsofq@\romannumeral \c@question}%
{}%
- {\addto@hlfcntr{tbl@points}
+ {\addto@hlfcntr{tbl@bonuspoints}
{\csname bonuspointsofq@\romannumeral \c@question\endcsname}}%
\ifnum \value{question} < \tbl@lastq\relax
\let\next@bvloop=\do@bvloop
@@ -4608,16 +4937,17 @@
\next@bvloop
}% do@bvloop
+
\def\@bvpttblquestions{%
% Vertical bonus point table, indexed by questions:
- \set@hlfcntr{tbl@points}{0}%
+ \set@hlfcntr{tbl@bonuspoints}{0}%
\begin{tabular}{|c|c|}
\hline
{\@bvqword}& {\@bvpword}\\
\hline
\setcounter{question}{\tbl@firstq}%
\addtocounter{question}{-1}\do@bvptloop
- {\@bvtword}& \prt@hlfcntr{tbl@points}\\
+ {\@bvtword}& \prt@tablebonuspoints\\
\hline
\end{tabular}%
}% @bvpttblquestions
@@ -4629,7 +4959,7 @@
\hline
\@ifundefined{bonuspointsofq@\romannumeral \c@question}%
{}%
- {\addto@hlfcntr{tbl@points}
+ {\addto@hlfcntr{tbl@bonuspoints}
{\csname bonuspointsofq@\romannumeral \c@question\endcsname}}%
\ifnum \value{question} < \tbl@lastq\relax
\let\next@bvptloop=\do@bvptloop
@@ -4648,7 +4978,7 @@
\hline
\setcounter{question}{\tbl@firstq}%
\addtocounter{question}{-1}\do@vloop
- {\@vtword}& \prt@hlfcntr{tbl@points}&\hbox to \@cellwidth{\hfill}\\
+ {\@vtword}& \prt@tablepoints&\hbox to \@cellwidth{\hfill}\\
\hline
\end{tabular}%
}% @vgrdtblquestions
@@ -4670,6 +5000,7 @@
\next@vloop
}% do@vloop
+
\def\@vpttblquestions{%
% Vertical non-bonus point table, indexed by questions:
\set@hlfcntr{tbl@points}{0}%
@@ -4679,7 +5010,7 @@
\hline
\setcounter{question}{\tbl@firstq}%
\addtocounter{question}{-1}\do@vptloop
- {\@vtword}& \prt@hlfcntr{tbl@points}\\
+ {\@vtword}& \prt@tablepoints\\
\hline
\end{tabular}%
}% @vpttblquestions
@@ -4706,7 +5037,12 @@
% Horizontal, indexed by question numbers:
\def\@htblquestions{%
+ % We get here from \@tblquestions.
% The table is horizontal and indexed by question numbers.
+ % The question range has already been determined.
+ % Set num@cols equal to the number of questions on the table, and
+ % do either bonus, combined, or non-bonus table, in each case
+ % putting in a line for scores only if it's a gradetable:
\@ifundefined{exam@numquestions}%
{}%
{%
@@ -4714,24 +5050,25 @@
\addtocounter{num@cols}{-\tbl@firstq}%
\addtocounter{num@cols}{1}%
}%
- % See whether it's bonus or non-bonus, and
- % gradetable or pointtable:
+ % Do either bonus, combined, or non-bonus table. In each case, put
+ % in a line for scores if it's a gradetable:
\begingroup
% Save the current value of question in @iterator, so that
% we can restore it after doing the table:
\setcounter{@iterator}{\value{question}}%
\renewcommand\arraystretch{\@gtblstretch}%
\if@bonus
- \set@hlfcntr{tbl@points}{0}%
+ % It's a horizontal bonus table, by questions:
\begin{tabular}{|l|*{\thenum@cols}{c|}c|}
\hline
{\@bhqword}& \setcounter{question}{\tbl@firstq}%
\addtocounter{question}{-1}\do@qnumloop
{\@bhtword}\\
\hline
+ \set@hlfcntr{tbl@bonuspoints}{0}%
{\@bhpword}& \setcounter{question}{\tbl@firstq}%
\addtocounter{question}{-1}\do@bptloop
- \prt@hlfcntr{tbl@points}\\
+ \prt@tablebonuspoints\\
\hline
% If it's a grade table, add in the score line:
\if@scores
@@ -4742,25 +5079,54 @@
\fi
\end{tabular}%
\else
- \set@hlfcntr{tbl@points}{0}%
- \begin{tabular}{|l|*{\thenum@cols}{c|}c|}
- \hline
- {\@hqword}& \setcounter{question}{\tbl@firstq}%
- \addtocounter{question}{-1}\do@qnumloop
- {\@htword}\\
- \hline
- {\@hpword}& \setcounter{question}{\tbl@firstq}%
- \addtocounter{question}{-1}\do@ptloop
- \prt@hlfcntr{tbl@points}\\
- \hline
- % If it's a grade table, add in the score line:
- \if@scores
- {\@hsword}& \setcounter{question}{\tbl@firstq}%
- \addtocounter{question}{-1}\do@sloop
- \\
+ \if@combined
+ % It's a horizontal combined table, by questions:
+ \begin{tabular}{|l|*{\thenum@cols}{c|}c|}
\hline
- \fi
- \end{tabular}%
+ {\@chqword}& \setcounter{question}{\tbl@firstq}%
+ \addtocounter{question}{-1}\do@qnumloop
+ {\@chtword}\\
+ \hline
+ \set@hlfcntr{tbl@points}{0}%
+ {\@chpword}& \setcounter{question}{\tbl@firstq}%
+ \addtocounter{question}{-1}\do@ptloop
+ \prt@tablepoints\\
+ \hline
+ \set@hlfcntr{tbl@bonuspoints}{0}%
+ {\@chbpword}& \setcounter{question}{\tbl@firstq}%
+ \addtocounter{question}{-1}\do@bptloop
+ \prt@tablebonuspoints\\
+ \hline
+ % If it's a grade table, add in the score line:
+ \if@scores
+ {\@chsword}& \setcounter{question}{\tbl@firstq}%
+ \addtocounter{question}{-1}\do@sloop
+ \\
+ \hline
+ \fi
+ \end{tabular}%
+ \else
+ % Horizontal non-bonus table, indexed by question number:
+ \set@hlfcntr{tbl@points}{0}%
+ \begin{tabular}{|l|*{\thenum@cols}{c|}c|}
+ \hline
+ {\@hqword}& \setcounter{question}{\tbl@firstq}%
+ \addtocounter{question}{-1}\do@qnumloop
+ {\@htword}\\
+ \hline
+ {\@hpword}& \setcounter{question}{\tbl@firstq}%
+ \addtocounter{question}{-1}\do@ptloop
+ \prt@tablepoints\\
+ \hline
+ % If it's a grade table, add in the score line:
+ \if@scores
+ {\@hsword}& \setcounter{question}{\tbl@firstq}%
+ \addtocounter{question}{-1}\do@sloop
+ \\
+ \hline
+ \fi
+ \end{tabular}%
+ \fi
\fi
% Restore the saved value of question:
\setcounter{question}{\value{@iterator}}%
@@ -4768,11 +5134,11 @@
}% @htblquestions
-% \do@qnumloop and \do@sloop are used both by non-bonus gradetable and
-% by bonusgradetable:
+% \do@qnumloop and \do@sloop are used by non-bonus,
+% combined, and bonus tables:
\def\do@qnumloop{%
\addtocounter{question}{1}%
- \ref{question@\arabic{question}} &
+ \ref{question@\arabic{question}}&
\ifnum \value{question} < \tbl@lastq\relax
\let\next@qnloop=\do@qnumloop
\else
@@ -4791,7 +5157,7 @@
\next@sloop
}% do@sloop
-% \do@ptloop is used only by non-bonus gradetable:
+% \do@ptloop is used by combined and non-bonus tables:
\def\do@ptloop{%
\addtocounter{question}{1}%
\pointsofquestion{\arabic{question}}&
@@ -4807,13 +5173,13 @@
\next@ptloop
}% do@ptloop
-% \do@bptloop is used only by bonusgradetable:
+% \do@bptloop is used by bonus and combined tables:
\def\do@bptloop{%
\addtocounter{question}{1}%
\bonuspointsofquestion{\arabic{question}}&
\@ifundefined{bonuspointsofq@\romannumeral \c@question}%
{}%
- {\addto@hlfcntr{tbl@points}
+ {\addto@hlfcntr{tbl@bonuspoints}
{\csname bonuspointsofq@\romannumeral \c@question\endcsname}}%
\ifnum \value{question} < \tbl@lastq\relax
\let\next@bptloop=\do@bptloop
@@ -4829,7 +5195,7 @@
% Grade and point tables indexed by page numbers:
-% The only pages listed are those on which there is a nonzero number
+% The only pages listed are those on which there are a nonzero number
% of points. We check pages \tbl@firstp through \tbl@lastp
% Once we've checked that, e.g., \lastpage@withpoints and
% \pointsonpage@\romannumeral{\lastpage@withpoints} are defined, we
@@ -4849,13 +5215,21 @@
% isn't defined, tmp@hlfcntr gets the value zero (because of the way
% that \set@hlfcntr is written).
-
-% \find@prange makes sure the grading range is defined and that
-% its last page isn't before its first page.
-
+% \find@prange makes sure the grading range is defined and that its
+% last page isn't before its first page (if it's a partial table). In
+% any case, it then sets \tbl@firstp and \tbl@lastp, and calls
+% \@tblpages.
\def\find@prange#1{%
% We're doing a table indexed by pages.
+ % The argument is either ``v'' or ``h''.
+ % After determining the first and last page of the range, we
+ % call \@tblpages, passing it that argument (i.e., we say
+ % \@tblpages{#1}).
+ % If not a partial table, we set \tbl@firstp to 1 and \tbl@lastp to
+ % the last page with the appropriate points (and so if it's a
+ % combined table, it's the last page to have either bonus or
+ % non-bonus points).
\if@partial
\@ifundefined{tbl@\tbl@range @firstp}%
{%
@@ -4870,7 +5244,7 @@
\edef\tbl@firstp{\csname tbl@\tbl@range @firstp\endcsname}%
\edef\tbl@lastp{\csname tbl@\tbl@range @lastp\endcsname}%
% Check that firstp precedes or equals lastp:
- \ifnum \tbl@firstp > \tbl@lastp
+ \ifnum \tbl@firstp > \tbl@lastp\relax
\fbox{Error: Grading Range `\tbl@range ':
Last page precedes first page.}%
\ClassError{exam}{%
@@ -4889,20 +5263,25 @@
\def\tbl@firstp{1}%
% \tbl@lastp isn't used on the first run of LaTeX, and
% \lastpage@withbonuspoints is defined on the second and later runs.
+ \def\tbl@lastp{\lastpage@withpoints}%
\if@bonus
\def\tbl@lastp{\lastpage@withbonuspoints}%
- \else
- \def\tbl@lastp{\lastpage@withpoints}%
+ \fi
+ \if@combined
+ \ifnum \lastpage@withbonuspoints > \lastpage@withpoints\relax
+ \def\tbl@lastp{\lastpage@withbonuspoints}%
+ \fi
\fi
\@tblpages{#1}%
\fi
}% find@prange
-
-% Check that there's enough info from the .aux file to do a page
-% indexed grade table:
\def\@tblpages#1{%
+ % We get here from \find@prange; the argument is either ``v'' or
+ % ``h''.
+ % Check that there's enough info from the .aux file to do a page
+ % indexed grade table. If so, call \@whichtblpgs{#1}:
\@ifundefined{lastpage@withpoints}%
{\ClassWarning{exam}{%
You must run LaTeX twice more\MessageBreak
@@ -4927,6 +5306,7 @@
% At this point, we know the table is indexed by pages.
% It can be vertical or horizontal,
% grade or point, and bonus or non-bonus.
+ % The argument is either ``v'' or ``h''; test it, and branch:
\if v#1%
\@vtblpages
\else
@@ -4971,12 +5351,14 @@
% Vertical, indexed by pages:
\def\@vtblpages{%
+ % We get here from \@whchtblpgs.
% At this point, we know it's a vertical table indexed by pages.
- % It can be grade or point, and bonus or non-bonus.
+ % It can be grade or point, and bonus, non-bonus, or combined.
\begingroup
\renewcommand\arraystretch{\@gtblstretch}%
- \set@hlfcntr{tbl@points}{0}%
\if@bonus
+ % It's vertical, bonus, by pages, either point or grade:
+ \set@hlfcntr{tbl@bonuspoints}{0}%
\if@scores
\begin{tabular}{|c|c|c|}
\hline
@@ -4984,7 +5366,8 @@
\hline
\setcounter{@iterator}{\tbl@firstp}%
\addtocounter{@iterator}{-1}\pg@bvloop
- {\@bvtword}& \prt@hlfcntr{tbl@points}&\hbox to \@cellwidth{\hfill}\\
+ {\@bvtword}& \prt@tablebonuspoints&
+ \hbox to \@cellwidth{\hfill}\\
\hline
\end{tabular}%
\else
@@ -4994,31 +5377,65 @@
\hline
\setcounter{@iterator}{\tbl@firstp}%
\addtocounter{@iterator}{-1}\pg@ptbvloop
- {\@bvtword}& \prt@hlfcntr{tbl@points}\\
+ {\@bvtword}& \prt@tablebonuspoints\\
\hline
\end{tabular}%
\fi
\else
- \if@scores
- \begin{tabular}{|c|c|c|}
- \hline
- {\@vpgword}& {\@vpword}& {\@vsword}\\
- \hline
- \setcounter{@iterator}{\tbl@firstp}%
- \addtocounter{@iterator}{-1}\pg@vloop
- {\@vtword}& \prt@hlfcntr{tbl@points}&\hbox to \@cellwidth{\hfill}\\
- \hline
- \end{tabular}%
+ \if@combined
+ % It's vertical, combined, by pages, either point or grade:
+ \set@hlfcntr{tbl@points}{0}%
+ \set@hlfcntr{tbl@bonuspoints}{0}%
+ \if@scores
+ % Combined gradetable, vertical, by pages:
+ \begin{tabular}{|c|c|c|c|}
+ \hline
+ {\@cvpgword}& {\@cvpword}& {\@cvbpword}& {\@cvsword}\\
+ \hline
+ \setcounter{@iterator}{\tbl@firstp}%
+ \addtocounter{@iterator}{-1}\pg@cvloop
+ {\@cvtword}& \prt@tablepoints&
+ \prt@tablebonuspoints&
+ \hbox to \@cellwidth{\hfill}\\
+ \hline
+ \end{tabular}%
+ \else
+ % Combined pointtable, vertical, by pages:
+ \begin{tabular}{|c|c|c|}
+ \hline
+ {\@cvpgword}& {\@cvpword}& {\@cvbpword}\\
+ \hline
+ \setcounter{@iterator}{\tbl@firstp}%
+ \addtocounter{@iterator}{-1}\pg@ptcvloop
+ {\@cvtword}& \prt@tablepoints&
+ \prt@tablebonuspoints\\
+ \hline
+ \end{tabular}%
+ \fi
\else
- \begin{tabular}{|c|c|}
- \hline
- {\@vpgword}& {\@vpword}\\
- \hline
- \setcounter{@iterator}{\tbl@firstp}%
- \addtocounter{@iterator}{-1}\pg@ptvloop
- {\@vtword}& \prt@hlfcntr{tbl@points}\\
- \hline
- \end{tabular}%
+ % It's non-bonus, either point or grade:
+ \set@hlfcntr{tbl@points}{0}%
+ \if@scores
+ \begin{tabular}{|c|c|c|}
+ \hline
+ {\@vpgword}& {\@vpword}& {\@vsword}\\
+ \hline
+ \setcounter{@iterator}{\tbl@firstp}%
+ \addtocounter{@iterator}{-1}\pg@vloop
+ {\@vtword}& \prt@tablepoints&\hbox to \@cellwidth{\hfill}\\
+ \hline
+ \end{tabular}%
+ \else
+ \begin{tabular}{|c|c|}
+ \hline
+ {\@vpgword}& {\@vpword}\\
+ \hline
+ \setcounter{@iterator}{\tbl@firstp}%
+ \addtocounter{@iterator}{-1}\pg@ptvloop
+ {\@vtword}& \prt@tablepoints\\
+ \hline
+ \end{tabular}%
+ \fi
\fi
\fi
\endgroup
@@ -5028,9 +5445,7 @@
% \pg@ptvloop and \pg@ptvloopline are used only by non-bonus pointtable:
\def\pg@ptvloop{%
\addtocounter{@iterator}{1}%
- % spanish.ldf redefines \@roman, so we'll avoid using \roman:
- \set@hlfcntr{tmp@hlfcntr}{\csname pointsonpage@\romannumeral
- \csname c@@iterator\endcsname\endcsname}%
+ \set@hlfcntr{tmp@hlfcntr}{\pointsonpage{\the@iterator}}%
\ifhlfcntr@pos{tmp@hlfcntr}%
\add@hlfcntrtohlfcntr{tbl@points}{tmp@hlfcntr}%
\pg@ptvloopline
@@ -5055,9 +5470,7 @@
% \pg@vloop and \pg@vloopline are used only by non-bonus gradetable:
\def\pg@vloop{%
\addtocounter{@iterator}{1}%
- % spanish.ldf redefines \@roman, so we'll avoid using \roman:
- \set@hlfcntr{tmp@hlfcntr}{\csname pointsonpage@\romannumeral
- \csname c@@iterator\endcsname\endcsname}%
+ \set@hlfcntr{tmp@hlfcntr}{\pointsonpage{\the@iterator}}%
\ifhlfcntr@pos{tmp@hlfcntr}%
\add@hlfcntrtohlfcntr{tbl@points}{tmp@hlfcntr}%
\pg@vloopline
@@ -5079,14 +5492,123 @@
\hline
}% pg@vloopline
+% \pg@cvloop, \pg@noncvloopline, \check@bnspts, and
+% \pg@cvloopline are used only by combined gradetable:
+\def\pg@cvloop{%
+ \addtocounter{@iterator}{1}%
+ % Add the bonus points:
+ \set@hlfcntr{tmp@hlfcntr}{\bonuspointsonpage{\the@iterator}}%
+ \add@hlfcntrtohlfcntr{tbl@bonuspoints}{tmp@hlfcntr}%
+ % Add the regular points:
+ \set@hlfcntr{tmp@hlfcntr}{\csname pointsonpage@\romannumeral
+ \csname c@@iterator\endcsname\endcsname}%
+ \add@hlfcntrtohlfcntr{tbl@points}{tmp@hlfcntr}%
+ % Print a line of the table, if there are points on this page:
+ \ifhlfcntr@pos{tmp@hlfcntr}%
+ \pg@noncvloopline
+ \else
+ \check@bnspts
+ \fi
+ % Do the tail recursion bit:
+ \ifnum \the@iterator < \tbl@lastp\relax
+ \let\next@pg@cvloop=\pg@cvloop
+ \else
+ \let\next@pg@cvloop=\relax
+ \fi
+ \next@pg@cvloop
+}% pg@cvloop
+\def\pg@noncvloopline{%
+ % We still don't understand why we need to hide this inside of a
+ % macro; there's some weird interaction with the \ifnum checking to
+ % see if something is ``>0''; checking that something is ``=0''
+ % doesn't cause the ``\ifnum incomplete'' (or whatever) error.
+ \pageref{firstpoints@onpage@\arabic{@iterator}}&
+ \pointsonpage{\the@iterator}&
+ \bonuspointsonpage{\the@iterator}&\\
+ \hline
+}% pg@noncvloopline
+\def\check@bnspts{%
+ % We still don't understand why we need to hide this inside of a
+ % macro; there's some weird interaction with the \ifnum checking to
+ % see if something is ``>0''; checking that something is ``=0''
+ % doesn't cause the ``\ifnum incomplete'' (or whatever) error.
+ \set@hlfcntr{tmp@hlfcntr}{\bonuspointsonpage{\the@iterator}}%
+ \ifhlfcntr@pos{tmp@hlfcntr}%
+ \pg@cvloopline
+ \fi
+}% check@bnspts
+\def\pg@cvloopline{%
+ % We still don't understand why we need to hide this inside of a
+ % macro; there's some weird interaction with the \ifnum checking to
+ % see if something is ``>0''; checking that something is ``=0''
+ % doesn't cause the ``\ifnum incomplete'' (or whatever) error.
+ \pageref{firstbonuspoints@onpage@\arabic{@iterator}}&
+ \pointsonpage{\the@iterator}&
+ \bonuspointsonpage{\the@iterator}&\\
+ \hline
+}% pg@cvloopline
+
+% \pg@ptcvloop, \pg@ptnoncvloopline, \check@ptbnspts, and
+% \pg@ptcvloopline are used only by combined pointtable:
+\def\pg@ptcvloop{%
+ \addtocounter{@iterator}{1}%
+ % Add the bonus points:
+ \set@hlfcntr{tmp@hlfcntr}{\bonuspointsonpage{\the@iterator}}%
+ \add@hlfcntrtohlfcntr{tbl@bonuspoints}{tmp@hlfcntr}%
+ % Add the regular points:
+ \set@hlfcntr{tmp@hlfcntr}{\pointsonpage{\the@iterator}}%
+ \add@hlfcntrtohlfcntr{tbl@points}{tmp@hlfcntr}%
+ % Print a line of the table, if there are points on this page:
+ \ifhlfcntr@pos{tmp@hlfcntr}%
+ \pg@ptnoncvloopline
+ \else
+ \check@ptbnspts
+ \fi
+ % Do the tail recursion bit:
+ \ifnum \the@iterator < \tbl@lastp\relax
+ \let\next@pg@ptcvloop=\pg@ptcvloop
+ \else
+ \let\next@pg@ptcvloop=\relax
+ \fi
+ \next@pg@ptcvloop
+}% pg@ptcvloop
+\def\pg@ptnoncvloopline{%
+ % We still don't understand why we need to hide this inside of a
+ % macro; there's some weird interaction with the \ifnum checking to
+ % see if something is ``>0''; checking that something is ``=0''
+ % doesn't cause the ``\ifnum incomplete'' (or whatever) error.
+ \pageref{firstpoints@onpage@\arabic{@iterator}}&
+ \pointsonpage{\the@iterator}&
+ \bonuspointsonpage{\the@iterator}\\
+ \hline
+}% pg@ptnoncvloopline
+\def\check@ptbnspts{%
+ % We still don't understand why we need to hide this inside of a
+ % macro; there's some weird interaction with the \ifnum checking to
+ % see if something is ``>0''; checking that something is ``=0''
+ % doesn't cause the ``\ifnum incomplete'' (or whatever) error.
+ \set@hlfcntr{tmp@hlfcntr}{\bonuspointsonpage{\the@iterator}}%
+ \ifhlfcntr@pos{tmp@hlfcntr}%
+ \pg@ptcvloopline
+ \fi
+}% check@ptbnspts
+\def\pg@ptcvloopline{%
+ % We still don't understand why we need to hide this inside of a
+ % macro; there's some weird interaction with the \ifnum checking to
+ % see if something is ``>0''; checking that something is ``=0''
+ % doesn't cause the ``\ifnum incomplete'' (or whatever) error.
+ \pageref{firstbonuspoints@onpage@\arabic{@iterator}}&
+ \pointsonpage{\the@iterator}&
+ \bonuspointsonpage{\the@iterator}\\
+ \hline
+}% pg@ptcvloopline
+
% \pg@bvloop and \pg@bvloopline are used only by bonus gradetable:
\def\pg@bvloop{%
\addtocounter{@iterator}{1}%
- % spanish.ldf redefines \@roman, so we'll avoid using \roman:
- \set@hlfcntr{tmp@hlfcntr}{\csname bonuspointsonpage@\romannumeral
- \csname c@@iterator\endcsname\endcsname}%
+ \set@hlfcntr{tmp@hlfcntr}{\bonuspointsonpage{\the@iterator}}%
\ifhlfcntr@pos{tmp@hlfcntr}%
- \add@hlfcntrtohlfcntr{tbl@points}{tmp@hlfcntr}%
+ \add@hlfcntrtohlfcntr{tbl@bonuspoints}{tmp@hlfcntr}%
\pg@bvloopline
\fi
\ifnum \the@iterator < \tbl@lastp\relax
@@ -5109,11 +5631,9 @@
% \pg@ptbvloop and \pg@ptbvloopline are used only by bonus pointtable:
\def\pg@ptbvloop{%
\addtocounter{@iterator}{1}%
- % spanish.ldf redefines \@roman, so we'll avoid using \roman:
- \set@hlfcntr{tmp@hlfcntr}{\csname bonuspointsonpage@\romannumeral
- \csname c@@iterator\endcsname\endcsname}%
+ \set@hlfcntr{tmp@hlfcntr}{\bonuspointsonpage{\the@iterator}}%
\ifhlfcntr@pos{tmp@hlfcntr}%
- \add@hlfcntrtohlfcntr{tbl@points}{tmp@hlfcntr}%
+ \add@hlfcntrtohlfcntr{tbl@bonuspoints}{tmp@hlfcntr}%
\pg@ptbvloopline
\fi
\ifnum \the@iterator < \tbl@lastp\relax
@@ -5140,25 +5660,56 @@
% pages there are with points on them:
\newcounter{num@cols}
\def\count@pgswpts{%
+ % We're called by \@htblpages.
% \count@pgswpts is used for horizontal
- % grade tables and point tables, both
- % bonus and non-bonus.
+ % grade tables and point tables,
+ % bonus, non-bonus, and combined.
\setcounter{num@cols}{0}%
\setcounter{@iterator}{\tbl@firstp}%
\addtocounter{@iterator}{-1}%
\if@bonus
\docount@pgswbpts
\else
- \docount@pgswpts
+ \if@combined
+ \docount@pgswcpts
+ \else
+ \docount@pgswpts
+ \fi
\fi
}% count@pgswpts
-% \docount@pgswpts is used for non-bonus gradetable:
+\def\docount@pgswcpts{%
+ % Called by \count@pgswpts
+ % \docount@pgswcpts is used for combined gradetable.
+ % Count the number of pages in range with any kind of point (bonus
+ % or non-bonus):
+ \addtocounter{@iterator}{1}%
+ \set@hlfcntr{tmp@hlfcntr}{\pointsonpage{\the@iterator}}%
+ \ifhlfcntr@pos{tmp@hlfcntr}%
+ \addtocounter{num@cols}{1}%
+ \else
+ \check@bnsptpage
+ \fi
+ \ifnum \the@iterator < \tbl@lastp\relax
+ \let\next@docount=\docount@pgswcpts
+ \else
+ \let\next@docount=\relax
+ \fi
+ \next@docount
+}% docount@pgswcpts
+\def\check@bnsptpage{%
+ % We don't understand why we need to hide this inside of a macro:
+ \set@hlfcntr{tmp@hlfcntr}{\bonuspointsonpage{\the@iterator}}%
+ \ifhlfcntr@pos{tmp@hlfcntr}%
+ \addtocounter{num@cols}{1}%
+ \fi
+}% check@bnsptpage
+
\def\docount@pgswpts{%
+ % Called by \count@pgswpts
+ % \docount@pgswpts is used for non-bonus gradetable:
\addtocounter{@iterator}{1}%
- % spanish.ldf redefines \@roman, so we'll avoid using \roman:
- \set@hlfcntr{tmp@hlfcntr}{\csname pointsonpage@\romannumeral
- \csname c@@iterator\endcsname\endcsname}%
+ \set@hlfcntr{tmp@hlfcntr}{\pointsonpage{\the@iterator}}%
\ifhlfcntr@pos{tmp@hlfcntr}%
\addtocounter{num@cols}{1}%
\fi
@@ -5170,12 +5721,11 @@
\next@docount
}% docount@pgswpts
-% \docount@pgswbpts is used for bonusgradetable:
\def\docount@pgswbpts{%
+ % Called by \count@pgswpts
+ % \docount@pgswbpts is used for bonusgradetable:
\addtocounter{@iterator}{1}%
- % spanish.ldf redefines \@roman, so we'll avoid using \roman:
- \set@hlfcntr{tmp@hlfcntr}{\csname bonuspointsonpage@\romannumeral
- \csname c@@iterator\endcsname\endcsname}%
+ \set@hlfcntr{tmp@hlfcntr}{\bonuspointsonpage{\the@iterator}}%
\ifhlfcntr@pos{tmp@hlfcntr}%
\addtocounter{num@cols}{1}%
\fi
@@ -5190,15 +5740,21 @@
%--------------------------------------------------------------------
\def\@htblpages{%
+ % We get here from \@whchtblpgs.
+ % Horizontal grade or point table, by pages:
\begingroup
\renewcommand\arraystretch{\@gtblstretch}%
+ % Set num@cols equal to the number of pages with points (of
+ % correct type):
\count@pgswpts
% Suppress ``extra alignment tab'' errors if \thenum@cols = 0:
- \ifnum \thenum@cols = 0
+ \ifnum \thenum@cols = 0\relax
\setcounter{num@cols}{1}%
\fi
\set@hlfcntr{tbl@points}{0}%
+ \set@hlfcntr{tbl@bonuspoints}{0}%
\if@bonus
+ % Horizontal bonus grade or point table, by pages:
\begin{tabular}{|l|*{\thenum@cols}{c|}c|}
\hline
{\@bhpgword}& \setcounter{@iterator}{\tbl@firstp}%
@@ -5207,7 +5763,7 @@
\hline
{\@bhpword}& \setcounter{@iterator}{\tbl@firstp}%
\addtocounter{@iterator}{-1}\do@bpgptloop
- \prt@hlfcntr{tbl@points}\\
+ \prt@tablebonuspoints\\
\hline
% If it's a grade table, do the line for scores:
\if@scores
@@ -5218,35 +5774,62 @@
\fi
\end{tabular}%
\else
- \begin{tabular}{|l|*{\thenum@cols}{c|}c|}
- \hline
- {\@hpgword}& \setcounter{@iterator}{\tbl@firstp}%
- \addtocounter{@iterator}{-1}\do@pgnumloop
- {\@htword}\\
- \hline
- {\@hpword}& \setcounter{@iterator}{\tbl@firstp}%
- \addtocounter{@iterator}{-1}\do@pgptloop
- \prt@hlfcntr{tbl@points}\\
- \hline
- % If it's a grade table, do the line for scores:
- \if@scores
- {\@hsword}& \setcounter{@iterator}{\tbl@firstp}%
- \addtocounter{@iterator}{-1}\do@pgsloop
- \\
+ \if@combined
+ % Horizontal combined grade or point table, by pages:
+ \begin{tabular}{|l|*{\thenum@cols}{c|}c|}
\hline
- \fi
- \end{tabular}%
+ {\@chpgword}& \setcounter{@iterator}{\tbl@firstp}%
+ \addtocounter{@iterator}{-1}\do@cpgnumloop
+ {\@chtword}\\
+ \hline
+ {\@chpword}& \setcounter{@iterator}{\tbl@firstp}%
+ \addtocounter{@iterator}{-1}\do@cpgptloop
+ \prt@tablepoints\\
+ \hline
+ {\@chbpword}& \setcounter{@iterator}{\tbl@firstp}%
+ \addtocounter{@iterator}{-1}\do@cbpgptloop
+ \prt@tablebonuspoints\\
+ \hline
+ % If it's a grade table, do the line for scores:
+ \if@scores
+ {\@chsword}& \setcounter{@iterator}{\tbl@firstp}%
+ \addtocounter{@iterator}{-1}\do@cpgsloop
+ \\
+ \hline
+ \fi
+ \end{tabular}%
+ \else
+ % Horizontal non-bonus grade or point table, by pages:
+ \begin{tabular}{|l|*{\thenum@cols}{c|}c|}
+ \hline
+ {\@hpgword}& \setcounter{@iterator}{\tbl@firstp}%
+ \addtocounter{@iterator}{-1}\do@pgnumloop
+ {\@htword}\\
+ \hline
+ {\@hpword}& \setcounter{@iterator}{\tbl@firstp}%
+ \addtocounter{@iterator}{-1}\do@pgptloop
+ \prt@tablepoints\\
+ \hline
+ % If it's a grade table, do the line for scores:
+ \if@scores
+ {\@hsword}& \setcounter{@iterator}{\tbl@firstp}%
+ \addtocounter{@iterator}{-1}\do@pgsloop
+ \\
+ \hline
+ \fi
+ \end{tabular}%
+ \fi
\fi
\endgroup
}% @htblpages
-% \do@pgnumloop, \pg@line, \do@pgptloop, \pgpt@line, \do@pgsloop, and
-% \pg@sline are only for non-bonus gradetable:
+%--------------------------------------------------------------------
+% \do@pgnumloop, \do@pgptloop, and \do@pgsloop
+% are only for non-bonus gradetable.
+% \pg@line is also for combinedgradetable.
\def\do@pgnumloop{%
\addtocounter{@iterator}{1}%
- % spanish.ldf redefines \@roman, so we'll avoid using \roman:
- \set@hlfcntr{tmp@hlfcntr}{\csname pointsonpage@\romannumeral
- \csname c@@iterator\endcsname\endcsname}%
+ \set@hlfcntr{tmp@hlfcntr}{\pointsonpage{\the@iterator}}%
\ifhlfcntr@pos{tmp@hlfcntr}%
\pg@line
\fi
@@ -5258,17 +5841,16 @@
\next@pgnumloop
}% \do@pgnumloop
\def\pg@line{%
+ % We still don't know why we need to hide this inside of a macro:
\pageref{firstpoints@onpage@\arabic{@iterator}}&
}% \pg@line
\def\do@pgptloop{%
\addtocounter{@iterator}{1}%
- % spanish.ldf redefines \@roman, so we'll avoid using \roman:
- \set@hlfcntr{tmp@hlfcntr}{\csname pointsonpage@\romannumeral
- \csname c@@iterator\endcsname\endcsname}%
+ \set@hlfcntr{tmp@hlfcntr}{\pointsonpage{\the@iterator}}%
\ifhlfcntr@pos{tmp@hlfcntr}%
\add@hlfcntrtohlfcntr{tbl@points}{tmp@hlfcntr}%
- \pgpt@line
+ \pgpt@entry
\fi
\ifnum \the@iterator < \tbl@lastp\relax
\let\next@pgptloop=\do@pgptloop
@@ -5277,20 +5859,17 @@
\fi
\next@pgptloop
}% \do@pgptloop
-\def\pgpt@line{%
- % spanish.ldf redefines \@roman, so we'll avoid using \roman:
- \csname pointsonpage@\romannumeral
- \csname c@@iterator\endcsname\endcsname &
-}% \pgpt@line
+% \pgpt@entry is used by different macros:
+\def\pgpt@entry{%
+ % We still don't know why we need to hide this inside of a macro:
+ \pointsonpage{\the@iterator}&
+}% \pgpt@entry
\def\do@pgsloop{%
\addtocounter{@iterator}{1}%
- % spanish.ldf redefines \@roman, so we'll avoid using \roman:
- \set@hlfcntr{tmp@hlfcntr}{\csname pointsonpage@\romannumeral
- \csname c@@iterator\endcsname\endcsname}%
+ \set@hlfcntr{tmp@hlfcntr}{\pointsonpage{\the@iterator}}%
\ifhlfcntr@pos{tmp@hlfcntr}%
- \add@hlfcntrtohlfcntr{tbl@points}{tmp@hlfcntr}%
- \pg@sline
+ \pg@sentry
\fi
\ifnum \the@iterator < \tbl@lastp\relax
\let\next@pgsloop=\do@pgsloop
@@ -5299,20 +5878,22 @@
\fi
\next@pgsloop
}% \do@pgsloop
-\def\pg@sline{%
+% \pg@sentry is called by several different macros,
+% to create different tables:
+\def\pg@sentry{%
+ % We still don't know why we need to hide this inside of a macro:
\hbox to \@cellwidth{\hfill}&
-}% \pg@sline
+}% \pg@sentry
%--------------------------------------------------------------------
% These things are for bonusgradetable:
-% \do@bpgnumloop, \bpg@line, \do@bpgptloop, \bpgpt@line, \do@bpgsloop,
-% and \bpg@sline are only for bonusgradetable:
+% \do@bpgnumloop, \do@bpgptloop, \do@bpgsloop,
+% and \bpg@sline are only for bonusgradetable.
+% \bpg@line is also used for combinedgradetable.
\def\do@bpgnumloop{%
\addtocounter{@iterator}{1}%
- % spanish.ldf redefines \@roman, so we'll avoid using \roman:
- \set@hlfcntr{tmp@hlfcntr}{\csname bonuspointsonpage@\romannumeral
- \csname c@@iterator\endcsname\endcsname}%
+ \set@hlfcntr{tmp@hlfcntr}{\bonuspointsonpage{\the@iterator}}%
\ifhlfcntr@pos{tmp@hlfcntr}%
\bpg@line
\fi
@@ -5324,16 +5905,15 @@
\next@bpgnumloop
}% do@bpgnumloop
\def\bpg@line{%
+ % We still don't know why we need to hide this inside of a macro:
\pageref{firstbonuspoints@onpage@\arabic{@iterator}}&
}% bpg@line
\def\do@bpgptloop{%
\addtocounter{@iterator}{1}%
- % spanish.ldf redefines \@roman, so we'll avoid using \roman:
- \set@hlfcntr{tmp@hlfcntr}{\csname bonuspointsonpage@\romannumeral
- \csname c@@iterator\endcsname\endcsname}%
+ \set@hlfcntr{tmp@hlfcntr}{\bonuspointsonpage{\the@iterator}}%
\ifhlfcntr@pos{tmp@hlfcntr}%
- \add@hlfcntrtohlfcntr{tbl@points}{tmp@hlfcntr}%
+ \add@hlfcntrtohlfcntr{tbl@bonuspoints}{tmp@hlfcntr}%
\bpgpt@line
\fi
\ifnum \the@iterator < \tbl@lastp\relax
@@ -5343,20 +5923,17 @@
\fi
\next@bpgptloop
}% do@bpgptloop
+% \bpgpt@line is called by several macros:
\def\bpgpt@line{%
- % spanish.ldf redefines \@roman, so we'll avoid using \roman:
- \csname bonuspointsonpage@\romannumeral
- \csname c@@iterator\endcsname\endcsname &
+ % We still don't know why we need to hide this inside of a macro:
+ \bonuspointsonpage{\the@iterator}&
}% bpgpt@line
\def\do@bpgsloop{%
\addtocounter{@iterator}{1}%
- % spanish.ldf redefines \@roman, so we'll avoid using \roman:
- \set@hlfcntr{tmp@hlfcntr}{\csname bonuspointsonpage@\romannumeral
- \csname c@@iterator\endcsname\endcsname}%
+ \set@hlfcntr{tmp@hlfcntr}{\bonuspointsonpage{\the@iterator}}%
\ifhlfcntr@pos{tmp@hlfcntr}%
- \add@hlfcntrtohlfcntr{tbl@points}{tmp@hlfcntr}%
- \bpg@sline
+ \pg@sentry
\fi
\ifnum \the@iterator < \tbl@lastp\relax
\let\next@bpgsloop=\do@bpgsloop
@@ -5365,9 +5942,193 @@
\fi
\next@bpgsloop
}% do@bpgsloop
-\def\bpg@sline{%
- \hbox to \@cellwidth{\hfill}&
-}% bpg@sline
+
+%--------------------------------------------------------------------
+% These things are for combinedgradetable:
+
+% \do@cpgnumloop, \cpg@line, \cbpg@line, \do@cpgptloop, \bpgpt@line,
+% \do@cpgsloop, \bpg@sline, and \do@cbpgptloop are only for
+% combinedgradetable:
+\def\do@cpgnumloop{%
+ \addtocounter{@iterator}{1}%
+ \set@hlfcntr{tmp@hlfcntr}{\pointsonpage{\the@iterator}}%
+ \ifhlfcntr@pos{tmp@hlfcntr}%
+ \pg@line
+ \else
+ \check@bpgpts
+ \fi
+ \ifnum \the@iterator < \tbl@lastp\relax
+ \let\next@cpgnumloop=\do@cpgnumloop
+ \else
+ \let\next@cpgnumloop=\relax
+ \fi
+ \next@cpgnumloop
+}% do@bpgnumloop
+\def\check@bpgpts{%
+ \set@hlfcntr{tmp@hlfcntr}{\bonuspointsonpage{\the@iterator}}%
+ \ifhlfcntr@pos{tmp@hlfcntr}%
+ \bpg@line
+ \fi
+}% check@bpgpts
+
+\def\do@cpgptloop{%
+ \addtocounter{@iterator}{1}%
+ \set@hlfcntr{tmp@hlfcntr}{\pointsonpage{\the@iterator}}%
+ \ifhlfcntr@pos{tmp@hlfcntr}%
+ \add@hlfcntrtohlfcntr{tbl@points}{tmp@hlfcntr}%
+ \pgpt@entry
+ \else
+ \check@cbpts
+ \fi
+ \ifnum \the@iterator < \tbl@lastp\relax
+ \let\next@cpgptloop=\do@cpgptloop
+ \else
+ \let\next@cpgptloop=\relax
+ \fi
+ \next@cpgptloop
+}% do@cpgptloop
+\def\check@cbpts{%
+ \set@hlfcntr{tmp@hlfcntr}{\bonuspointsonpage{\the@iterator}}%
+ \ifhlfcntr@pos{tmp@hlfcntr}%
+ \pgpt@entry
+ \fi
+}% check@cbpts
+
+\def\do@cbpgptloop{%
+ \addtocounter{@iterator}{1}%
+ \set@hlfcntr{tmp@hlfcntr}{\bonuspointsonpage{\the@iterator}}%
+ \ifhlfcntr@pos{tmp@hlfcntr}%
+ \add@hlfcntrtohlfcntr{tbl@bonuspoints}{tmp@hlfcntr}%
+ \bpgpt@line
+ \else
+ \check@cnonpts
+ \fi
+ \ifnum \the@iterator < \tbl@lastp\relax
+ \let\next@cbpgptloop=\do@cbpgptloop
+ \else
+ \let\next@cbpgptloop=\relax
+ \fi
+ \next@cbpgptloop
+}% do@cbpgptloop
+\def\check@cnonpts{%
+ \set@hlfcntr{tmp@hlfcntr}{\pointsonpage{\the@iterator}}%
+ \ifhlfcntr@pos{tmp@hlfcntr}%
+ \bpgpt@line
+ \fi
+}% check@cnonpts
+
+\def\do@cpgsloop{%
+ \addtocounter{@iterator}{1}%
+ \set@hlfcntr{tmp@hlfcntr}{\pointsonpage{\the@iterator}}%
+ \ifhlfcntr@pos{tmp@hlfcntr}%
+ \pg@sentry
+ \else
+ \check@bnsline
+ \fi
+ \ifnum \the@iterator < \tbl@lastp\relax
+ \let\next@cpgsloop=\do@cpgsloop
+ \else
+ \let\next@cpgsloop=\relax
+ \fi
+ \next@cpgsloop
+}% do@cpgsloop
+\def\check@bnsline{%
+ \set@hlfcntr{tmp@hlfcntr}{\bonuspointsonpage{\the@iterator}}%
+ \ifhlfcntr@pos{tmp@hlfcntr}%
+ \pg@sentry
+ \fi
+}% check@bnsline
+
+%--------------------------------------------------------------------
+% \pointsinrange and \bonuspointsinrange:
+% We say either \@bonusfalse or \@bonustrue, and then we check it only
+% in \do@countloop:
+\def\pointsinrange#1{%
+ \@bonusfalse
+ \def\tbl@range{#1}%
+ \@ifundefined{exam@numpoints}%
+ {\mbox{\normalfont\bf ??}}%
+ {\read@range}%
+}% pointsinrange
+
+\def\bonuspointsinrange#1{%
+ \@bonustrue
+ \def\tbl@range{#1}%
+ \@ifundefined{exam@numpoints}%
+ {\mbox{\normalfont\bf ??}}%
+ {\read@range}%
+}% bonuspointsinrange
+
+\def\bad@range{%
+ {\mbox{\normalfont\bf ??}}%
+ \ClassWarning{exam}{%
+ Grading range `\tbl@range ' not defined.\MessageBreak
+ \space\space Run LaTeX again.\MessageBreak
+ }%
+}% bad@range
+
+\def\read@range{%
+ \@ifundefined{tbl@\tbl@range @firstq}%
+ {%
+ \bad@range
+ }%
+ {%
+ \@ifundefined{tbl@\tbl@range @lastq}%
+ {%
+ \bad@range
+ }%
+ {%
+ \edef\tbl@firstq{\csname tbl@\tbl@range @firstq\endcsname}%
+ \edef\tbl@lastq{\csname tbl@\tbl@range @lastq\endcsname}%
+ % Check that firstq precedes or equals lastq:
+ \ifnum \tbl@firstq > \tbl@lastq\relax
+ \fbox{Error: Grading Range `\tbl@range ':
+ Last question precedes first question.}%
+ \ClassError{exam}{%
+ In grading range `\tbl@range ',
+ the last question\MessageBreak
+ \space\space comes before the first question.\MessageBreak
+ }{%
+ \string\begingradingrange \space must precede
+ \string\endgradingrange \space by at
+ least one question.\MessageBreak
+ }%
+ \else
+ \count@pointsinrange
+ \fi
+ }%
+ }%
+}% read@range
+
+\def\count@pointsinrange{%
+ % Used for both \pointsinrange and \bonuspointsinrange:
+ \set@hlfcntr{tbl@points}{0}%
+ \setcounter{@iterator}{\tbl@firstq}%
+ \addtocounter{@iterator}{-1}\do@countloop
+ \prt@hlfcntr{tbl@points}%
+}% count@pointsinrange
+\def\do@countloop{%
+ % We check \if@bonus here when needed:
+ \addtocounter{@iterator}{1}%
+ \if@bonus
+ \@ifundefined{bonuspointsofq@\romannumeral \c@@iterator}%
+ {}%
+ {\addto@hlfcntr{tbl@points}
+ {\csname bonuspointsofq@\romannumeral \c@@iterator\endcsname}}%
+ \else
+ \@ifundefined{pointsofq@\romannumeral \c@@iterator}%
+ {}%
+ {\addto@hlfcntr{tbl@points}
+ {\csname pointsofq@\romannumeral \c@@iterator\endcsname}}%
+ \fi
+ \ifnum \value{@iterator} < \tbl@lastq\relax
+ \let\next@countloop=\do@countloop
+ \else
+ \let\next@countloop=\relax
+ \fi
+ \next@countloop
+}% do@countloop
+
%--------------------------------------------------------------------
@@ -5388,80 +6149,164 @@
\def\printanswers{\printanswerstrue}
\def\noprintanswers{\printanswersfalse}
+% If the documentclass options include ``cancelspace'', then the
+% command \cancelspacetrue is given at the beginning of the run.
+
+% If the documentclass options include ``nocancelspace'', then the
+% command \cancelspacefalse is given at the beginning of the run.
+
+\def\cancelspace{\cancelspacetrue}
+\def\nocancelspace{\cancelspacefalse}
+
+\newcommand\SolutionEmphasis[1]{%
+ \def\Solution@Emphasis{#1}%
+}
+\SolutionEmphasis{}
% If printanswers is true, we print the solution using a TheSolution
-% environment. If printanswers is false, we insert blank vertical
-% space equal to the optional argument (the default value of which is
-% 0pt).
+% environment. If printanswers is false and cancelspace is false, we
+% insert blank vertical space equal to the optional argument (the
+% default value of which is 0pt).
\newenvironment{solution}[1][0pt]%
{%
\ifprintanswers
+ \begingroup
+ \Solution@Emphasis
\begin{TheSolution}%
\else
- \par
- \vspace*{#1}%
+ \ifcancelspace
+ % Do nothing
+ \else
+ \par
+ \penalty 0
+ \vspace*{#1}%
+ \fi
\setbox\z@\vbox\bgroup
\fi
}{%
\ifprintanswers
\end{TheSolution}%
+ \endgroup
\else
\egroup
\fi
}%
% If printanswers is true, we print the solution using a TheSolution
-% environment. If printanswers is false, we insert lined vertical
-% space equal to the optional argument (the default value of which is
-% 0pt).
+% environment. If printanswers is false and cancelspace is false,
+% we insert an empty box of width the current line width and of
+% height equal to the optional argument, which can be a length, or
+% \fill, or \stretch{number}. If the optional argument is omitted,
+% then the box is entirely omitted when printanswers is false.
+\newenvironment{solutionorbox}[1][-1pt]%
+ {%
+ \ifprintanswers
+ \begingroup
+ \Solution@Emphasis
+ \begin{TheSolution}%
+ \else
+ \ifcancelspace
+ % Do nothing
+ \else
+ \par
+ % Note: It's important that the following test be
+ % ``\ifdim 0pt > #1'' rather than ``\ifdim #1 < 0pt''
+ % That's because if the user says
+ % ``\begin{solutionorbox}{\stretch{1}}''
+ % (or \stretch{anythingelse}), then this will expand to
+ % ``\ifdim 0pt > \z@ plus 1fill\relax''.
+ % The \ifdim will be ``\ifdim 0pt > \z@'', and we'll have
+ % ``plus 1fill\relax'' left over. This is OK because if the
+ % \ifdim is false, that leftover stuff will be ignored,
+ % and it will only be true if the user omitted the optional
+ % argument, in which case there's no \stretch and thus no
+ % left over part.
+ % If we said ``\ifdim #1 < 0pt'', then we'd get an error
+ % when the user used \stretch, since the leftover stuff
+ % would appear when TeX was looking for <, =, or >.
+ \ifdim 0pt > #1
+ % do nothing
+ \else
+ \makeemptybox{#1}%
+ \fi
+ \fi
+ \setbox\z@\vbox\bgroup
+ \fi
+ }{%
+ \ifprintanswers
+ \end{TheSolution}%
+ \endgroup
+ \else
+ \egroup
+ \fi
+ }%
+
+% If printanswers is true, we print the solution using a TheSolution
+% environment. If printanswers is false and cancelspace is false,
+% we insert lined vertical space equal to the optional argument (the
+% default value of which is 0pt).
\newenvironment{solutionorlines}[1][0pt]%
{%
\ifprintanswers
+ \begingroup
+ \Solution@Emphasis
\begin{TheSolution}%
\else
- \par
- \fillwithlines{#1}%
+ \ifcancelspace
+ % Do nothing
+ \else
+ \par
+ \penalty 0
+ \fillwithlines{#1}%
+ \fi
\setbox\z@\vbox\bgroup
\fi
}{%
\ifprintanswers
\end{TheSolution}%
+ \endgroup
\else
\egroup
\fi
}%
-
% If printanswers is true, we print the solution using a TheSolution
-% environment. If printanswers is false, we insert dotted lined
-% vertical space equal to the optional argument (the default value of
-% which is 0pt).
+% environment. If printanswers is false and cancelspace is false,
+% we insert dotted lined vertical space equal to the optional
+% argument (the default value of which is 0pt).
\newenvironment{solutionordottedlines}[1][0pt]%
{%
\ifprintanswers
+ \begingroup
+ \Solution@Emphasis
\begin{TheSolution}%
\else
- \par
- \fillwithdottedlines{#1}%
+ \ifcancelspace
+ % Do nothing
+ \else
+ \par
+ \penalty 0
+ \fillwithdottedlines{#1}%
+ \fi
\setbox\z@\vbox\bgroup
\fi
}{%
\ifprintanswers
\end{TheSolution}%
+ \endgroup
\else
\egroup
\fi
}%
-
% The environment TheSolution is called from the solution,
-% solutionorlines, and solutionordottedlines environments
-% when printanswers is true. It uses Donald Arseneau's
-% framed.sty macros (included at the end if this file) to allow the
+% solutionorbox, solutionorlines, and solutionordottedlines
+% environments when printanswers is true. It uses Donald Arseneau's
+% framed.sty macros (included at the end of this file) to allow the
% solution to be broken across pages and have each piece enclosed in
% an fbox (or a colorbox, if the user has given the command
-% \shadedsolutions).
-%
+% \shadedsolutions), (or no box at all, if the user has given the
+% command \unframedsolutions).
% Of course, the user can change TheSolution with a \renewenvironment
% command.
\newcommand{\solutiontitle}{\noindent\textbf{Solution:}\enspace}
@@ -5473,10 +6318,17 @@
% inside of the solution box:
\leftskip=0pt
\rightskip=0pt
+ % If the user said \unframedsolutions, then both
+ % \if@framedsolutions and \if@shadedsolutions are false:
\if@framedsolutions
- % Do nothing; we'll use the default \FrameCommand
+ % We'll use the default \FrameCommand
\else
- \def\FrameCommand{\colorbox{SolutionColor}}%
+ \if@shadedsolutions
+ \def\FrameCommand{\colorbox{SolutionColor}}%
+ \else
+ % It's \unframedsolutions:
+ \def\FrameCommand{}%
+ \fi
\fi
\MakeFramed{\advance\hsize-\width}%
\solutiontitle
@@ -5489,8 +6341,12 @@
\newif\if@framedsolutions
\@framedsolutionstrue
+\newif\if@shadedsolutions
+\@shadedsolutionsfalse
+% If the user said \unframedsolutions, then both
+% \if@framedsolutions and \if@shadedsolutions are false.
-\def\framedsolutions{\@framedsolutionstrue}
+\def\framedsolutions{\@framedsolutionstrue\@shadedsolutionsfalse}
\def\shadedsolutions{%
\@ifundefined{definecolor}
{%
@@ -5507,9 +6363,11 @@
}%
{%
\definecolor{SolutionColor}{gray}{0.8}
+ \@shadedsolutionstrue
\@framedsolutionsfalse
}%
}
+\def\unframedsolutions{\@framedsolutionsfalse\@shadedsolutionsfalse}
%--------------------------------------------------------------------
%--------------------------------------------------------------------