summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/tex/latex/exam
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2015-05-08 22:18:17 +0000
committerKarl Berry <karl@freefriends.org>2015-05-08 22:18:17 +0000
commit1026bf8cf7773dad92367f2ad81598536dd6d3da (patch)
treebd82d3c14cfd25e7eef91dfc65afb851e93b1bcc /Master/texmf-dist/tex/latex/exam
parentb01c284cd5b49463dc30f117b5b24020a1f8cc7d (diff)
exam (8may15)
git-svn-id: svn://tug.org/texlive/trunk@37279 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/tex/latex/exam')
-rw-r--r--Master/texmf-dist/tex/latex/exam/exam.cls1526
1 files changed, 924 insertions, 602 deletions
diff --git a/Master/texmf-dist/tex/latex/exam/exam.cls b/Master/texmf-dist/tex/latex/exam/exam.cls
index 1f4fc6358fc..5ea596ca0a3 100644
--- a/Master/texmf-dist/tex/latex/exam/exam.cls
+++ b/Master/texmf-dist/tex/latex/exam/exam.cls
@@ -3,7 +3,7 @@
% A LaTeX2e document class for preparing exams.
%% exam.cls
-%% Copyright (c) 1994, 1997, 2000, 2004, 2008 Philip S. Hirschhorn
+%% Copyright (c) 1994, 1997, 2000, 2004, 2008, 2011, 2015 Philip S. Hirschhorn
%
% This work may be distributed and/or modified under the
% conditions of the LaTeX Project Public License, either version 1.3
@@ -31,8 +31,8 @@
% from my web page: http://www-math.mit.edu/~psh/
-\def\fileversion{2.4}
-\def\filedate{2011/05/22}
+\def\fileversion{2.5}
+\def\filedate{2015/05/07}
%---------------------------------------------------------------------
%---------------------------------------------------------------------
%
@@ -82,460 +82,230 @@
%
%--------------------------------------------------------------------
%--------------------------------------------------------------------
-% Changelog since version 2.3:
+% Changelog since version 2.4:
%--------------------------------------------------------------------
-% Version 2.4, 2011/05/22:
-%
+% Version 2.5 2015/05/07
+
% No longer betatest.
-%
-%--------------------------------------------------------------------
-% Version 2.321$\beta$, 2011/05/15:
-%
-% New environments: EnvUplevel and EnvFullwidth
-%
-% 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.)
-%
-% 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.320$\beta$, 2011/04/16:
-%
-% 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.
-%
-% 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.
-%
-% 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.
-%
-%--------------------------------------------------------------------
-% Version 2.319$\beta$, 2011/04/11:
-%
-% 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).
-%
-%--------------------------------------------------------------------
-% Version 2.318$\beta$, 2011/04/05:
-%
-% \qformat and \bonusqformat are now totally independent.
-% That is: \qformat doesn't affect bonus questions, and \noqformat
-% no longer cancels \bonusqformat.
-%
-% New command: \nobonusqformat
-% \nobonusqformat does for \bonusqformat what \noqformat does for
-% \qformat.
-%
-%--------------------------------------------------------------------
-% Version 2.317$\beta$, 2011/04/02:
-%
-% 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 also made changes and corrections to comments.
-%
-%--------------------------------------------------------------------
-% Version 2.316$\beta$, 2010/12/22:
-%
-%
-% New commands:
-%
-% \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.315$\beta$, 2010/12/21:
-%
+% Version 2.408$\beta$ 2013/11/17
+
% New commands:
%
-% \settabletotalpoints
-% \settabletotalbonuspoints
-%
-% 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.
-%
-% 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.
+% \firstqinrange{whatever}
+% \lastqinrange{whatever}
+% \numqinrange{whatever}
%
-% 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.
+% where ``whatever'' is the name of a grading range.
%
+% \firstqinrange{whatever} prints the number of the first question in
+% the range.
%
-% To have one of these commands affect only a single table, confine the
-% command and the \gradetable command inside of a group, as in
+% \lastqinrange{whatever} prints the number of the last question in the
+% range.
%
-% \begingroup
-% \settabletotalpoints{100}
-% \gradetable[v][questions]
-% \endgroup
+% \numqinrange{whatever} prints the number of questions in the range.
%
-% or even just
+% We changed a couple of internal command name related to grading
+% ranges. If the user defines the range `myrange', then we now use
+
+% \range@myrange@firstp
+% \range@myrange@lastp
+% \range@myrange@firstq
+% \range@myrange@lastq
%
-% \begin{center}
-% \settabletotalpoints{100}
-% \gradetable[v][questions]
-% \end{center}
+% where we used to use
%
+% \tbl@myrange@firstp
+% \tbl@myrange@lastp
+% \tbl@myrange@firstq
+% \tbl@myrange@lastq
+
%--------------------------------------------------------------------
-% Version 2.314$\beta$, 2010/12/01:
-%
-% New user command:
-%
-% \addquestionobject
-%
-% 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.
+% Version 2.407$\beta$ 2012/12/19
+
+% New environment:
%
-% New commands used only internally:
+% solutionbox
%
-% \first@questionobject
-% \questionobject@pluspagecheck
+% The solutionbox environment is different from the other solution
+% environments (solution, solutionorbox, solutionorlines,
+% solutionordottedlines, and solutionorgrid), in that
%
-% These were just to clean up some of the internal code.
+% (1) The box is always printed, whether answers are being printed
+% or not.
%
-%--------------------------------------------------------------------
-% Version 2.313$\beta$, 2010/02/18:
+% (2) The argument giving the size of the box is a required
+% argument, not an optional argument, and so it should be enclosed
+% in braces, not in brackets. It can be either a length or
+% \stretch{number}.
%
-% 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
+% (3) We make no use of the TheSolution environment; the solutionbox
+% environment is completely freestanding.
%
-% \penalty 0
+% If answers are not being printed then only the box is printed, with
+% nothing in it. If answers are being printed, then the solution is
+% printed inside of the box.
%
-% to allow a pagebreak before the environment. We make no change to
-% the solutionorbox environment, since it didn't have this problem.
+% Note: It's the user's responsibility to be sure that the box is
+% large enough to hold the solution! If the solution takes up too
+% much vertical space, then it will spill out of the bottom of the
+% box, overwriting whatever follows the box.
%
%--------------------------------------------------------------------
-% Version 2.312$\beta$, 2010/01/17:
+% Version 2.406$\beta$, 2012/12/16
%
-% 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
+% New command:
%
-% \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.
+% \noquestionsonthispage
%
-%--------------------------------------------------------------------
-% Version 2.311$\beta$, 2010/01/10:
+% This command tells the \ifcontinuation and \ifincomplete commands
+% to assume that no part of any question is on this page. This is
+% similar to the job done by the \nomorequestions command for the
+% pages that follow the end of all of the questions.
%
-% New environment: oneparcheckboxes
%
-% 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 you give the command \noquestionsonthispage on a page, then
%
-% \checkboxchar{$\bigcirc$}
+% (1) \ifcontinuation on that page will expand to its second
+% argument,
+% (2) \ifincomplete on that page will expand to its second
+% argument, and
+% (3) an \ifincomplete on an earlier page will not assume that a
+% question from that earlier page continues onto this page.
%
-% (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
+% The way that this command affects the \ifincomplete command on
+% earlier pages is as follows: If there is a page with no questions or
+% parts or subparts or subsubparts, then the last page before that
+% with a question (or part, etc.) would normally be deemed incomplete;
+% if, however, the page with no questions (or parts, etc.) (along with
+% all adjacent pages with no questions or parts etc.) has a
+% \noquestionsonthispage command, then that last page with a question
+% (or part, etc.) will not be deemed incomplete.
%
-% \checkedchar{$\surd$}
+% Note that if you're tempted to use this command on a page that follows
+% the end of all of the questions, then you should probably use the
+% command \nomorequestions instead.
%
%--------------------------------------------------------------------
-% Version 2.310$\beta$, 2010/01/09:
-%
-% New command: \bonusqformat
-%
-% The \bonusqformat command takes one argument, with the same
-% description as for the argument of the \qformat command.
+% Version 2.405$\beta$, 2012/10/21
+%
+% It is now possible to use a parts, subparts, or subsubparts
+% environment inside one of the solution environments (solution,
+% solutionorbox, solutionorlines, solutionordottedlines, or
+% solutionorgrid) without getting problems from multiply defined
+% labels or having its points (if any) counted as being actual points
+% on the exam.
+%
+% Any \part, \subpart, or \subsubpart command inside one of the
+% solution environments now writes a \PgInfo command in the .aux file
+% of the form question2@object3, but no labels and no other \PgInfo
+% commands. In addition, if there are points assigned to any of these
+% commands inside any of the solution environments, those points are
+% not added to the points of the question or the points on the page,
+% and do not affect any gradetables or pointtables.
%
-% Note added 2011/04/05: Version 2.318$\beta$ changes the behavior so
-% that \qformat and \bonusqformat are now completely independent!
-%
-% 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.
-%
-% Note: The \bonusqformat command must be given *after* the \qformat
-% command, or else the \bonusqformat command will have no effect.
-%
-% Note: If the user hasn't given a \qformat command, then a
-% \bonusqformat command will have no effect.
-%
-% 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.
-%
-% 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.309$\beta$, 2009/11/30:
+% Version 2.404$\beta$, 2012/09/03
%
-% New environment: checkboxes
-% New commands: \checkboxeshook
-% \checkboxchar
-% \checkedchar
+% New command:
%
-% 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
+% \fillwithgrid{length}
%
-% \checkboxchar{$\bigcirc$}
+% New environment:
%
-% (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
+% solutionorgrid
%
-% \checkedchar{$\surd$}
+% These are similar to the \fillwithlines command and the
+% solutionorlines environment.
%
-% 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.)
+% By default, the created grids are in black. However, if you give the
+% commands
%
-%--------------------------------------------------------------------
-% Version 2.308$\beta$, 2009/11/26:
+% \usepackage{color}
+% \colorgrids
%
-% We fixed a bug that caused \bonussubpart to act like \subpart and
-% \bonussubsubpart to act like \subsubpart.
+% then the grids will be in color, by default a light gray. That
+% default color was defined by the command
%
-%--------------------------------------------------------------------
-% Version 2.307$\beta$, 2009/06/11:
+% \definecolor{GridColor}{gray}{0.8}
%
-% 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.
+% You can change the color by redefining the color GridColor, and you
+% can return to using black grids by giving the command
%
-%--------------------------------------------------------------------
-% Version 2.306$\beta$, 2009/03/28:
+% \nocolorgrids
%
-% 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.
+% The default grid size and grid line thickness were set by the
+% commands
%
-% We fixed this by commenting out several lines at the end of
-% \@setheadheight and @setfootheight.
+% \setlength{\gridsize}{5mm}
+% \setlength{\gridlinewidth}{0.1pt}
%
-%--------------------------------------------------------------------
-% Version 2.305$\beta$, 2009/01/30:
-%
-% 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.
-%
-% We also fixed a bug in the solutionorbox environment that showed
-% itself when the user used \stretch in the optional argument.
+% You can change either or both of those by giving new \setlength
+% commands. The period of the grid is \gridsize (both horizontally
+% and vertically). That is, the horizontal distance from the left
+% edge of one vertical line to the left edge of the next vertical line
+% is \gridsize, as is the vertical distance from the top edge of one
+% horizontal line to the top edge of the next horizontal line. Thus,
+% each square has outer side length equal to \gridsize+\gridlinewidth.
%
%--------------------------------------------------------------------
-% Version 2.304$\beta$, 2009/01/22:
-%
-% We rewrote the definition of \makeemptybox and the solutionorbox
-% environment (created in version 2.303).
-%
-% The argument to \makeemptybox can now be either a length, or \fill, or
-% \stretch{number}.
-%
-% 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.
-%
-% The minimum box height is \minboxheight, whose value is set by the
-% command
+% Version 2.403$\beta$, 2012/08/29:
%
-% \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.
+% We changed the code for the command \fillin (which had been modified
+% in version 2.402beta) so that if only one optional argument is used,
+% a space following that optional argument will not be ignored. We
+% did this in such a way that the second optional argument will be
+% recognized even when spaces appear in between the optional
+% arguments.
%
%--------------------------------------------------------------------
-% Version 2.303$\beta$, 2009/01/21:
+% Version 2.402$\beta$, 2012/08/21:
%
-% New command: \makeemptybox
-% New environment: solutionorbox
+% We modified the command \fillin that we had created in version
+% 2.401beta. \fillin now takes two optional arguments (and no required
+% arguments).
%
-% \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.
-%
-% 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.
+% \fillin can take two optional arguments, as in
%
-% Note: This is changed in version 2.304. As of that version, the
-% argument can be a length, or \fill, or \stretch{number}.
+% \fillin[Answer][Length]
%
-%--------------------------------------------------------------------
-% Version 2.302$\beta$, 2008/10/18:
+% The first optional argument is the answer to be printed above the line
+% when \printanswers is in effect; the default value is empty. That
+% line is printed a distance of \answerclearance below the baseline.
%
-% New commands: \numcoverpages and \totalnumpages
+% The second optional argument is the length of the line that we print;
+% the default value is \fillinlinelength. The value of
+% \fillinlinelength is set with the command
%
-% \numcoverpages inserts the number of pages occupied by the
-% coverpages environment. If there is no coverpages environment,
-% it inserts 0.
+% \setlength\fillinlinelength{1in}
%
-% \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.
+% and can be changed by giving a new \setlength command.
%
-% 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.
+% When answers are being printed, the first optional argument is
+% printed subject to the declarations in the argument of the last
+% \CorrectChoiceEmphasis command. It is centered on the line unless
+% it is too long, in which case it extends to the right of the line.
%
%--------------------------------------------------------------------
-% Version 2.301$\beta$, 2008/09/22:
-%
-% All solution, solutionorlines, and solutionordotteslines
-% environments are now enclosed in a group which is begun
-% with the argument of the command
-%
-% \SolutionEmphasis
+% Version 2.401$\beta$, 2012/08/20:
%
-% the default value of which is determined by the command
%
-% \SolutionEmphasis{}
+% New command:
%
-% That is, the default is that nothing is inserted.
-% For example, if the command
+% \fillin[CorrectAnswer]{width}
%
-% \SolutionEmphasis{\itshape\small}
+% This is for use in fill in the blank questions. This command inserts
+% a blank line of width ``width''. If answers are being printed and if
+% the optional argument ``CorrectAnswer'' appears, then the optional
+% argument is printed subject to the declarations in the argument of the
+% last \CorrectChoiceEmphasis command, and it is printed a distance of
+% \answerclearance above the line. It is centered on the line unless it
+% is too long, in which case it extends to the right of the line.
%
-% is used, the solutions will be set in italics, in small type.
-%
-%
-% New command: \unframedsolutions
-%
-% 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.
+% Note: We changed this command in version 2.401beta.
%
%--------------------------------------------------------------------
%--------------------------------------------------------------------
@@ -1777,11 +1547,16 @@
% \PgInfo@write command using a label of the form question2@object3 (if
% it's the third object of the second question).
-% The \PgInfo command defines a control sequence of the form `Pg@label'
-% that expands to the page number for the corresponding question. For
-% example, \PgInfo{subsubpart@2@1@3@4}{7} defines
-% \csname Pg@subsubpart@2@1@3@4\endcsname
-% to expand to 7.
+% Inside one of the solution environments (solution, solutionorbox,
+% etc.) each part, subpart, subsubpart, and choice get only the
+% \PgInfo@write command using a label of the form question2@object3
+% (if it's the third object of the second question).
+
+% When read in from the .aux file, the \PgInfo command defines a
+% control sequence of the form `Pg@label' that expands to the page
+% number for the corresponding question. For example,
+% \PgInfo{subsubpart@2@1@3@4}{7} defines \csname
+% Pg@subsubpart@2@1@3@4\endcsname to expand to 7.
% The \PgInfo@get{label} command returns the value of the macro Pg@label,
% but it *doesn't* check whether that macro is defined. Thus, it's
@@ -1836,17 +1611,35 @@
%--------------------------------------------------------------------
-% \ifcontinuation#1#2 expands to #2 if either: (1) The current page is
-% before the page containing question number 1, or (2) A question begins
-% on this page before any part, subpart, subsubpart, or choice begins,
-% or (3) The current page is later than a page with the \nomorequestions
-% command. Otherwise, it expands to #1.
+% \ifcontinuation#1#2 expands to #2 if either:
+% (1) The command \noquestionsonthispage has been given on this page,
+% or
+% (2) The current page is before the page containing question number
+% 1, or
+% (3) A question begins on this page before any part, subpart,
+% subsubpart, or choice begins, or
+% (4) The current page is later than a page with the \nomorequestions
+% command.
+% Otherwise, it expands to #1.
+%
+% Thus, for example, if there are no questions, parts, subparts,
+% subsubparts, or choices on this page, and no \noquestionsonthispage
+% command, and we're not before question 1, and not after a
+% \nomorequestions command, then \ifcontinuation will expand to #1.
\def\ifcontinuation#1#2{%
- % We need to first check whether we're on a page *before* the page on
- % which the first question appears. If we don't yet know which page
- % has question number 1, then we must be doing an early run of LaTeX,
+ % If there's a \noquestionsonthispage command on this page, then
+ % we assume that we're not continuing anything:
+ \@ifundefined{No@Questions@Pg@\thepage}%
+ {\chk@contin{#1}{#2}}%
+ {#2}%
+}% \ifcontinuation
+
+\def\chk@contin#1#2{%
+ % We check whether we're on a page *before* the page on which the
+ % first question appears. If we don't yet know which page has
+ % question number 1, then we must be doing an early run of LaTeX,
% and we'll assume we're not a continuation.
\expandafter\ifx\csname Pg@question@1\endcsname\relax
% No page info yet; assume not a continuation
@@ -1865,10 +1658,10 @@
#2%
\else
% The current page begins a new question if Contin@\thepage
- % has been defined as a macro that expands to \relax
- % (Note that this is different from if Contin@\thepage
- % has never been defined at all, in which case it will
- % be let equal to \relax (temporarily) by the \csname command.)
+ % has been defined as a macro that expands to \relax (Note
+ % that this is different from if Contin@\thepage has never
+ % been defined at all, in which case it will be let equal to
+ % \relax (temporarily) by the \csname command.)
\expandafter\ifx\csname Contin@\thepage\endcsname\ref@relax
#2%
\else
@@ -1886,11 +1679,18 @@
\fi
\fi
\fi
-}
+}% chk@contin
-\def\nomorequestions{
+\def\nomorequestions{%
\PgInfo@write{@endquestions}%
-}
+}% nomorequestions
+
+\def\noquestionsonthispage{%
+ \write\@mainaux{\string\expandafter\string\gdef
+ \string\csname\space No@Questions@Pg@\thepage\string\endcsname
+ {No questions here}}%
+}% noquestionsonthispage
+
%--------------------------------------------------------------------
% \ContinuedQuestion is for use in headers and footers, where we can
@@ -1928,7 +1728,7 @@
% The last possibility is that this page begins with either a part,
% subpart, subsubpart, or choice. In this case, Contin@\thepage is
% defined, and it expands to the number of the question that is
-% continues onto this page.
+% continued onto this page.
\def\ref@relax{\relax}
@@ -2095,55 +1895,115 @@
\def\IncompleteQuestion{%
\Find@Incmp@ques
+ % If there's no incomplete question, the counter incmp@ques will be
+ % set to -1:
\theincmp@ques
}
\def\Find@Incmp@ques{%
+ % If we're on the last page, then there's no incomplete question:
\iflastpage{\setcounter{incmp@ques}{-1}}{\chk@incomp}%
-}
+}% Find@Incmp@ques
\newcounter{next@ques}
-\newcounter{nextq@page}
+\newcounter{next@page}
+
\def\chk@incomp{%
+ % If we get here, we're not on the last page.
+ % \find@quesend calls \find@latestques to set the counter
+ % latest@ques equal to the number of the last question begun on or
+ % before the current page, and then it sets the counter ques@end to
+ % the page containing the last ques@object of that question:
\find@quesend
\ifnum \theques@end > \thepage\relax
% This question has a part (or sub...) starting on a later page
\setcounter{incmp@ques}{\value{latest@ques}}%
\else
- \setcounter{next@ques}{\thelatest@ques}%
- \addtocounter{next@ques}{1}%
- \expandafter\ifx\csname Pg@question@\thenext@ques \endcsname\relax
- % This isn't the last page but there is no next question:
- \setcounter{incmp@ques}{\thelatest@ques}%
- \else
- % This isn't the last page and there is a next question:
- \setcounter{nextq@page}{\PgInfo@get{question@\thenext@ques}}%
- \addtocounter{nextq@page}{-1}%
- \ifnum \thenextq@page > \thepage\relax
- \setcounter{incmp@ques}{\thelatest@ques}%
- \else
- \setcounter{incmp@ques}{-1}%
- \fi
- \fi
+ \chk@incompi
\fi
-}
+}% chk@incomp
+
+\def\chk@incompi{%
+ % If there are any pages after the current one and before the next
+ % question (if there is a next question) that lack a
+ % \noquestionsonthispage and that aren't following the page of a
+ % \nomorequestions command, then question latest@ques is incomplete.
+ % Otherwise, there is no incomplete question:
+ \setcounter{next@ques}{\thelatest@ques}%
+ \addtocounter{next@ques}{1}%
+ % We use next@page as a scratch counter. We start by setting it
+ % to the last page we want to check for a \noquestionsonthispage
+ % command:
+ \expandafter\ifx\csname Pg@question@\thenext@ques \endcsname\relax
+ % This isn't the last page but there is no next question:
+%
+ \@ifundefined{exam@lastpage}%
+ {\setcounter{next@page}{-1}}%
+ {\setcounter{next@page}{\exam@lastpage}}%
+%
+% \setcounter{next@page}{\exam@lastpage}%
+ \else
+ \setcounter{next@page}{\PgInfo@get{question@\thenext@ques}}%
+ \addtocounter{next@page}{-1}%
+ \fi
+ % See if that's after a \nomorequestions command:
+ \@ifundefined{Pg@@endquestions}%
+ {}%
+ {\ifnum \PgInfo@get{@endquestions} < \value{next@page}\relax
+ \setcounter{next@page}{\PgInfo@get{@endquestions}}%
+ \fi
+ }%
+ % OK, the counter next@page now contains the last page to check.
+ \chk@incompii
+}% chk@incompi
+
+\def\chk@incompii{%
+ \ifnum \value{next@page} > \value{page}\relax
+ % We need to check the page next@page:
+ \@ifundefined{No@Questions@Pg@\arabic{next@page}}%
+ {\setcounter{incmp@ques}{\value{latest@ques}}%
+ \let\next@incompii=\relax
+ }%
+ {\addtocounter{next@page}{-1}%
+ \let\next@incompii = \chk@incompii
+ }%
+ \else
+ % There's no incomplete question:
+ \setcounter{incmp@ques}{-1}%
+ \let\next@incompii=\relax
+ \fi
+ \next@incompii
+}% chk@incompii
\def\ifincomplete#1#2{%
+ % We need to pass the arguments to \chk@ifincomp; we save them in
+ % macros so they won't be messed up by the call to \Find@Incmp@ques:
\def\incomp@first{#1}%
\def\incomp@second{#2}%
+ % If there's a \noquestionsonthispage command on this page, then
+ % we assume nothing from this page is incomplete:
+ \@ifundefined{No@Questions@Pg@\thepage}%
+ {\chk@ifincomp}%
+ {\incomp@second}%
+}% ifincomplete
+
+\def\chk@ifincomp{%
\Find@Incmp@ques
+ % If there's no incomplete question, \Find@Incmp@ques sets the
+ % counter incmp@ques to -1:
\ifnum \theincmp@ques < 0\relax
\incomp@second
\else
- \@ifundefined{Pg@@endquestions}%
- {\incomp@first}%
- {\ifnum \thepage < \PgInfo@get{@endquestions}\relax
- \incomp@first
- \else
- \incomp@second
- \fi
- }%
+ % Are we after a page with \nomorequestions?
+ \@ifundefined{Pg@@endquestions}%
+ {\incomp@first}%
+ {\ifnum \thepage < \PgInfo@get{@endquestions}\relax
+ \incomp@first
+ \else
+ \incomp@second
+ \fi
+ }%
\fi
-}
+}% chk@ifincomp
%--------------------------------------------------------------------
% These are the commands for dealing with hlfcntr's, i.e., the things
@@ -2546,9 +2406,11 @@
% \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}%
+ % \PgInfo@write expands it's argument, so we don't need edef:
+% \edef\q@object@label{%
+% question\arabic{question}@object\arabic{ques@object}}%
+% \PgInfo@write{\q@object@label}%
+ \PgInfo@write{question\arabic{question}@object\arabic{ques@object}}%
}% first@questionobject
% \addquestionobject will be used by each part, subpart, and
@@ -2557,18 +2419,35 @@
% 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}%
+ % \PgInfo@write expands it's argument, so we don't need edef:
+% \edef\q@object@label{%
+% question\arabic{question}@object\arabic{ques@object}}%
+% \PgInfo@write{\q@object@label}%
+ \PgInfo@write{question\arabic{question}@object\arabic{ques@object}}%
}% 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).
+% \questionobject@pluspagecheck will be used by each choice, as well
+% as by any \part, \subpart, or \subsubpart that's inside of a
+% solution. It uses the questionobject to check if we're the first
+% one on the current page, since choices (and questions etc. inside of
+% solution environments) 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}{%
+ % We don't want to do any of this if we're both inside a solution
+ % environment and not printing answers (because we want to avoid
+ % incrementing ques@object):
+ \if@insolution
+ \ifprintanswers
+ \doqobj@ppchk
+ \fi
+ \else
+ \doqobj@ppchk
+ \fi
+}% questionobject@pluspagecheck
+\newcommand{\doqobj@ppchk}{%
\addtocounter{ques@object}{1}%
+ % We need the edef because we check the page of \q@object@label:
\edef\q@object@label{%
question\arabic{question}@object\arabic{ques@object}}%
\PgInfo@write{\q@object@label}%
@@ -2579,7 +2458,7 @@
\global\expandafter\edef\csname
Contin@\theCurr@Page\endcsname{\arabic{question}}%
\fi
-}% questionobject@pluspagecheck
+}% doqobj@ppchk
@@ -2755,47 +2634,56 @@
\cover@question@error
\fi
\@checkqueslevel{subpart}%
- \addtocounter{numsubparts}{1}%
- % Important: Don't leave any blank lines inside of
- % \pageinfo@commands!! This token list will be dumped into
- % horizontal mode by \everypar, and so any blank lines will
- % cause paragraph breaks.
- \temp@toks={%
- \edef\@subpartlabel{subpart@\arabic{question}%
- @\arabic{partno}@\arabic{subpart}}%
- \PgInfo@write{\@subpartlabel}%
- \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
- % \usepackage{hyperref}, those question numbers will be clickable.
- %
- % A further purpose of these labels (which we actually do for all
- % questions, parts, subparts, and subsubparts) is that if a
- % question (or part, etc.) is, e.g., moved from one page to
- % another, LaTeX will notice this and warn the user that LaTeX
- % must be run one more time to be sure everything is correct.
- %
- % We need to do this even though we've already included code to
- % check when point totals change because questions (and parts,
- % etc.) know what page they're on from reading the info written to
- % the .aux file on the previous run. Thus, if a question (or
- % part, etc.) is moved to a different page, then the pointsonpage
- % totals won't notice until the *second* subsequent run of LaTeX,
- % and so there'll be no warning to the user on the *first* run.
- % Including these labels gives the user a warning on that first
- % run.
- \label{\@subpartlabel}%
- \set@counter@to@pageof{Curr@Page}{\@subpartlabel}%
- \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
- \the\pagepoint@commands
- \global \pageinfo@commands={}%
- }% temp@toks
+ \if@insolution
+ % We don't count this subpart, so no addtocounter{numsubparts}.
+ \temp@toks={%
+ \questionobject@pluspagecheck
+ \global \pageinfo@commands={}%
+ % We omit the pagepoint@commands
+ }% temp@toks
+ \else
+ \addtocounter{numsubparts}{1}%
+ % Important: Don't leave any blank lines inside of
+ % \pageinfo@commands!! This token list will be dumped into
+ % horizontal mode by \everypar, and so any blank lines will
+ % cause paragraph breaks.
+ \temp@toks={%
+ \edef\@subpartlabel{subpart@\arabic{question}%
+ @\arabic{partno}@\arabic{subpart}}%
+ \PgInfo@write{\@subpartlabel}%
+ \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
+ % \usepackage{hyperref}, those question numbers will be clickable.
+ %
+ % A further purpose of these labels (which we actually do for all
+ % questions, parts, subparts, and subsubparts) is that if a
+ % question (or part, etc.) is, e.g., moved from one page to
+ % another, LaTeX will notice this and warn the user that LaTeX
+ % must be run one more time to be sure everything is correct.
+ %
+ % We need to do this even though we've already included code to
+ % check when point totals change because questions (and parts,
+ % etc.) know what page they're on from reading the info written to
+ % the .aux file on the previous run. Thus, if a question (or
+ % part, etc.) is moved to a different page, then the pointsonpage
+ % totals won't notice until the *second* subsequent run of LaTeX,
+ % and so there'll be no warning to the user on the *first* run.
+ % Including these labels gives the user a warning on that first
+ % run.
+ \label{\@subpartlabel}%
+ \set@counter@to@pageof{Curr@Page}{\@subpartlabel}%
+ \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
+ \the\pagepoint@commands
+ \global \pageinfo@commands={}%
+ }% temp@toks
+ \fi
\append@toklist \pageinfo@commands \temp@toks
\ifhmode
% Remove any skips at the end of the previous paragraph
@@ -2817,47 +2705,56 @@
\cover@question@error
\fi
\@checkqueslevel{subsubpart}%
- \addtocounter{numsubsubparts}{1}%
- % Important: Don't leave any blank lines inside of
- % \pageinfo@commands!! This token list will be dumped into
- % horizontal mode by \everypar, and so any blank lines will
- % cause paragraph breaks.
- \temp@toks={%
- \edef\@subsubpartlabel{subsubpart@\arabic{question}%
- @\arabic{partno}@\arabic{subpart}@\arabic{subsubpart}}%
- \PgInfo@write{\@subsubpartlabel}%
- \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
- % \usepackage{hyperref}, those question numbers will be clickable.
- %
- % A further purpose of these labels (which we actually do for all
- % questions, parts, subparts, and subsubparts) is that if a
- % question (or part, etc.) is, e.g., moved from one page to
- % another, LaTeX will notice this and warn the user that LaTeX
- % must be run one more time to be sure everything is correct.
- %
- % We need to do this even though we've already included code to
- % check when point totals change because questions (and parts,
- % etc.) know what page they're on from reading the info written to
- % the .aux file on the previous run. Thus, if a question (or
- % part, etc.) is moved to a different page, then the pointsonpage
- % totals won't notice until the *second* subsequent run of LaTeX,
- % and so there'll be no warning to the user on the *first* run.
- % Including these labels gives the user a warning on that first
- % run.
- \label{\@subsubpartlabel}%
- \set@counter@to@pageof{Curr@Page}{\@subsubpartlabel}%
- \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
- \the\pagepoint@commands
- \global \pageinfo@commands={}%
- }% temp@toks
+ \if@insolution
+ % We don't count this subsubpart, so no addtocounter{numsubsubparts}.
+ \temp@toks={%
+ \questionobject@pluspagecheck
+ \global \pageinfo@commands={}%
+ % We omit the pagepoint@commands
+ }% temp@toks
+ \else
+ \addtocounter{numsubsubparts}{1}%
+ % Important: Don't leave any blank lines inside of
+ % \pageinfo@commands!! This token list will be dumped into
+ % horizontal mode by \everypar, and so any blank lines will
+ % cause paragraph breaks.
+ \temp@toks={%
+ \edef\@subsubpartlabel{subsubpart@\arabic{question}%
+ @\arabic{partno}@\arabic{subpart}@\arabic{subsubpart}}%
+ \PgInfo@write{\@subsubpartlabel}%
+ \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
+ % \usepackage{hyperref}, those question numbers will be clickable.
+ %
+ % A further purpose of these labels (which we actually do for all
+ % questions, parts, subparts, and subsubparts) is that if a
+ % question (or part, etc.) is, e.g., moved from one page to
+ % another, LaTeX will notice this and warn the user that LaTeX
+ % must be run one more time to be sure everything is correct.
+ %
+ % We need to do this even though we've already included code to
+ % check when point totals change because questions (and parts,
+ % etc.) know what page they're on from reading the info written to
+ % the .aux file on the previous run. Thus, if a question (or
+ % part, etc.) is moved to a different page, then the pointsonpage
+ % totals won't notice until the *second* subsequent run of LaTeX,
+ % and so there'll be no warning to the user on the *first* run.
+ % Including these labels gives the user a warning on that first
+ % run.
+ \label{\@subsubpartlabel}%
+ \set@counter@to@pageof{Curr@Page}{\@subsubpartlabel}%
+ \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
+ \the\pagepoint@commands
+ \global \pageinfo@commands={}%
+ }% temp@toks
+ \fi
\append@toklist \pageinfo@commands \temp@toks
\ifhmode
% Remove any skips at the end of the previous paragraph
@@ -2984,44 +2881,53 @@
\cover@question@error
\fi
\@checkqueslevel{part}%
- \addtocounter{numparts}{1}%
- % Important: Don't leave any blank lines inside of
- % \pageinfo@commands!! This token list will be dumped into
- % horizontal mode by \everypar, and so any blank lines will
- % cause paragraph breaks.
- \temp@toks={%
- \edef\@partlabel{part@\arabic{question}@\arabic{partno}}%
- \PgInfo@write{\@partlabel}%
- \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
- % \usepackage{hyperref}, those question numbers will be clickable.
- %
- % A further purpose of these labels (which we actually do for all
- % questions, parts, subparts, and subsubparts) is that if a
- % question (or part, etc.) is, e.g., moved from one page to
- % another, LaTeX will notice this and warn the user that LaTeX
- % must be run one more time to be sure everything is correct.
- %
- % We need to do this even though we've already included code to
- % check when point totals change because questions (and parts,
- % etc.) know what page they're on from reading the info written to
- % the .aux file on the previous run. Thus, if a question (or
- % part, etc.) is moved to a different page, then the pointsonpage
- % totals won't notice until the *second* subsequent run of LaTeX,
- % and so there'll be no warning to the user on the *first* run.
- % Including these labels gives the user a warning on that first
- % run.
- \label{\@partlabel}%
- \set@counter@to@pageof{Curr@Page}{\@partlabel}%
- \expandafter\ifx\csname Contin@\theCurr@Page\endcsname\relax
- \global\expandafter\edef\csname
- Contin@\theCurr@Page\endcsname{\arabic{question}}%
- \fi
- \the\pagepoint@commands
- \global \pageinfo@commands={}%
- }%
+ \if@insolution
+ % We don't count this part, so no addtocounter{numparts}.
+ \temp@toks={%
+ \questionobject@pluspagecheck
+ \global \pageinfo@commands={}%
+ % We omit the pagepoint@commands
+ }% temp@toks
+ \else
+ \addtocounter{numparts}{1}%
+ % Important: Don't leave any blank lines inside of
+ % \pageinfo@commands!! This token list will be dumped into
+ % horizontal mode by \everypar, and so any blank lines will
+ % cause paragraph breaks.
+ \temp@toks={%
+ \edef\@partlabel{part@\arabic{question}@\arabic{partno}}%
+ \PgInfo@write{\@partlabel}%
+ \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
+ % \usepackage{hyperref}, those question numbers will be clickable.
+ %
+ % A further purpose of these labels (which we actually do for all
+ % questions, parts, subparts, and subsubparts) is that if a
+ % question (or part, etc.) is, e.g., moved from one page to
+ % another, LaTeX will notice this and warn the user that LaTeX
+ % must be run one more time to be sure everything is correct.
+ %
+ % We need to do this even though we've already included code to
+ % check when point totals change because questions (and parts,
+ % etc.) know what page they're on from reading the info written to
+ % the .aux file on the previous run. Thus, if a question (or
+ % part, etc.) is moved to a different page, then the pointsonpage
+ % totals won't notice until the *second* subsequent run of LaTeX,
+ % and so there'll be no warning to the user on the *first* run.
+ % Including these labels gives the user a warning on that first
+ % run.
+ \label{\@partlabel}%
+ \set@counter@to@pageof{Curr@Page}{\@partlabel}%
+ \expandafter\ifx\csname Contin@\theCurr@Page\endcsname\relax
+ \global\expandafter\edef\csname
+ Contin@\theCurr@Page\endcsname{\arabic{question}}%
+ \fi
+ \the\pagepoint@commands
+ \global \pageinfo@commands={}%
+ }% temp@toks
+ \fi
\append@toklist \pageinfo@commands \temp@toks
\ifhmode
% Remove any skips at the end of the previous paragraph
@@ -3952,6 +3858,8 @@
\def\subpart@ref{subpart}
\def\subsubpart@ref{subsubpart}
+% Note: \answerclearance is also used by \fillin
+
\newlength\answerlinelength
\newlength\answerskip
\newlength\answerclearance
@@ -3994,14 +3902,133 @@
}% answerline
%--------------------------------------------------------------------
+% \fillin, for fill-in-the-blank questions
+
+\newlength\fillinlinelength
+\setlength\fillinlinelength{1in}
+
+% \fillin can take two optional arguments.
+%
+% The first optional argument is the answer to be printed above the line
+% when \printanswers is in effect; the default value is empty. That
+% line is printed a distance of \answerclearance below the baseline.
+%
+% The second optional argument is the length of the line that we print;
+% the default value is \fillinlinelength. The value of
+% \fillinlinelength is set with the command
+%
+% \setlength\fillinlinelength{1in}
+%
+% and can be changed by giving a new \setlength command.
+%
+% When answers are being printed, the optional argument is printed
+% subject to the declarations in the argument of the last
+% \CorrectChoiceEmphasis command. It is centered on the line unless it
+% is too long, in which case it extends to the right of the line.
+%
+% \fillin eats (and ignores) space characters appearing before the
+% first optional argument. It also eats (and ignores) space
+% characters appearing after the first optional argument and before
+% the second optional argument. However, if exactly one optional
+% argument appears, and if there are one or more space characters
+% following that one optional argument, then those spaces are replaced
+% by a single space character, but not eaten.
+
+\newcommand\fillin[1][{}]{%
+ \def\fillin@ans{#1}%
+ \fillin@relay
+}% fillin
+
+\newcommand\fillin@relay{%
+ % We use \exam@ifnextchar, a variation on \@ifnextchar.
+ % If \exam@ifnextchar encounters one or more space characters
+ % followed by a [, then those spaces are ignored (just as they would
+ % be by \@ifnextchar). However, if one or more space characters are
+ % followed by a non-space character other than [, then
+ % \exam@ifnextchar inserts a space following the
+ % {\@fillin@relay[\fillinlinelength]} that is the third argument to
+ % \exam@ifnextchar.
+ \exam@ifnextchar[{\@fillin@relay}
+ {\@fillin@relay[\fillinlinelength]}%
+}% fillin@relay
+
+\def\@fillin@relay[#1]{%
+ % The first argument is in \fillin@ans, the second is #1.
+ \leavevmode
+ \ifprintanswers
+ \rlap{\raise -\answerclearance \hbox to #1{\hrulefill}}%
+ \begingroup
+ \setbox0 \hbox{\color@begingroup
+ \CorrectChoice@Emphasis \fillin@ans \color@endgroup}%
+ \ifdim\wd0 > #1\relax
+ \hbox{\CorrectChoice@Emphasis \fillin@ans}%
+ \else
+ \hbox to #1{\CorrectChoice@Emphasis \hfil \fillin@ans \hfil}%
+ \fi
+ \endgroup
+ \else
+ \raise -\answerclearance \hbox to #1{\hrulefill}%
+ \fi
+}% @fillin@relay
+
+% \exam@ifnextchar is used by \fillin.
+% \exam@ifnextchar is a variation of \@ifnextchar that does not always
+% ignore space tokens. If \exam@ifnextchar encounters one or more
+% space tokens, it makes note of that (with the command
+% \@tempswatrue). If the first non-space character encountered
+% matches argument #1, then any spaces that had been encountered are
+% ignored. However, if one or more spaces are encountered and the
+% first non-space character found does not match argument #1, then
+% \exam@ifnextchar produces argument #3 followed by a space character.
+% (This differs from the behavior of \new@ifnextchar in amsgen.sty,
+% which does lookahead for any character, including a space.) This
+% code (as well as the idea for it) is due to Dan Luecking and Ulrich
+% Diez.
+\long\def\exam@ifnextchar#1#2#3{%
+ \let\reserved@d=#1%
+ \def\reserved@a{#2}%
+ \def\reserved@b{#3}%
+ % The following says we haven't yet seen any spaces:
+ \@tempswafalse
+ \futurelet\@let@token\exam@ifnch
+}% exam@ifnextchar
+
+\def\exam@ifnch{%
+ \ifx\@let@token\@sptoken
+ % Signal that we've found a space:
+ \@tempswatrue
+ \let\reserved@c\exam@xifnch % this gobbles the space
+ \else
+ \ifx\@let@token\reserved@d
+ \let\reserved@c\reserved@a
+ \else
+ \if@tempswa
+ \def\reserved@c{\expandafter\reserved@b\space}%
+ \else
+ \let\reserved@c\reserved@b
+ \fi
+ \fi
+ \fi
+ \reserved@c
+}% exam@ifnch
+
+% The following defines \exam@xifnch so that it will eat a space
+% following it and then call \exam@ifnch:
+{% keep redefinition of \: local
+ \def\:{\exam@xifnch}
+ \expandafter\gdef\: {\futurelet\@let@token\exam@ifnch}
+}
+
+%--------------------------------------------------------------------
% \fillwithlines
-% \fillwithlines takes one argument, which is either a length or \fill,
-% and it fills that much vertical space with 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.
+% \fillwithlines takes one argument, which is either a length or \fill
+% or \stretch{number}, and it fills that much vertical space with
+% 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.
%
% The distance between the lines is \linefillheight, whose default value
% is set with the command
@@ -4053,10 +4080,11 @@
% with solid lines.
% \fillwithdottedlines takes one argument, which is either a length or
-% \fill, and it fills that much vertical space with dotted 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.
+% \fill or \stretch{number}, and it fills that much vertical space
+% with dotted 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.
%
% The distance between the lines is \dottedlinefillheight, whose
% default value is set with the command
@@ -4083,7 +4111,130 @@
% no matter where on the page it happens to start:
\cleaders \copy0 \vskip #1 \hbox{}%
\endgroup
-}
+}% fillwithdottedlines
+
+%--------------------------------------------------------------------
+% \fillwithgrid
+
+
+% \fillwithgrid is similar to \fillwithlines, except that it
+% fills the space with a grid.
+
+% \fillwithgrid takes one argument, which is either a length or \fill
+% or \stretch{number}, and it fills that much vertical space with a
+% grid that runs the length of the current line. That is, it extends
+% from the current left margin (which depends on whether we're in a
+% question, part, subpart, or subsubpart) to the right margin.
+%
+% The default grid size and grid line thickness were set by the
+% commands
+%
+% \setlength{\gridsize}{5mm}
+% \setlength{\gridlinewidth}{0.1pt}
+%
+% You can change either or both of those by giving new \setlength
+% commands. The period of the grid is \gridsize (both horizontally
+% and vertically). That is, the horizontal distance from the left
+% edge of one vertical line to the left edge of the next vertical line
+% is \gridsize, as is the vertical distance from the top edge of one
+% horizontal line to the top edge of the next horizontal line. Thus,
+% each square has outer side length equal to \gridsize+\gridlinewidth.
+
+% By default, the created grids are in black. However, if you give the
+% commands
+%
+% \usepackage{color}
+% \colorgrids
+%
+% then the grids will be in color, by default a light gray. That
+% default color was defined by the command
+%
+% \definecolor{GridColor}{gray}{0.8}
+%
+% You can change the color by redefining the color GridColor by giving
+% a new \definecolor command.
+
+\newif\if@colorgrids
+\newcommand\colorgrids{%
+ \@ifundefined{definecolor}
+ {%
+ \ClassError{exam}{%
+ You must load the color package with the command\MessageBreak
+ \space\space\protect\usepackage{color}\MessageBreak
+ in order to use the command \protect\colorgrids
+ }{%
+ This command makes use of the package color.sty,\MessageBreak
+ and so you have to load color.sty before your\MessageBreak
+ \protect\begin{document} command.\MessageBreak
+ }%
+ }%
+ {%
+ \definecolor{GridColor}{gray}{0.8}
+ \@colorgridstrue
+ }%
+}% \colorgrids
+\newcommand\nocolorgrids{\@colorgridsfalse}
+\nocolorgrids
+
+\newlength\gridsize
+\newlength\gridlinewidth
+\setlength{\gridsize}{5mm}
+\setlength{\gridlinewidth}{0.1pt}
+
+\def\fillwithgrid#1{%
+ \begingroup
+ \ifhmode
+ \par
+ \fi
+ \hrule height \z@
+ \nobreak
+
+ % We first set box0 equal to an \hbox which, when printed, is a
+ % square with width and height equal to \gridsize+\gridlinewidth,
+ % but which has
+ % width equal to \gridsize,
+ % height equal to \gridsize, and
+ % depth equal to 0pt.
+ % When we put multiple copies of it together using \leaders or
+ % \cleaders, the right edge will coincide with the left edge of the
+ % next box and the bottom edge will coincide with the top edge of
+ % the box below it.
+ \setlength{\@tempdima}{\gridsize}
+ \addtolength{\@tempdima}{\gridlinewidth}
+ \setlength{\@tempdimb}{\gridsize}
+ \addtolength{\@tempdimb}{-\gridlinewidth}
+ \setbox0=\hbox{%
+ \rlap{\vrule height \gridsize depth \gridlinewidth width \gridlinewidth}%
+ \rlap{\vrule height \gridsize depth -\@tempdimb width \@tempdima}%
+ \vrule height 0pt depth \gridlinewidth width \@tempdima
+ \llap{\vrule height \gridsize depth \gridlinewidth width \gridlinewidth}%
+ }%
+ \wd0=\gridsize
+ \dp0=0pt
+ % Now we set box1 equal to an \hbox containing a single line of
+ % copies of box0. We use \leaders (instead of \cleaders) so that
+ % if we use it twice on a page, once with a question and once
+ % with a part, the boxes will line up vertically. We add a kern of
+ % \gridlinewidth at the right because the rightmost vertical line
+ % appears to the right of where the \leaders command thinks that it
+ % appears.
+ \setbox1=\hbox to \textwidth{%
+ \color@begingroup
+ \if@colorgrids
+ \color{GridColor}%
+ \fi
+ \hskip \@totalleftmargin \leaders\copy0\hfil \kern\gridlinewidth
+ \color@endgroup
+ }%
+ % Finally: We create the grid, using \cleaders: We use \cleaders
+ % (rather than \leaders) so that a given vertical space will always
+ % produce the same number of lines no matter where on the page it
+ % happens to start. We add a kern of \gridlinewidth because the
+ % bottommost horizontal line appears below where the \cleaders
+ % command thinks that it appears.
+ \cleaders \copy1 \vskip #1 \kern \gridlinewidth \hbox{}%
+ \endgroup
+}% fillwithgrid
%--------------------------------------------------------------------
% \makeemptybox
@@ -4331,8 +4482,9 @@
% \bonuspointtable, \combinedpointtable, \partialgradetable,
% \partialbonusgradetable, \partialcombinedtable, \partialpointtable,
% \partialbonuspointtable, \partialcombinedpointtable,
-% \begingradingrange, \endgradingrange, \pointsinrange, and
-% \bonuspointsinrange.
+% \begingradingrange, \endgradingrange, \pointsinrange,
+% \bonuspointsinrange, \firstqinrange, \lastqinrange, and
+% \numqinrange.
% The possibilities are
@@ -4402,6 +4554,10 @@
% \pointsinrange{whatever}
% \bonuspointsinrange{whatever}
%
+% \firstqinrange{whatever}
+% \lastqinrange{whatever}
+% \numqinrange{whatever}
+%
% where ``whatever'' is a label chosen by the user.
% If one or both optional arguments are omitted, the defaults are
@@ -4429,11 +4585,11 @@
\addtocounter{num@cols}{1}%
\immediate\write\@mainaux
{\string\expandafter\string\gdef
- \string\csname\space tbl@#1@firstq\string\endcsname
+ \string\csname\space range@#1@firstq\string\endcsname
{\arabic{num@cols}}}%
\write\@mainaux
{\string\expandafter\string\gdef
- \string\csname\space tbl@#1@firstp\string\endcsname
+ \string\csname\space range@#1@firstp\string\endcsname
{\thepage}}%
}% begingradingrange
@@ -4441,11 +4597,11 @@
\setcounter{num@cols}{\value{question}}%
\immediate\write\@mainaux
{\string\expandafter\string\gdef
- \string\csname\space tbl@#1@lastq\string\endcsname
+ \string\csname\space range@#1@lastq\string\endcsname
{\arabic{num@cols}}}%
\write\@mainaux
{\string\expandafter\string\gdef
- \string\csname\space tbl@#1@lastp\string\endcsname
+ \string\csname\space range@#1@lastp\string\endcsname
{\thepage}}%
}% endgradingrange
@@ -4706,18 +4862,18 @@
\def\find@qrange#1{%
% We're doing a table indexed by question numbers.
\if@partial
- \@ifundefined{tbl@\tbl@range @firstq}%
+ \@ifundefined{range@\tbl@range @firstq}%
{%
\range@undefined
}%
{%
- \@ifundefined{tbl@\tbl@range @lastq}%
+ \@ifundefined{range@\tbl@range @lastq}%
{%
\range@undefined
}%
{%
- \edef\tbl@firstq{\csname tbl@\tbl@range @firstq\endcsname}%
- \edef\tbl@lastq{\csname tbl@\tbl@range @lastq\endcsname}%
+ \edef\tbl@firstq{\csname range@\tbl@range @firstq\endcsname}%
+ \edef\tbl@lastq{\csname range@\tbl@range @lastq\endcsname}%
% Check that firstq precedes or equals lastq:
\ifnum \tbl@firstq > \tbl@lastq\relax
\fbox{Error: Grading Range `\tbl@range ':
@@ -5231,18 +5387,18 @@
% combined table, it's the last page to have either bonus or
% non-bonus points).
\if@partial
- \@ifundefined{tbl@\tbl@range @firstp}%
+ \@ifundefined{range@\tbl@range @firstp}%
{%
\range@undefined
}%
{%
- \@ifundefined{tbl@\tbl@range @lastp}%
+ \@ifundefined{range@\tbl@range @lastp}%
{%
\range@undefined
}%
{%
- \edef\tbl@firstp{\csname tbl@\tbl@range @firstp\endcsname}%
- \edef\tbl@lastp{\csname tbl@\tbl@range @lastp\endcsname}%
+ \edef\tbl@firstp{\csname range@\tbl@range @firstp\endcsname}%
+ \edef\tbl@lastp{\csname range@\tbl@range @lastp\endcsname}%
% Check that firstp precedes or equals lastp:
\ifnum \tbl@firstp > \tbl@lastp\relax
\fbox{Error: Grading Range `\tbl@range ':
@@ -6068,18 +6224,18 @@
}% bad@range
\def\read@range{%
- \@ifundefined{tbl@\tbl@range @firstq}%
+ \@ifundefined{range@\tbl@range @firstq}%
{%
\bad@range
}%
{%
- \@ifundefined{tbl@\tbl@range @lastq}%
+ \@ifundefined{range@\tbl@range @lastq}%
{%
\bad@range
}%
{%
- \edef\tbl@firstq{\csname tbl@\tbl@range @firstq\endcsname}%
- \edef\tbl@lastq{\csname tbl@\tbl@range @lastq\endcsname}%
+ \edef\tbl@firstq{\csname range@\tbl@range @firstq\endcsname}%
+ \edef\tbl@lastq{\csname range@\tbl@range @lastq\endcsname}%
% Check that firstq precedes or equals lastq:
\ifnum \tbl@firstq > \tbl@lastq\relax
\fbox{Error: Grading Range `\tbl@range ':
@@ -6129,7 +6285,39 @@
\next@countloop
}% do@countloop
+%--------------------------------------------------------------------
+% \firstqinrange, \lastqinrange, and \numqinrange.
+\newcommand{\firstqinrange}[1]{%
+ \@ifundefined{range@#1@firstq}%
+ {\mbox{\normalfont\bf ??}}%
+ {\csname range@#1@firstq\endcsname}%
+}% firstqinrange
+
+\newcommand{\lastqinrange}[1]{%
+ \@ifundefined{range@#1@lastq}%
+ {\mbox{\normalfont\bf ??}}%
+ {\csname range@#1@lastq\endcsname}%
+}% lastqinrange
+
+\newcommand{\numqinrange}[1]{%
+ \@ifundefined{range@#1@firstq}%
+ {%
+ \mbox{\normalfont\bf ??}%
+ }%
+ {%
+ \@ifundefined{range@#1@lastq}%
+ {%
+ \mbox{\normalfont\bf ??}%
+ }%
+ {%
+ \setcounter{@iterator}{\csname range@#1@lastq\endcsname}%
+ \addtocounter{@iterator}{-\csname range@#1@firstq\endcsname}%
+ \stepcounter{@iterator}%
+ \arabic{@iterator}%
+ }%
+ }%
+}% numqinrange
%--------------------------------------------------------------------
%--------------------------------------------------------------------
@@ -6158,6 +6346,15 @@
\def\cancelspace{\cancelspacetrue}
\def\nocancelspace{\cancelspacefalse}
+% \if@insolution will be true while we're inside of any of the
+% solution environments. This is used to supress \PgInfo@write and
+% \label commands generated if there's a parts (or subparts, or
+% subsubparts) environment inside of a solution. (It won't suppress
+% the labels for the question objects, since a question object is
+% never a label that's been used before.)
+\newif\if@insolution
+\@insolutionfalse
+
\newcommand\SolutionEmphasis[1]{%
\def\Solution@Emphasis{#1}%
}
@@ -6169,6 +6366,8 @@
% default value of which is 0pt).
\newenvironment{solution}[1][0pt]%
{%
+ \@insolutiontrue % cancelled by the end of the environment
+ \@addpointsfalse % cancelled by the end of the environment
\ifprintanswers
\begingroup
\Solution@Emphasis
@@ -6200,6 +6399,8 @@
% then the box is entirely omitted when printanswers is false.
\newenvironment{solutionorbox}[1][-1pt]%
{%
+ \@insolutiontrue % cancelled by the end of the environment
+ \@addpointsfalse % cancelled by the end of the environment
\ifprintanswers
\begingroup
\Solution@Emphasis
@@ -6247,6 +6448,8 @@
% default value of which is 0pt).
\newenvironment{solutionorlines}[1][0pt]%
{%
+ \@insolutiontrue % cancelled by the end of the environment
+ \@addpointsfalse % cancelled by the end of the environment
\ifprintanswers
\begingroup
\Solution@Emphasis
@@ -6276,6 +6479,8 @@
% argument (the default value of which is 0pt).
\newenvironment{solutionordottedlines}[1][0pt]%
{%
+ \@insolutiontrue % cancelled by the end of the environment
+ \@addpointsfalse % cancelled by the end of the environment
\ifprintanswers
\begingroup
\Solution@Emphasis
@@ -6299,14 +6504,47 @@
\fi
}%
+% If printanswers is true, we print the solution using a TheSolution
+% environment. If printanswers is false and cancelspace is false,
+% we insert a grid occupying vertically the optional argument (the
+% default value of which is 0pt).
+\newenvironment{solutionorgrid}[1][0pt]%
+ {%
+ \@insolutiontrue % cancelled by the end of the environment
+ \@addpointsfalse % cancelled by the end of the environment
+ \ifprintanswers
+ \begingroup
+ \Solution@Emphasis
+ \begin{TheSolution}%
+ \else
+ \ifcancelspace
+ % Do nothing
+ \else
+ \par
+ \penalty 0
+ \fillwithgrid{#1}%
+ \fi
+ \setbox\z@\vbox\bgroup
+ \fi
+ }{%
+ \ifprintanswers
+ \end{TheSolution}%
+ \endgroup
+ \else
+ \egroup
+ \fi
+ }%
+
+
% The environment TheSolution is called from the solution,
-% 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), (or no box at all, if the user has given the
-% command \unframedsolutions).
+% solutionorbox, solutionorlines, solutionordottedlines, and
+% solutionorgrid 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), (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}
@@ -6369,6 +6607,90 @@
}
\def\unframedsolutions{\@framedsolutionsfalse\@shadedsolutionsfalse}
+
+% The solutionbox environment is different from the other solution
+% environments (solution, solutionorbox, solutionorlines,
+% solutionordottedlines, and solutionorgrid), in that
+%
+% (1) The box is always printed, whether answers are being printed
+% or not.
+%
+% (2) The argument giving the size of the box is a required
+% argument, not an optional argument, and so it should be enclosed
+% in braces, not in brackets. It can be either a length or
+% \stretch{number}.
+%
+% (3) We make no use of the TheSolution environment; the solutionbox
+% environment is completely freestanding.
+%
+% If answers are not being printed then only the box is printed, with
+% nothing in it. If answers are being printed, then the solution is
+% printed inside of the box.
+%
+% Note: It's the user's responsibility to be sure that the box is
+% large enough to hold the solution! If the solution takes up too
+% much vertical space, then it will spill out of the bottom of the
+% box, overwriting whatever follows the box.
+
+\newbox\exam@box
+\newenvironment{solutionbox}[1]{%
+ \@insolutiontrue % cancelled by the end of the environment
+ \@addpointsfalse % cancelled by the end of the environment
+ \def\solutionbox@size{#1}% saved for end of environment
+ \@tempdima=\textwidth
+ \advance\@tempdima -\@totalleftmargin
+ \advance\@tempdima -6\fboxsep
+ \advance\@tempdima -2\fboxrule
+ % Confine the \Solution@Emphasis, as well as anything the user puts
+ % into the solution (e.g., \color{red}, or whatever); don't say
+ % \endgroup until after using \box\exam@box:
+ \begingroup
+ \Solution@Emphasis
+ % We save the solution in a box of the proper width. We'll either
+ % print it (if we're printing solutions) or throw it away by just
+ % not using it before the environment ends:
+ \setbox\exam@box=\vtop\bgroup
+ \hsize=\@tempdima
+ \leftskip=0pt
+ \rightskip=0pt
+ \vskip 2\fboxsep
+ \solutiontitle
+ \ignorespaces
+ }%
+ {%
+ \unskip
+ \egroup
+ % OK, the solution is now inside \box\exam@box.
+ % Set the height and depth to 0pt, so that if we use it we won't
+ % be advancing our position on the page:
+ \ht\exam@box=0pt
+ \dp\exam@box=0pt
+ \par
+ \vspace{\parskip}
+ \ifprintanswers
+ % We enclose the \vtop in an \hbox to avoid having the
+ % indentation of the enclosing list environment (implemented via
+ % \parshape) shift us to the right when we enter horizontal
+ % mode. If we don't use this \hbox, then we'd have to comment
+ % out the \hskip \@totalleftmargin:
+ \hbox to \textwidth{%
+ \noindent
+ \hskip\@totalleftmargin
+ \hskip3\fboxsep\hskip\fboxrule
+ \box\exam@box\hfill
+ }%
+ \par\nointerlineskip
+ \fi
+ \endgroup % Finish confining the \Solution@Emphasis
+ \makeemptybox{\solutionbox@size}%
+ }
+
+
+
+
+
+
+
%--------------------------------------------------------------------
%--------------------------------------------------------------------