% exam.cls
%
% A LaTeX2e document class for preparing exams.

%% exam.cls
%% Copyright (c) 1994, 1997, 2000, 2004 Philip S. Hirschhorn
%
% This work may be distributed and/or modified under the
% conditions of the LaTeX Project Public License, either version 1.3
% of this license or (at your option) any later version.
% The latest version of this license is in
%   http://www.latex-project.org/lppl.txt
% and version 1.3 or later is part of all distributions of LaTeX
% version 2003/12/01 or later.
%
% This work has the LPPL maintenance status "author-maintained".
% 
% This work consists of the files exam.cls and examdoc.tex.


% The user documentation for exam.cls is in the file examdoc.tex.


%%% Philip Hirschhorn
%%% Department of Mathematics
%%% Wellesley College
%%% Wellesley, MA 02481
%%% psh@math.mit.edu

% The newest version of this documentclass should always be available
% from my web page: http://www-math.mit.edu/~psh/


\def\fileversion{2.2}
\def\filedate{2004/08/14}
%---------------------------------------------------------------------
%---------------------------------------------------------------------
% PLEASE DO NOT MAKE ANY CHANGES TO THIS FILE!
% 
% If you wish to make changes to this file, rename this file
% to something other than exam.cls BEFORE YOU MAKE THE CHANGES!
% 
% If there's some feature that you'd like that this file doesn't
% provide, tell me about it.
% 
%
%
%
%
% Thanks to:
%
% Piet van Oostrum, from whose excellent ``fancyheadings.sty'' we
% shamelessly stole most of the code for setting the headers and
% footers.
%
% Mate Wierdl <mw@wierdlmpc.msci.memphis.edu>, who contributed the
% code so that if the number of points is ``1'', then the default
% value of \pointname will print ``1 point'' instead of ``1 points''.
%
% Tom Brikowski <brikowi@utdallas.edu>, who contributed the code for
% making the number of points and number of questions available as
% macros (as well as the idea of putting the number of points in a 
% box, instead of in parentheses).  (I changed his code to make this
% all optional, so if there are errors there, it's my fault and not
% his.)
%
% Ottmar Beucher <beucher@fh-karlsruhe.de>, Dan Drake
% <drake@math.umn.edu>, and Justus Piater <Justus.Piater@ULg.ac.be> who
% contributed ideas and code for the \pointsofquestion and \gradetable
% commands for printing a Grading Table.  (I changed all the code to
% make this compatible with hyperref.sty, so if there are errors there,
% it's my fault and not theirs.)
%
% Justus Piater <Justus.Piater@ULg.ac.be>, who contributed the code for
% the solution environment.  (I changed his code to allow page breaks
% inside solutions so, once again, if it's buggy, it's my fault.) 
%
% Donald Arseneau <asnd@triumf.ca>, who created the excellent
% ``framed.sty'' and generously allowed me to include basically the
% whole thing in exam.cls, making the few changes needed for it to
% work well with question environments:
% framed.sty   v 0.8a   21-Jul-2003
% Copyright (C) 1992-2003 by Donald Arseneau
% These macros may be freely transmitted, reproduced, or modified
% provided that this notice is left intact.
%
%--------------------------------------------------------------------
%--------------------------------------------------------------------
%                             Changelog:


% Version 2.2:
%
% Enough already with betatest.
%
%--------------------------------------------------------------------
%
% Version 2.116$\beta$:
%
% We futzed with the oneparchoices environment so that a bit more
% space will be left before the first choice when the list of choices
% continues the paragraph of the question.
%
%--------------------------------------------------------------------
%
% Version 2.115$\beta$:
%
% New environment: oneparchoices
%
% Intended for multiple choice questions (just like the choices
% environment), except that the oneparchoices prints all the choices in
% a single paragraph.  This environment does *not* create a paragraph
% break at its beginning, so if you begin the environment without
% skipping a line before it, the choices will be printed as a
% continuation of the paragraph preceding the environment.
%
%--------------------------------------------------------------------
%
% Version 2.114$\beta$:
%
% We fixed up the code for \uplevel and \fullwidth so that they work
% correctly if a solution environment is inside the argument.
%
%--------------------------------------------------------------------
%
% Version 2.113$\beta$:
%
% Added code to warn if point totals have changed since the last run of
% LaTeX (which requires running LaTeX again to make sure that
% gradetables, pointsofquestion, and pointsonpage values are correct).
%
%
% We also added code to create a label for every question, part,
% subpart, and subsubpart.  We make no use of these labels, but we put
% them there so 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.
%
%--------------------------------------------------------------------
%
% Version 2.112$\beta$:
%
% New environment: coverpages
%
% This is for use only *before* any questions (or parts, or subparts, or
% subsubparts).  It allows you to print one or more cover pages,
% numbered in a different sequence of page numbers from the main pages.
% That is, the page number is reset to 1 at the end of a coverpages
% environment.
%
% The default is that headers and footers are empty on the coverpages,
% but if you print the page number (using \thepage in the header or
% footer) then the page number will be printed in roman numerals.  When
% the coverpages environment ends, the page number is reset to 1 and the
% page numbers revert to the (standard) arabic numbers.
%
% Headers and footers on coverpages are determined by commands
% completely analogous to the relevant commands for the main pages,
% except that the names of the commands begin with the word ``cover''.
% That is, the following commands are available to define headers and
% footers, and to leave additional space for the headers and footers as
% needed: 
%
%
% New commands:
%
% \coverheader
% \coverrunningheader
% \coverfirstpageheader
%
% \coverlhead
% \coverchead
% \coverrhead
%
% \coverfooter
% \coverrunningfooter
% \coverfirstpagefooter
%
% \coverlfoot
% \covercfoot
% \coverrfoot
%
% \coverextraheadheight
% \coverextrafootheight
%
%--------------------------------------------------------------------
%
% Version 2.111$\beta$:
%
% Bugfix: There was an incompatibility with spanish.ldf (loaded when the
% user loads the babel package with the spanish option) (and possibly
% with other language packages as well).  That file redefines \@roman,
% which is used by \roman, which I had used to define some internally
% used command names.  I replaced
%
%   \roman{countername}
%
% with
%
%   \romannumeral \csname c@countername\endcsname
%
% for all of those command names, and now all at least seems to be
% well.
%
%
% The following stuff isn't really complete yet:
% New environment: coverpages
%
% New commands:
%
% \coverheader
% \coverrunningheader
% \coverfirstpageheader
%
% \coverlhead
% \coverchead
% \coverrhead
%
% \coverfooter
% \coverrunningfooter
% \coverfirstpagefooter
%
% \coverlfoot
% \covercfoot
% \coverrfoot
%
% \coverextraheadheight
% \coverextrafootheight
%
%--------------------------------------------------------------------
%
% Version 2.110$\beta$:
%
% We change the definition of \half to print a fraction one half that
% uses a slanted fraction bar.  We also created two new commands:
%
%   \newcommand*\usehorizontalhalf
%   \newcommand*\useslantedhalf
%
% The first one changes the definition of \half so that it produces a
% fraction with a horizontal fraction bar (via $\frac{1}{2}$), and the
% second one returns the definition of \half to its default.
%
%--------------------------------------------------------------------
%
% Version 2.109$\beta$:
%
% Point values for questions (and parts, etc.) can now include half
% points.  To specify a half point, you include ``\half'' immediately
% following the integer part (or just with ``\half'' if the integer part
% is zero).  For example, the following are all valid point values:
%
% 0
% \half
% 1
% 1\half
% 2
% 2\half
% Etc.
%
%--------------------------------------------------------------------
%
% Version 2.108$\beta$:
%
% New environment: solutionorlines
%
% This is almost identical to the solution 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 ruled lines (created by \fillwithlines), rather than being
% left blank (as it is by the solution environment).
%
% Also: Changed the shade of gray used as the default color for
%       \shadedsolutions.
%
%       Changed the default thickness of lines used by \fillwithlines.
%
%--------------------------------------------------------------------
%
% Version 2.107$\beta$:
%
% We added an option to have solution environments use a \colorbox (from
% the color package) instead of an \fbox.  Instead of surrounding the
% solution with a printed box, it prints the solution on a colored
% background.  The default color is a light gray (so that it can be
% printed on any printer that can do grayscale), but the color can be
% changed.
%
% To use this option, the user must load the color package with the
% command
%
%   \usepackage{color}
%
% in the preamble.  (If appropriate, optional arguments can be used in
% that command.)  The user can then give the command
%
%   \shadedsolutions
%
% to have all solutions printed using a \colorbox.  After giving that
% command, the user can change the color of the backgrounds of solutions
% by defining the color ``SolutionColor''.  The default SolutionColor is
% set via the command
%
%   \definecolor{SolutionColor}{gray}{0.9}
%
% and the user can change that by giving a \definecolor command *after*
% giving the command \shadedsolutions.  For example, the command
%
%   \definecolor{SolutionColor}{rgb}{0.8,0.9,1}
%
% sets the background color to a light blue.
%
% You can return to the default situation of having solutions printed
% inside an \fbox by giving the command
%
%   \framedsolutions
%
% Note added later: The default shade of gray was changed in version
% 2.108$\beta$.
%
%--------------------------------------------------------------------
%
% Version 2.106$\beta$:
%
%
% We redid the solution environment to use Donald Arseneau's framed.sty
% macros, so that the solution can be broken across pages with each
% piece enclosed in a frame.
%
% We also changed the default definition of \solutiontitle; it's now
% defined by:
%
%  \newcommand{\solutiontitle}{\noindent\textbf{Solution:}\enspace}
%
%
%--------------------------------------------------------------------
%
% Version 2.105$\beta$:
%
% We're making the thickness of the lines used by \fillwithlines
% changeable, and changing the default thickness.
%
% We're doing this by defining a new command:
%
%   \linefill,
%
% which is similar to \hrulefill, except that \linefill uses a line of
% height \linefillthickness, whose default value is 0.2pt.
% (\fillwithlines used to use \hrulefill, which uses a line of height
% 0.4pt.)
%
% The default value of \linefillthickness is set by the command
%
%   \setlength\linefillthickness{0.2pt}
%
% and this can be changed by giving a new \setlength command.
%
% Note added later: The default thickness was changed in version
% 2.108$\beta$.
%
%--------------------------------------------------------------------
%
% Version 2.104$\beta$:
%
% We added a new command: \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.
%
% The distance between the lines is \linefillheight, whose default value
% is set with the command
%
%   \setlength\linefillheight{.25in}
%
% This value can be changed by giving a new \setlength command.
%
%--------------------------------------------------------------------
%
% Version 2.103$\beta$:
%
% We added a new command: \answerline
%
% This is intended for short answer questions.  It inserts a \vskip of
% length \answerskip and then inserts a horizontal line of length
% \answerlinelength at the right margin, preceded by the number of the
% current question, part, subpart, or subsubpart.
%
% The default values are set by the commands
%
%   \setlength\answerlinelength{1in}
%   \setlength\answerskip{2ex}
%
% and these can be changed by giving new \setlength commands.
%
%--------------------------------------------------------------------
%
% Version 2.101$\beta$:
%
% We eliminated the command \marks, since it conflicts with a definition
% of that name in some package or other.  We changed the definition of
% \marksnotpoints so that it still accomplishes the same thing, but now
% it works through the \pointpoints command.
%
% We changed the default format for the \droptotalpoints command, so
% that it now prints
%
%   Total for Question 1: 25
%
% where the ``25'' is followed by \marginpointname, whose default value
% is empty.
%
%--------------------------------------------------------------------
%
% Version 2.098$\beta$:
%
% We moved the definitions of \thepartno, \thesubpart, and
% \thesubsubpart outside of the associated list environments, so that
% the user can redefine them once at the beginning of the LaTeX file and
% not have their redefinition overridden in every such list.
%
% We also replaced most occurrences of \thequestion with
% \arabic{question}, so that the user can safely redefine \thequestion
% to something like \Alph{question}, etc.
%
% We rewrote the components of the \gradetable[v][questions] and
% \gradetable[h][questions] to use the question counter in place of
% @iterator, and to insert \thequestion instead of \the@iterator as the
% question number in the table (so that if the user redefines
% \thequestion, then the table will print the question ``numbers'' (or
% letters, etc.) in whatever format \thequestion prints the question
% numbers on the exam).
%
% We also created a new command:
%
%   \totalpoints
%
% for use in the argument of a \totalformat command.  \totalpoints is
% just an abbreviation for \pointsofquestion{\arabic{question}}.  That
% is, it's a macro that prints the total number of points for the
% current question.
%
% We changed the longsolution environment to make it easy to change the
% amount by which the left and right margins are increased.  The default
% amount is set by the command
%
%   \setlength{\longsolutionindent}{2em}
%
% and the user can change this by giving a new \setlength command.
%
% Note added later: longsolution was eliminated in version
% 2.106$\beta$.
%
%--------------------------------------------------------------------
%
% Version 2.097$\beta$:
%
% We've changed the default format for the total points for a question
% printed by the \droptotalpoints command.  This command still prints
% the total points for the question right justified a distance of
% \rightpointsmargin from the right edge of the paper, but now the
% number of points will, by default, be surrounded by either
%
%   a double box, if \boxedpoints is in effect,
%   double brackets, if \bracketedpoints is in effect, or
%   double parentheses, otherwise.
%
% It's still true that if you use a \totalformat command, then the
% format of the printed total points is completely controlled by the
% argument of the \totalformat command and the default doesn't matter at
% all.
%
%
% Note added later: We changed the default format again in version
% 2.101$\beta$; see the notes above.
%
%--------------------------------------------------------------------
%
% Version 2.096$\beta$:
%
% The labels for questions, parts, subparts, and subsubparts can now be
% customized.  The format now depends on the commands
%
%   \questionlabel
%   \partlabel
%   \subpartlabel
%   \subsubpartlabel
%
% the default definitions of which are:
%
%   \newcommand\questionlabel{\thequestion.}
%   \newcommand\partlabel{(\thepartno)}
%   \newcommand\subpartlabel{\thesubpart.}
%   \newcommand\subsubpartlabel{\thesubsubpart)}
%
% These definions can be changed by using a \renewcommand command.
% Note that the definition of \partlabel used `\thepartno', and *not*
% `\thepart'.  This is because `\thepart' refers to the counter for the
% standard sectioning command \part, and not the counter used in the
% parts environment.  The counter used by the parts environment is
% inserted with the command `\thepartno'.
%
%--------------------------------------------------------------------
%
% Version 2.095$\beta$:
%
% Added solution and longsolution environments.
%
% The command \printanswers causes both of these environments print the
% solution, and the command \noprintanswers causes both of these
% environments not to print the solution.  The default is
% \noprintanswers.
%
% The commands \printanswers and \noprintanswers can be given as many
% times as desired to switch back and forth between the two.
%
% The documentclass option ``answers'' is equivalent to giving a
% \printanswers command at the beginning of the file.
%
%
% Both of these environments take an optional argument which is an
% amount of blank vertical space to be left when \noprintanswers is in
% effect.  (The default value of this blank vertical space is 0pt.)
%
%
% The solution environment prints the solution inside of a box, which
% cannot be broken across pages.  Thus, it is only appropriate for
% solutions that are short enough to fit on a page.
%
% The longsolution environment prints the solution with left and right
% margins slightly increased, and it can be broken across pages.
%
% When printing the solution, both environments begin with
% \solutiontitle, the default value of which is created by the command
%
% \newcommand{\solutiontitle}{\textbf{Solution:}\enspace}
%
% This can be changed with the \renewcommand command.
%
% Note added later: solution was changed and longsolution was
% eliminated in version 2.106$\beta$.
%
%--------------------------------------------------------------------
%
% Version 2.094$\beta$:
%
% We've expanded the options of the \gradetable command, so that you
% can now get a grading table indexed by either question numbers or by
% page numbers, and in either case you can have either a horizontally
% oriented table or a vertically oriented table.
%
% \gradetable now takes two optional arguments: The first can be either
% `[v]' or `[h]', and the second can be either `[questions]' or
% `[pages]'.  The defaults are `[v]' and `[questions]', and you must
% specify a first option if you want to specify a second option.
%
% Thus: \gradetable is equivalent to \gradetable[v][questions]
%
% `[v]' and `[h]' are as before: Vertically oriented or horizontally
% oriented.
%
% `[questions]' is the same as the earlier version: A table that lists
% the question numbers, the possible total points for each question the
% total for the entire exam, and spaces are left for the score on each
% question.
%
% `[pages]' prints a table indexed by page numbers instead of by
% question numbers.  It lists only the numbers of pages that have points
% on them, and for each such page it lists the number of points possible
% on that page.  It also lists the total possible points on the exam,
% and spaces are left for the score on each page.
%
% For both tables indexed by questions and tables indexed by points,
% there are commands that allow you to change the column and row
% headings (the following are shown setting the default values:)
%
%    \hpword{Points:}
%    \hsword{Score:}
%    \htword{Total}
%    \vpword{Points}
%    \vsword{Score}
%    \vtword{Total:}
%
% For tables indexed by questions, the appropriate row and column titles
% are set by the following commands:
%
%    \hqword{Question:}
%    \vqword{Question}
%
% For tables indexed by pages, the appropriate row and column titles are
% set by the following commands:
%
%    \hpgword{Page:}
%    \vpgword{Page}
%
%
% For both \gradetable[h] and \gradetable [v], the width of the blank
% cells created for filling in the grades can be changed with the
% command \cellwidth, and the arraystretch applied to the table can be
% changed with the command \gradetablestretch.  The default values are
% created by the commands:
%
%   \cellwidth{2em}
%   \gradetablestretch{1.5}
%
%--------------------------------------------------------------------
%
% Version 2.093$\beta$:
%
% If the user gives the comman \addpoints, then
% \pointsonpage{n} expands to the number of points on page n.
%
%--------------------------------------------------------------------
%
% Version 2.092$\beta$:
%
% Increased the \leftmargin in the choices environment.
%
%--------------------------------------------------------------------
%
% Version 2.091$\beta$:
%
% New commands:
% \pointsdroppedatright
% \droppoints
% \droptotalpoints
% \totalformat
%
% \pointsdroppedatright: The command \pointsdroppedatright causes points
% not to be printed until you give the command \droppoints, except that
% a \qformat command still works as expected (i.e., if you include
% ``\thepoints'' in the argument of the \qformat, it will print the
% points as usual).
%
%
% \droppoints: The command \droppoints should be given only at the end
% of a paragraph or between paragraphs; if you give it within a
% paragraph, it causes the paragraph to end.  \droppoints prints the
% most recent point value in the right margin, formatted as it is when
% you give the command \pointsinrightmargin, except that the points
% appear opposite the last line of the paragraph (or, if the command
% \droppoints is given between paragraphs, then additional vertical
% space is left between the paragraphs and the points are printed
% opposite the blank space).  Thus, the formatting can be changed by
% using giving the commands \bracketedpoints, \boxedpoints, or
% \marginpointname.
%
% The command \droppoints actually works this way even if one of the
% commands \pointsdroppedatright, \pointsinmargin, or
% \pointsinrightmargin, is in effect, but if you use it that way the
% points will appear twice on the page.
%
%
% \droptotalpoints: To use the command \droptotalpoints, you must first
% give the command \addpoints.  The command \droptotalpoints should be
% given only at the end of a paragraph or between paragraphs; if you
% give it within a paragraph, it causes the paragraph to end.
% \droptotalpoints prints the total points for the current question
% (i.e., the sum of the points assigned to the question and to all of
% its parts, subparts, and subsubparts) in the right margin, formatted
% formatted by default inside either double brackets, double box, or
% double parentheses, depending on whether \bracketedpoints,
% \boxedpoints, or neither is in effect.
%
% \totalformat: The \totalformat command allows you to change the format
% used by the \droptotalpoints command.  It takes one argument, and that
% argument becomes the command to print the total points, right
% justified a distance of \rightpointsmargin from the right edge of the
% paper.  The argument should contain the expression
% ``\pointsofquestion{\arabic{question}}'' at the point at which the number
% of points should appear.  For example, the command
%
%   \totalformat{[\pointsofquestion{\arabic{question}}]}
%
% will produce the same appearance as the default does when the command
% \bracketedpoints is in effect and \marginpointname is empty, and the
% command
%
%   \totalformat{\fbox{Total: \pointsofquestion{\arabic{question}}}}
%
% produces a box surrounding ``Total: 25''.
%
%--------------------------------------------------------------------
%
% Version 2.087$\beta$:
%
% We changed ``\point@toks={}'' into ``\global \point@toks={}'' when
% \point@toks is set, so that if the user somehow arranges for us to be
% inside of a group when we enter horizontal mode, the \point@toks will
% be properly set equal to null, and so the points won't accidentally be
% placed a second time at the second paragraph of the question.
%
% Similarly, we changed ``\pageinfo@commands={}'' to 
% ``\global \pageinfo@commands={}''.
%
%--------------------------------------------------------------------
%
% Version 2.080$\beta$:
%
% We added a new command \gradetable that produces a grading table,
% oriented either vertically or horizontally, that lists the questions,
% their point values, and the total points, and leaves spaces for
% entering the grade for each question and the total grade.  We also
% added a new command \pointsofquestion that takes one argument that is
% assumed to be the number of a question and returns the total number of
% points for that question.  \pointsofquestion is used by the
% \gradetable command, but the user can choose to use it separately.

% To use either \gradetable or \pointsofquestion, the user must give the
% command \addpoints.  \pointsofquestion{n} will then return the total
% number of points for question n and all of its parts, subparts, and
% subsubparts.  Since all this information is stored in the .aux file
% and then read back on the next run of LaTeX, the user must run LaTeX
% twice after any changes to the questions or points.

% \gradetable[h] produces a horizonatlly oriented grade table, and
% \gradetable[v] produces a vertically oriented grade table.  The
% command \gradetable is equivalent to \gradetable[v].

% \gradetable[h] produces a table with three rows, titled (by default)
% ``Question:'', ``Points:'', and ``Score:'' (the titles are in the
% first column of the table).  There is then one column for each
% question (with the question number and point value in the first two
% rows), plus a final column labelled ``Total'' with the total points in
% the second row.

% \gradetable[v] produces a table with three columns, titled (by
% default) ``Question'', ``Points'', and ``Score'' (the titles are in
% the first row of the table).  There is then one row for each question
% (with the question number and point value in the first two columns),
% plus a final row labelled ``Total:'' with the total points in the
% second column.

% Note that \gradetable[h] produces row titles whose default values
% contains colons, while \gradetable[v] produces column titles whose
% default values do not contain colons.

% The row and column titles and the word ``Total'' can be changed using
% the commands \hqword, \hpword, \hsword, \htword, \vqword,
% \vpword, \vsword, and \vtword, where the first four affect
% \gradetable[h] and the second four affect \gradetable[v].  The default
% values are created by the commands:

%   \hqword{Question:}
%   \hpword{Points:}
%   \hsword{Score:}
%   \htword{Total}
%   \vqword{Question}
%   \vpword{Points}
%   \vsword{Score}
%   \vtword{Total:}

% For both \gradetable[h] and \gradetable [v], the width of the blank
% cells created for filling in the grades can be changed with the
% command \cellwidth, and the arraystretch applied to the table can be
% changed with the command \gradetablestretch.  The default values are
% created by the commands:

%   \cellwidth{2em}
%   \gradetablestretch{1.5}



% Changing the definition of \points:

% The default definition of \points is that it expands to ``point'' if
% the number of points is 1 and to ``points'' otherwise.  There is now a
% command ``\pointpoints'' that takes two arguments, after which
% \points will expand to the first argument when the number of points is
% 1 and to the second argument otherwise.  For example, the default is
% the result of the command \pointpoints{point}{points}.
%
%--------------------------------------------------------------------
%
% Version 2.070$\beta$:
%
% We made this compatible with hyperref.sty.
% We did this by eliminating all use of LaTeX's 
% \label, \newlabel, \ref, and \pageref commands.
% We now put information into the .aux file using the
% \PgInfo@write command, and get that info out of the aux file
% using \PgInfo and \PgInfo@get, along with a few \gdef commands
% written straight to the .aux file.
%
%--------------------------------------------------------------------
%
% Version 2.067$\beta$:
%
% We're adding code to enable headers and footers
% to know whether the current page continues a question started on an
% earlier page, and whether the page ends with a question still
% incomplete.

%--------------------------------------------------------------------
% For use in headers and footers:
%
% \ifcontinuation{Text 1}{Text 2}
% Expands to ``Text 1'' if this page begins with a part or subpart or
% subsubpart that continues a question begun on an earlier page, and
% expands to ``Text 2'' if this page begins with a new question.
%
% \ContinuedQuestion expands to the number of the question that is
% being continued from an earlier page.
%
% \ifincomplete{Text 1}{Text 2}
% Expands to ``Text 1'' if the last question begun on or before this
% page has a part, subpart, or subsubpart that begins on a later page,
% and if we have not yet encountered a \nomorequestions command.
%
% \IncompleteQuestion expands to the number of the question that is
% continued on the next page.
%
% \nomorequestions is a command that you can give after the last
% question if you intend to include extra material (e.g., tables for
% use on the exam) but you don't want the pages containing the extra
% material to be labelled as continuing the last question on the exam.
%
%--------------------------------------------------------------------
%
%
% Also: 
% Changed the code for headers and footers to
% use the command \normalfont instead of \rm so that the main
% document font will appear in headers and footers even when the
% main document font is *not* a roman font.
%
% \def\marksnotpoints
%
% Changes \pointname so that it is identical to the default \pointname
% except that the work ``mark'' is used instead of the word
% ``point''.  That is, if the number of points is 1, then you'll get
% ``1 mark'', and if the number of points is other than 1 then you'll
% get ``n marks'' (where n is the number of points).
%
%
% \bracketedpoints
% \nobracketedpoints
%
% The default remains to put the points inside of parentheses.
% \bracketedpoints switches to points inside of square brackets and
% \boxedpoints switches to points in side of a box.  Both
% \nobracketedpoints and \noboxedpoints return to the default of
% points inside of parentheses no matter how many \boxedpoints and
% \bracketedpoints commands have been given in any order.
%
%
% \pointsinrightmargin
% \nopointsinrightmargin
%
% The default remains to put the points right after the question
% number, before the text of the question. \pointsinrightmargin
% switches to points in the right margin and \pointsinleftmargin
% switches to points in the left margin.  Both \nopointsinrightmargin
% and \nopointsinleftmargin return to the default of points right
% after the question number, before the text of the question, no
% matter how many \pointsinrightmargin and \pointsinleftmargin
% commands have been given in any order. 
%
% if \pointsinrightmargin is used, then the points are printed
% right justified in the right margin, with the right edge a distance
% of \rightpointsmargin from the right edge of the paper.
% The default value of \rightpointsmargin is 1 cm, but it can be set
% to any other length with the usual \setlength command
% (as in \setlength{\rightpointsmargin}{0.5cm}).
%
%
% subsubparts environment
% Numbered using lower case greek letters.
%
%
% choices environment, for multiple choice answers
%
%
% \qformat{Format line}
% 
% Format line must have some stretch (e.g., at least one \hfil or
% \dotfill or something similar).
% \thequestion inserts the question number,
% \thepoints inserts the number of points followed by pointname if
%   a number of points has been specified for this question, and it
%   inserts nothing at all if no points have been specified.
%
% \noqformat returns to the standard question number formatting.
%
%
%
% The standard options
%   a4paper
%   a5paper
%   b5paper
%   letterpaper
%   legalpaper
%   executivepaper
%   landscape
% now all work.
%
%
%
% Two new commands for use in \pointname, \marginpointname, and
% \qformat: 
%
% \points expands to either ``point'' or ``points'', depending on
% whether the number of points is 1 or other than 1.
%
% \marks expands to either ``mark'' or ``marks'', depending on
% whether the number of points is 1 or other than 1.
%
%
%--------------------------------------------------------------------
%--------------------------------------------------------------------
%
% The only change from version 2.0 to version 2.01 is that this
% documentclass (and its accompanying documentation) is now
% explicitly distributed under the LaTeX Project Public License.
%
%--------------------------------------------------------------------
%--------------------------------------------------------------------

\NeedsTeXFormat{LaTeX2e}

\ProvidesClass{exam}[\filedate\space Version \fileversion\space by
  Philip Hirschhorn]

\RequirePackage{ifthen}

\newif\if@printanswers
\@printanswersfalse
\DeclareOption{answers}{\@printanswerstrue}
\DeclareOption{noanswers}{\@printanswersfalse}

\DeclareOption*{%
  \PassOptionsToClass{\CurrentOption}{article}%
}
\ProcessOptions\relax
\LoadClass{article}




%                         *****************
%                         ** PAGE LAYOUT **
%                         *****************


% We set the parameters in terms of \paperwidth and \paperheight
% so that the options

% a4paper
% a5paper
% b5paper
% letterpaper
% legalpaper
% executivepaper
% landscape

% will all work:

\setlength{\textwidth}{\paperwidth}
\addtolength{\textwidth}{-2in}
\setlength{\oddsidemargin}{0pt}
\setlength{\evensidemargin}{0pt}

\setlength{\headheight}{15pt}
\setlength{\headsep}{15pt}
\setlength{\topmargin}{0in}
\addtolength{\topmargin}{-\headheight}
\addtolength{\topmargin}{-\headsep}
\setlength{\footskip}{29pt}
\setlength{\textheight}{\paperheight}
\addtolength{\textheight}{-2.2in}

\setlength{\marginparwidth}{.5in}
\setlength{\marginparsep}{5pt}





%--------------------------------------------------------------------

%                          ****************
%                          ** EXTRAWIDTH **
%                          ****************

\newlength\@extrawidth

% \@rightmargin is needed for \pointsinrightmargin and
% \pointsdroppedatright, so that we can right justify the points:
\newlength\@rightmargin
\setlength{\@rightmargin}{1in}

% We put the argument of \extrawidth into a length so that it will
% work correctly even if it's negative:

\def\extrawidth#1{%
  \@extrawidth=#1
  \advance \textwidth by \@extrawidth
  \divide\@extrawidth by 2
  \advance\oddsidemargin by -\@extrawidth
  \advance\evensidemargin by -\@extrawidth
  % Bug fix, 13 April 2004: 
  %\advance\@rightmargin by \@extrawidth
  \advance\@rightmargin by -\@extrawidth
}




%--------------------------------------------------------------------
%--------------------------------------------------------------------
%             Making room for large headers and footers

% The following are used to save the effect of any changes to 
% \topmargin and \textheight caused by \extraheadheight or
% \extrafootheight commands.  They hold the values currently in effect.
% We put them into lengths so that it will work correctly even if the
% argument is negative:

\newlength\@extrahead
\newlength\@extrafoot
\setlength{\@extrahead}{0in}
\setlength{\@extrafoot}{0in}

% The following are used to hold the requested values for extrahead and
% extrafoot, first page and all pages after the first, and then the
% similar things requested for the cover pages:
\newlength\run@exhd
\newlength\fp@exhd
\newlength\run@exft
\newlength\fp@exft
\newlength\covrun@exhd
\newlength\covfp@exhd
\newlength\covrun@exft
\newlength\covfp@exft

\setlength{\run@exhd}{0in}
\setlength{\fp@exhd}{0in}
\setlength{\run@exft}{0in}
\setlength{\fp@exft}{0in}
\setlength{\covrun@exhd}{0in}
\setlength{\covfp@exhd}{0in}
\setlength{\covrun@exft}{0in}
\setlength{\covfp@exft}{0in}


\newcommand*\adj@hdht@ftht{%
  \if@coverpages
    \ifnum\value{page}=1
      \@setheadheight{\covfp@exhd}%
      \@setfootheight{\covfp@exft}%
    \else
      \@setheadheight{\covrun@exhd}%
      \@setfootheight{\covrun@exft}%
    \fi
  \else
    \ifnum\value{page}=1
      \@setheadheight{\fp@exhd}%
      \@setfootheight{\fp@exft}%
    \else
      \@setheadheight{\run@exhd}%
      \@setfootheight{\run@exft}%
    \fi
  \fi
}


\newcommand*\extraheadheight{%
  \@ifnextchar[{\@xtrahd}{\@ytrahd}%
}

\def\@xtrahd[#1]#2{%
  \setlength{\fp@exhd}{#1}%
  \setlength{\run@exhd}{#2}%
  \adj@hdht@ftht
}

\def\@ytrahd#1{%
  \setlength{\fp@exhd}{#1}%
  \setlength{\run@exhd}{#1}%
  \adj@hdht@ftht
}

\newcommand*\extrafootheight{%
  \@ifnextchar[{\@xtraft}{\@ytraft}%
}

\def\@xtraft[#1]#2{%
  \setlength{\fp@exft}{#1}%
  \setlength{\run@exft}{#2}%
  \adj@hdht@ftht
}

\def\@ytraft#1{%
  \setlength{\fp@exft}{#1}%
  \setlength{\run@exft}{#1}%
  \adj@hdht@ftht
}


\newcommand*\coverextraheadheight{%
  \@ifnextchar[{\cov@xtrahd}{\cov@ytrahd}%
}

\def\cov@xtrahd[#1]#2{%
  \setlength{\covfp@exhd}{#1}%
  \setlength{\covrun@exhd}{#2}%
  \adj@hdht@ftht
}

\def\cov@ytrahd#1{%
  \setlength{\covfp@exhd}{#1}%
  \setlength{\covrun@exhd}{#1}%
  \adj@hdht@ftht
}

\newcommand*\coverextrafootheight{%
  \@ifnextchar[{\cov@xtraft}{\cov@ytraft}%
}

\def\cov@xtraft[#1]#2{%
  \setlength{\covfp@exft}{#1}%
  \setlength{\covrun@exft}{#2}%
  \adj@hdht@ftht
}

\def\cov@ytraft#1{%
  \setlength{\covfp@exft}{#1}%
  \setlength{\covrun@exft}{#1}%
  \adj@hdht@ftht
}

\def\@appendoutput#1{%
  \output=\expandafter{\the\output #1}%
}

\@appendoutput{\adj@hdht@ftht}

%--------------------------------------------------------------------
%                 \setheadheight and \setfootheight:

\def\@setheadheight#1{%
  \begingroup % Avoid trouble from using \@temp and \@spaces
    % Reset the effect of the most recent change:
    \global\advance\topmargin by -\@extrahead
    \global\advance\textheight by \@extrahead
    % Save the newly set value:
    \def\@temp{#1}
    \def\@spaces{ }
    \ifx\@temp\@empty
      \global\@extrahead=0in
    \else
      \ifx\@temp\@spaces
        \global\@extrahead=0in
      \else
        \global\@extrahead=#1
      \fi
    \fi
    % Set the new values:
    \global\advance\topmargin by \@extrahead
    \global\advance\textheight by -\@extrahead
    % Make it take effect RIGHT NOW!:
    % (The following stuff isn't necessary if \@setheadheight is
    % 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). 
    \global\@colht=\textheight
    \global\@colroom=\textheight
    \global\vsize=\textheight
    \global\pagegoal=\textheight
  \endgroup
}

\def\@setfootheight#1{%
  \begingroup % Avoid trouble from using \@temp and \@spaces
    % Reset the effect of the most recent change:
    \global\advance\textheight by \@extrafoot
    % Save the newly set value:
    \def\@temp{#1}
    \def\@spaces{ }
    \ifx\@temp\@empty
      \global\@extrafoot=0in
    \else
      \ifx\@temp\@spaces
        \global\@extrafoot=0in
      \else
        \global\@extrafoot=#1
      \fi
    \fi
    % Set the new values:
    \global\advance\textheight by -\@extrafoot
    % Make it take effect RIGHT NOW!:
    % (The following stuff isn't necessary if \@setfootheight is
    % 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). 
    \global\@colht=\textheight
    \global\@colroom=\textheight
    \global\vsize=\textheight
    \global\pagegoal=\textheight
  \endgroup
}




%---------------------------------------------------------------------
%
%                      *************************
%                      ** HEADERS AND FOOTERS **
%                      *************************
% 
% The pagestyles available are head, foot, headandfoot, and empty.
% \pagestyle{head} prints the head, and gives an empty foot.
% \pagestyle{foot} prints the foot, and gives an empty head.
% \pagestyle{headandfoot} prints both the head and the foot.
% \pagestyle{empty} gives an empty head and an empty foot.
% 

%                            Pagestyles:

\newcommand*\ps@head{%
  \@dohead
  \@nofoot
}

\newcommand*\ps@headandfoot{%
  \@dohead
  \@dofoot
}

\newcommand*\ps@foot{%
  \@nohead
  \@dofoot
}

% \ps@empty is already defined by article.cls, so we'll
% say \def instead of \newcommand*:
\def\ps@empty{%
  \@nohead
  \@nofoot
}

\newif\if@coverpages
\@coverpagesfalse

\newenvironment{coverpages}{%
    \ifnum \value{numquestions}>0
      \ClassError{exam}{%
        Coverpages cannot be used after questions have begun.\MessageBreak
      }{%
        All question, part, subpart, and subsubpart environments
        \MessageBreak
        must begin after the cover pages are complete.\MessageBreak
      }%
    \fi
    \@coverpagestrue
    \pagenumbering{roman}%
    \adj@hdht@ftht
  }{%
    \clearpage
    \pagenumbering{arabic}%
    \adj@hdht@ftht
}

\newcommand*\cover@question@error{%
  \ClassError{exam}{%
    No questions are allowed in the cover pages.\MessageBreak
  }{%
    All question, part, subpart, and subsubpart environments
    \MessageBreak
    must begin after the cover pages are complete.\MessageBreak
  }%
}



\newcommand*\@dohead{%
  \def\@oddhead{%
    \if@coverpages
      \ifnum\value{page}=1
        \cov@fullhead
      \else
        \covrun@fullhead
      \fi
    \else
      \ifnum\value{page}=1
        \@fullhead
      \else
        \run@fullhead
      \fi
    \fi
  }% @oddhead
  \let\@evenhead=\@oddhead
}

\newcommand*\@dofoot{%
  \def\@oddfoot{%
    \if@coverpages
      \ifnum\value{page}=1
        \cov@fullfoot
      \else
        \covrun@fullfoot
      \fi
    \else
      \ifnum\value{page}=1
        \@fullfoot
      \else
        \run@fullfoot
      \fi
    \fi
  }% @oddfoot
  \let\@evenfoot=\@oddfoot
}

\newcommand*\@nohead{%
  \def\@oddhead{}%
  \let\@evenhead=\@oddhead
}

\newcommand*\@nofoot{%
  \def\@oddfoot{}%
  \let\@evenfoot=\@oddfoot
}




%--------------------------------------------------------------------
%       \@fullhead, \run@fullhead, \@fullfoot, and \run@fullfoot:

\newcommand*\@fullhead{%
  \vbox to \headheight{%
    \vss
    \hbox to \textwidth{%
      \normalfont\rlap{\parbox[b]{\textwidth}{\raggedright\@lhead\strut}}%
        \hss\parbox[b]{\textwidth}{\centering\@chead\strut}\hss
        \llap{\parbox[b]{\textwidth}{\raggedleft\@rhead\strut}}%
    }% hbox
    \if@headrule
      \hrule
    \else
      % an invisible hrule, to keep positioning constant:
      \hrule width 0pt
    \fi
  }% vbox
}


\newcommand*\run@fullhead{%
  \vbox to \headheight{%
    \vss
    \hbox to \textwidth{%
      \normalfont\rlap{\parbox[b]{\textwidth}{\raggedright\run@lhead\strut}}%
        \hss\parbox[b]{\textwidth}{\centering\run@chead\strut}\hss
        \llap{\parbox[b]{\textwidth}{\raggedleft\run@rhead\strut}}%
    }% hbox
    \ifrun@headrule
      \hrule
    \else
      % an invisible hrule, to keep positioning constant:
      \hrule width 0pt
    \fi
  }% vbox
}



% We arrange it so that the very top of first line of text in the
% foot is at a fixed position on the page, whether or not there's
% a footrule:

\newcommand*\@fullfoot{%
  \vbox to 0pt{%
    \if@footrule
      \hrule
    \else
      % an invisible hrule, to keep positioning constant:
      \hrule width 0pt
    \fi
    \vskip 3pt
    \hbox to \textwidth{%
      \normalfont\rlap{\parbox[t]{\textwidth}{\raggedright\@lfoot}}%
        \hss\parbox[t]{\textwidth}{\centering\@cfoot}\hss
        \llap{\parbox[t]{\textwidth}{\raggedleft\@rfoot}}%
    }% hbox
    \vss
  }% vbox
}


\newcommand*\run@fullfoot{%
  \vbox to 0pt{%
    \ifrun@footrule
      \hrule
    \else
      % an invisible hrule, to keep positioning constant:
      \hrule width 0pt
    \fi
    \vskip 3pt
    \hbox to \textwidth{%
      \normalfont\rlap{\parbox[t]{\textwidth}{\raggedright\run@lfoot}}%
        \hss\parbox[t]{\textwidth}{\centering\run@cfoot}\hss
        \llap{\parbox[t]{\textwidth}{\raggedleft\run@rfoot}}%
    }% hbox
    \vss
  }% vbox
}

%--------------------------------------------------------------------
%       \cov@fullhead, \covrun@fullhead, \cov@fullfoot, and
%       \covrun@fullfoot: 

\newcommand*\cov@fullhead{%
  \vbox to \headheight{%
    \vss
    \hbox to \textwidth{%
      \normalfont\rlap{\parbox[b]{\textwidth}{\raggedright\cov@lhead\strut}}%
        \hss\parbox[b]{\textwidth}{\centering\cov@chead\strut}\hss
        \llap{\parbox[b]{\textwidth}{\raggedleft\cov@rhead\strut}}%
    }% hbox
    \ifcov@headrule
      \hrule
    \else
      % an invisible hrule, to keep positioning constant:
      \hrule width 0pt
    \fi
  }% vbox
}


\newcommand*\covrun@fullhead{%
  \vbox to \headheight{%
    \vss
    \hbox to \textwidth{%
      \normalfont\rlap{\parbox[b]{\textwidth}{\raggedright\covrun@lhead\strut}}%
        \hss\parbox[b]{\textwidth}{\centering\covrun@chead\strut}\hss
        \llap{\parbox[b]{\textwidth}{\raggedleft\covrun@rhead\strut}}%
    }% hbox
    \ifcovrun@headrule
      \hrule
    \else
      % an invisible hrule, to keep positioning constant:
      \hrule width 0pt
    \fi
  }% vbox
}



% We arrange it so that the very top of first line of text in the
% foot is at a fixed position on the page, whether or not there's
% a footrule:

\newcommand*\cov@fullfoot{%
  \vbox to 0pt{%
    \ifcov@footrule
      \hrule
    \else
      % an invisible hrule, to keep positioning constant:
      \hrule width 0pt
    \fi
    \vskip 3pt
    \hbox to \textwidth{%
      \normalfont\rlap{\parbox[t]{\textwidth}{\raggedright\cov@lfoot}}%
        \hss\parbox[t]{\textwidth}{\centering\cov@cfoot}\hss
        \llap{\parbox[t]{\textwidth}{\raggedleft\cov@rfoot}}%
    }% hbox
    \vss
  }% vbox
}


\newcommand*\covrun@fullfoot{%
  \vbox to 0pt{%
    \ifcovrun@footrule
      \hrule
    \else
      % an invisible hrule, to keep positioning constant:
      \hrule width 0pt
    \fi
    \vskip 3pt
    \hbox to \textwidth{%
      \normalfont\rlap{\parbox[t]{\textwidth}{\raggedright\covrun@lfoot}}%
        \hss\parbox[t]{\textwidth}{\centering\covrun@cfoot}\hss
        \llap{\parbox[t]{\textwidth}{\raggedleft\covrun@rfoot}}%
    }% hbox
    \vss
  }% vbox
}


%--------------------------------------------------------------------
%--------------------------------------------------------------------
%
%            ********************************************
%            ** COMMANDS TO DEFINE HEADERS AND FOOTERS **
%            ********************************************
%
% \lhead[#1]{#2} sets the first page left head to #1, and the
%   running left head to #2
% 
% \lhead{#1} sets both the first page left head and the running
%   left head to #1
% 
% \chead, \rhead, \lfoot, \cfoot, and \rfoot work similarly.
% 
% 
% \@lhead is the left head for Page 1
% \run@lhead is the running left head
% (i.e., for all pages other than the first)
% 
% \@chead is the center head for Page 1
% \run@chead is the running center head
% (i.e., for all pages other than the first)
% 
% etc.
% 
% Alternative commands are:
% \firstpageheader{LEFT}{CENTER}{RIGHT}
% \runningheader{LEFT}{CENTER}{RIGHT}
% or
% \header{LEFT}{CENTER}{RIGHT}
% which is equivalent to the two commands
%          \firstpageheader{LEFT}{CENTER}{RIGHT}
%          \runningheader{LEFT}{CENTER}{RIGHT}
% 
% Alternative commands are:
% \firstpagefooter{LEFT}{CENTER}{RIGHT}
% \runningfoother{LEFT}{CENTER}{RIGHT}
% or
% \footer{LEFT}{CENTER}{RIGHT}
% which is equivalent to the two commands
%          \firstpagefooter{LEFT}{CENTER}{RIGHT}
%          \runningfoother{LEFT}{CENTER}{RIGHT}

\def\firstpageheader#1#2#3{%
  \def\@lhead{#1}%
  \def\@chead{#2}%
  \def\@rhead{#3}%
}

\def\runningheader#1#2#3{%
  \def\run@lhead{#1}%
  \def\run@chead{#2}%
  \def\run@rhead{#3}%
}

\def\header#1#2#3{%
  \firstpageheader{#1}{#2}{#3}%
  \runningheader{#1}{#2}{#3}%
}


\def\firstpagefooter#1#2#3{%
  \def\@lfoot{#1}%
  \def\@cfoot{#2}%
  \def\@rfoot{#3}%
}

\def\runningfooter#1#2#3{%
  \def\run@lfoot{#1}%
  \def\run@cfoot{#2}%
  \def\run@rfoot{#3}%
}

\def\footer#1#2#3{%
  \firstpagefooter{#1}{#2}{#3}%
  \runningfooter{#1}{#2}{#3}%
}



\def\lhead{\@ifnextchar[{\@xlhead}{\@ylhead}}
\def\@xlhead[#1]#2{\def\@lhead{#1}\def\run@lhead{#2}}
\def\@ylhead#1{\def\run@lhead{#1}\def\@lhead{#1}}

\def\chead{\@ifnextchar[{\@xchead}{\@ychead}}
\def\@xchead[#1]#2{\def\@chead{#1}\def\run@chead{#2}}
\def\@ychead#1{\def\run@chead{#1}\def\@chead{#1}}

\def\rhead{\@ifnextchar[{\@xrhead}{\@yrhead}}
\def\@xrhead[#1]#2{\def\@rhead{#1}\def\run@rhead{#2}}
\def\@yrhead#1{\def\run@rhead{#1}\def\@rhead{#1}}

\def\lfoot{\@ifnextchar[{\@xlfoot}{\@ylfoot}}
\def\@xlfoot[#1]#2{\def\@lfoot{#1}\def\run@lfoot{#2}}
\def\@ylfoot#1{\def\run@lfoot{#1}\def\@lfoot{#1}}

\def\cfoot{\@ifnextchar[{\@xcfoot}{\@ycfoot}}
\def\@xcfoot[#1]#2{\def\@cfoot{#1}\def\run@cfoot{#2}}
\def\@ycfoot#1{\def\run@cfoot{#1}\def\@cfoot{#1}}

\def\rfoot{\@ifnextchar[{\@xrfoot}{\@yrfoot}}
\def\@xrfoot[#1]#2{\def\@rfoot{#1}\def\run@rfoot{#2}}
\def\@yrfoot#1{\def\run@rfoot{#1}\def\@rfoot{#1}}


%                    Initialize head and foot:



\pagestyle{headandfoot}

\lhead{}
\chead{}
\rhead{}
\lfoot{}
\cfoot[]{Page \thepage}
\rfoot{}

%--------------------------------------------------------------------
%                    Coverpage headers and footers
%
% \coverlhead[#1]{#2} sets the first cover page left head to #1, and the
%   running cover left head to #2
% 
% \coverlhead{#1} sets both the first cover page left head and the running
%   cover left head to #1
% 
% \coverchead, \coverrhead, \coverlfoot, \covercfoot, and \coverrfoot
% work similarly.
% 
% 
% \cov@lhead is the left head for Page 1
% \covrun@lhead is the running left head
% (i.e., for all pages other than the first)
% 
% \cov@chead is the center head for Page 1
% \covrun@chead is the running center head
% (i.e., for all pages other than the first)
% 
% etc.
% 
% Alternative commands are:
% \coverfirstpageheader{LEFT}{CENTER}{RIGHT}
% \coverrunningheader{LEFT}{CENTER}{RIGHT}
% or
% \coverheader{LEFT}{CENTER}{RIGHT}
% which is equivalent to the two commands
%          \coverfirstpageheader{LEFT}{CENTER}{RIGHT}
%          \coverrunningheader{LEFT}{CENTER}{RIGHT}
% 
% Alternative commands are:
% \coverfirstpagefooter{LEFT}{CENTER}{RIGHT}
% \coverrunningfoother{LEFT}{CENTER}{RIGHT}
% or
% \coverfooter{LEFT}{CENTER}{RIGHT}
% which is equivalent to the two commands
%          \coverfirstpagefooter{LEFT}{CENTER}{RIGHT}
%          \coverrunningfoother{LEFT}{CENTER}{RIGHT}

\def\coverfirstpageheader#1#2#3{%
  \def\cov@lhead{#1}%
  \def\cov@chead{#2}%
  \def\cov@rhead{#3}%
}

\def\coverrunningheader#1#2#3{%
  \def\covrun@lhead{#1}%
  \def\covrun@chead{#2}%
  \def\covrun@rhead{#3}%
}

\def\coverheader#1#2#3{%
  \coverfirstpageheader{#1}{#2}{#3}%
  \coverrunningheader{#1}{#2}{#3}%
}


\def\coverfirstpagefooter#1#2#3{%
  \def\cov@lfoot{#1}%
  \def\cov@cfoot{#2}%
  \def\cov@rfoot{#3}%
}

\def\coverrunningfooter#1#2#3{%
  \def\covrun@lfoot{#1}%
  \def\covrun@cfoot{#2}%
  \def\covrun@rfoot{#3}%
}

\def\coverfooter#1#2#3{%
  \coverfirstpagefooter{#1}{#2}{#3}%
  \coverrunningfooter{#1}{#2}{#3}%
}



\def\coverlhead{\@ifnextchar[{\cov@xlhead}{\cov@ylhead}}
\def\cov@xlhead[#1]#2{\def\cov@lhead{#1}\def\covrun@lhead{#2}}
\def\cov@ylhead#1{\def\covrun@lhead{#1}\def\cov@lhead{#1}}

\def\coverchead{\@ifnextchar[{\cov@xchead}{\cov@ychead}}
\def\cov@xchead[#1]#2{\def\cov@chead{#1}\def\covrun@chead{#2}}
\def\cov@ychead#1{\def\covrun@chead{#1}\def\cov@chead{#1}}

\def\coverrhead{\@ifnextchar[{\cov@xrhead}{\cov@yrhead}}
\def\cov@xrhead[#1]#2{\def\cov@rhead{#1}\def\covrun@rhead{#2}}
\def\cov@yrhead#1{\def\covrun@rhead{#1}\def\cov@rhead{#1}}

\def\coverlfoot{\@ifnextchar[{\cov@xlfoot}{\cov@ylfoot}}
\def\cov@xlfoot[#1]#2{\def\cov@lfoot{#1}\def\covrun@lfoot{#2}}
\def\cov@ylfoot#1{\def\covrun@lfoot{#1}\def\cov@lfoot{#1}}

\def\covercfoot{\@ifnextchar[{\cov@xcfoot}{\cov@ycfoot}}
\def\cov@xcfoot[#1]#2{\def\cov@cfoot{#1}\def\covrun@cfoot{#2}}
\def\cov@ycfoot#1{\def\covrun@cfoot{#1}\def\cov@cfoot{#1}}

\def\coverrfoot{\@ifnextchar[{\cov@xrfoot}{\cov@yrfoot}}
\def\cov@xrfoot[#1]#2{\def\cov@rfoot{#1}\def\covrun@rfoot{#2}}
\def\cov@yrfoot#1{\def\covrun@rfoot{#1}\def\cov@rfoot{#1}}


%                 Initialize coverpage head and foot:


\coverlhead{}
\coverchead{}
\coverrhead{}
\coverlfoot{}
\covercfoot{}
\coverrfoot{}




%--------------------------------------------------------------------
%--------------------------------------------------------------------

%                      Headrules and footrules:

\newif\if@headrule
\newif\ifrun@headrule

\def\firstpageheadrule{\@headruletrue}
\def\nofirstpageheadrule{\@headrulefalse}

\def\runningheadrule{\run@headruletrue}
\def\norunningheadrule{\run@headrulefalse}

\def\headrule{\@headruletrue\run@headruletrue}
\def\noheadrule{\@headrulefalse\run@headrulefalse}



\newif\if@footrule
\newif\ifrun@footrule

\def\firstpagefootrule{\@footruletrue}
\def\nofirstpagefootrule{\@footrulefalse}

\def\runningfootrule{\run@footruletrue}
\def\norunningfootrule{\run@footrulefalse}

\def\footrule{\@footruletrue\run@footruletrue}
\def\nofootrule{\@footrulefalse\run@footrulefalse}



%                             Initialize:

\noheadrule
\nofootrule


%                 Cover page headrules and footrules:

\newif\ifcov@headrule
\newif\ifcovrun@headrule

\def\coverfirstpageheadrule{\cov@headruletrue}
\def\nocoverfirstpageheadrule{\cov@headrulefalse}

\def\coverrunningheadrule{\covrun@headruletrue}
\def\nocoverrunningheadrule{\covrun@headrulefalse}

\def\coverheadrule{\cov@headruletrue\covrun@headruletrue}
\def\nocoverheadrule{\cov@headrulefalse\covrun@headrulefalse}



\newif\ifcov@footrule
\newif\ifcovrun@footrule

\def\coverfirstpagefootrule{\cov@footruletrue}
\def\nocoverfirstpagefootrule{\cov@footrulefalse}

\def\coverrunningfootrule{\covrun@footruletrue}
\def\nocoverrunningfootrule{\covrun@footrulefalse}

\def\coverfootrule{\cov@footruletrue\covrun@footruletrue}
\def\nocoverfootrule{\cov@footrulefalse\covrun@footrulefalse}



%                             Initialize:

\nocoverheadrule
\nocoverfootrule



%--------------------------------------------------------------------
%--------------------------------------------------------------------

%                \numpages, \iflastpage, and \oddeven
%     Also: \numpoints, \numquestions, \numparts, and \numsubparts
%                    Also also: \pointsofquestion

% Make the number of pages available as the macro \numpages,
% the number of points as \numpoints,
% the number of questions as \numquestions,
% the number of parts as \numparts, and
% the number of subparts as \numsubparts
%\def\numpages{\pageref{@lastpage}}
%\def\numpoints{\pageref{@numpoints}}
%\def\numquestions{\pageref{@numquestions}}
%\def\numparts{\pageref{@numparts}}
%\def\numsubparts{\pageref{@numsubparts}}
%\def\numsubsubparts{\pageref{@numsubsubparts}}

% This was previously done with \pageref commands.  When I eliminated
% all \label, \ref, and \pageref commands in order to make this
% compatible with hyperref.sty, this stuff was created:

% \gdef commands for exam@lastpage, exam@numpoints, exam@numquestions,
% exam@numparts, exam@numsubparts and exam@numsubsubparts are written to
% the .aux file via \AtEndDocument.

% \gdef commands for pointsofq@i, pointsofq@ii, etc. are written to the
% .aux file as each question is completed (see the definition of the
% questions environment).

% \gdef commands for pointsonpage@i, pointsonpage@ii, etc. are written
% to the .aux file as we encounter points defined for a later page, and
% for the last such page with AtEndDocument.

\def\numpages{\@ifundefined{exam@lastpage}%
  {\mbox{\normalfont\bf ??}}%
  \exam@lastpage
}

\def\numpoints{\@ifundefined{exam@numpoints}%
  {\mbox{\normalfont\bf ??}}%
  \exam@numpoints
}

\def\numquestions{\@ifundefined{exam@numquestions}%
  {\mbox{\normalfont\bf ??}}%
  \exam@numquestions
}

\def\numparts{\@ifundefined{exam@numparts}%
  {\mbox{\normalfont\bf ??}}%
  \exam@numparts
}

\def\numsubparts{\@ifundefined{exam@numsubparts}%
  {\mbox{\normalfont\bf ??}}%
  \exam@numsubparts
}

\def\numsubsubparts{\@ifundefined{exam@numsubsubparts}%
  {\mbox{\normalfont\bf ??}}%
  \exam@numsubsubparts
}

\def\pointsofquestion#1{\@ifundefined{pointsofq@\romannumeral #1}%
  {\mbox{\normalfont\bf ??}}%
  {\csname pointsofq@\romannumeral #1\endcsname}%
}

\def\pointsonpage#1{\@ifundefined{pointsonpage@\romannumeral #1}%
  {\mbox{\normalfont\bf ??}}%
  {\csname pointsonpage@\romannumeral #1\endcsname}%
}


\newif\if@pointschanged
\@pointschangedfalse



%%%\let\@realenddocument=\enddocument
%%%\def\enddocument{\clearpage
%%%   \if@filesw 
%%%     {\advance\c@page-1 \immediate\write\@mainaux
%%%       {\string\newlabel{@lastpage}{{}{\arabic{page}}}}%
%%%     }
%%%   \fi
%%%   \@realenddocument
%%%}


\AtEndDocument{%
  \clearpage
  \if@filesw
    \advance\c@page-1
    \immediate\write\@mainaux
      {\string\gdef\string\exam@lastpage{\arabic{page}}}%
    \advance\c@page+1 % In case some other package looks at \c@page
    \immediate\write\@mainaux
        {\string\gdef\string\exam@numpoints{\prtaux@hlfcntr{numpoints}}}%
    % See if this has changed from the last run of LaTeX:
    \@ifundefined{exam@numpoints}%
      {\global\@pointschangedtrue}%
      {%
      % OK; it's defined.  See if it's changed:
      \begingroup
        \set@hlfcntr{tmp@hlfcntr}{\exam@numpoints}%
        \edef\othpt@check{\prtaux@hlfcntr{tmp@hlfcntr}}%
        \edef\pt@check{\prtaux@hlfcntr{numpoints}}%
        \ifx \pt@check \othpt@check
          % Do nothing
        \else
          \global\@pointschangedtrue
        \fi
      \endgroup
      }%
    \immediate\write\@mainaux
      {\string\gdef\string\exam@numquestions{\thenumquestions}}%
    \immediate\write\@mainaux
      {\string\gdef\string\exam@numparts{\thenumparts}}%
    \immediate\write\@mainaux
      {\string\gdef\string\exam@numsubparts{\thenumsubparts}}%
    \immediate\write\@mainaux
      {\string\gdef\string\exam@numsubsubparts{\thenumsubsubparts}}%
    \ifnum \thepageof@pagepoints > 0\relax
      \immediate\write\@mainaux
          {\string\gdef\string\pointsonpage@\romannumeral
                          \csname c@pageof@pagepoints\endcsname
             {\prtaux@hlfcntr{@pagepoints}}}%
      % See if this has changed from the last run of LaTeX:
      \@ifundefined{pointsonpage@\romannumeral
                          \csname c@pageof@pagepoints\endcsname}%
        {\global\@pointschangedtrue}%
        {%
        % OK; it's defined.  See if it's changed:
        \begingroup
          \set@hlfcntr{tmp@hlfcntr}{\csname pointsonpage@\romannumeral 
                    \csname c@pageof@pagepoints\endcsname\endcsname}%
          \edef\othpt@check{\prtaux@hlfcntr{tmp@hlfcntr}}%
          \edef\pt@check{\prtaux@hlfcntr{@pagepoints}}%
          \ifx \pt@check \othpt@check
            % Do nothing
          \else
            \global\@pointschangedtrue
          \fi
        \endgroup
        }%
    \fi
    \immediate\write\@mainaux
      {\string\gdef\string\lastpage@withpoints{\page@withpoints}}%
    % See if this has changed from the last run of LaTeX:
    \@ifundefined{lastpage@withpoints}%
      {\global\@pointschangedtrue}%
      {%
      % OK; it's defined.  See if it's changed:
      \begingroup
        \edef\othpt@check{\page@withpoints}%
        \edef\pt@check{\lastpage@withpoints}%
        \ifx \pt@check \othpt@check
          % Do nothing
        \else
          \global\@pointschangedtrue
        \fi
      \endgroup
      }%
  \fi
  % Echo numbers of questions, parts, and subparts:
  \typeout{This exam contains \thenumquestions\space questions
    with \thenumparts\space parts, \thenumsubparts\space subparts,
    and \thenumsubsubparts\space subsubparts.}
  % If counting points, echo total points:
  \if@printtotalpoints
    \begingroup
      \def\typ@expnd{%
        \thenumpoints
        \ifnumpoints@half
          \space and a half%
        \fi
      }
      \typeout{This exam has a total of \typ@expnd\space points.}
    \endgroup
  \fi
  \if@pointschanged
    \ClassWarningNoLine{exam}{Point totals have changed.
               Rerun to get point totals right}%
  \fi
}


% We define \iflastpage so that it can safely be used
% in headers and footers:
\def\iflastpage#1#2{%
  \@ifundefined{exam@lastpage}{\def\@@lastpage{-1}}%
          {\edef\@@lastpage{\exam@lastpage}}%
  \ifnum\value{page}=\@@lastpage
    #1%
  \else
    #2%
  \fi
}


% The macro \oddeven takes two arguments.  If the page number is odd,
% then you get the first argument; otherwise, you get the second
% argument.
\def\oddeven#1#2{%
  \ifodd\value{page}%
    #1
  \else
    #2
  \fi
}



%--------------------------------------------------------------------
%--------------------------------------------------------------------
%                 \ifcontinuation, \ContinuedQuestion,
%                \ifincomplete, and \IncompleteQuestion

% The commands \ifcontinuation, \ContinuedQuestion, \ifincomplete, and
% \IncompleteQuestion assume that there is only one questions
% environment in the entire document.  (Actually, \ContinuedQuestion
% should work even if there are multiple questions environments, but
% none of the other three will work in general.)



% \PgInfo@write, \PgInfo and \PgInfo@get are our replacements
% for \label, \newlabel, and \pageref.  (We're avoiding using
% \label, \newlabel, and \pageref so that we will be compatible
% with hyperref.sty, which redefines those commands.)

% We use \PgInfo, \PgInfo@write, and \PgInfo@get to know on which page
% each question, part, subpart, and subsubpart appears.

% We use \PgInfo@write to write \PgInfo commands to the .aux file.  The
% \PgInfo command takes two arguments: A question (or part, or subpart,
% or subsubpart) label, and the number of the page on which it appears.

% The label for a question is of the form `question@2' (if it's question
% 2).

% The label for a part is of the form `part@2@1' (if it's part a of
% question 2).

% The label for a subpart is of the form `subpart@2@1@3' (if it's
% subpart iii of part a of question 2).

% The label for a subsubpart is of the form `subsubpart@2@1@3@4' (if
% it's subsubpart $\delta$ of subpart iii of part a of question 2).

% 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
% important to check that the macro Pg@label is defined before giving the
% command \PgInfo@get{label}.



% The token list to a \write command isn't expanded until
% it's shipped out.  Since the argument to PgInfo@write
% generally contains macros, we want to expand those macros
% now, rather than waiting until this is shipped out, at which
% point the macros may have different values.  Thus, we use
% \edef to force expansion of the argument, and we put
% a \noexpand in front of \thepage so that the \thepage
% will not be expanded now.  (This may not get shipped out
% until a later page, and so we want the \thepage to be expanded
% only when it's shipped out.)
% We use the \begingroup \endgroup pair so that our use
% of \reserved@a won't affect its use anywhere else.
\def\PgInfo@write#1{%
  \begingroup
    \edef\reserved@a{\write\@mainaux
      {\string\PgInfo{#1}{\noexpand\thepage}}}%
    \reserved@a
  \endgroup
}

%\PgInfo commands are written to the .aux file by the \PgInfo@write
%command; that's the only place that \PgInfo commands appear.
\def\PgInfo#1#2{\expandafter\gdef\csname Pg@#1\endcsname{#2}}

% Note: PgInfo@get assumes that the control sequence being
% constructed is already defined; you have to make sure of this
% *before* calling \Pginfo@get
\def\PgInfo@get#1{\csname Pg@#1\endcsname}

% \set@counter@to@pageof takes two arguments: The first is the name
% of a counter, and the second (expands to) the label of a question,
% part, subpart, or subsubpart.  If that label exists, then we set
% the counter equal to the page on which the question (or part, etc.)
% appears.  If that label doesn't exist, we set the counter equal
% to -1.  (No labels exist on the first run of LaTeX on the file,
% and if a new question (or part, etc.) was created by editing the
% file, then the label will not exist until the second run of LaTeX
% after that.
\def\set@counter@to@pageof#1#2{%
  \@ifundefined{Pg@#2}%
  {\setcounter{#1}{-1}}%
  {\setcounter{#1}{\csname Pg@#2\endcsname}}%
}


%--------------------------------------------------------------------

% \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, or subsubpart begins, or (3)
% The current page is later than a page with the \nomorequestions
% command.  Otherwise, it expands 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,
  % 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
    #2%
  \else
    % Note: The ``\relax'' at the end of the following \ifnum
    % serves an entirely different purpose from the one at the
    % end of the above \expandafter\ifx.  That one (above)
    % is one of the things being compared, whereas the
    % one we're about to use is just to clearly mark the
    % end of the second number being compared by the \ifnum
    % (since it's conceivable that the ``#2'' would begin
    % with a digit).
    \ifnum \thepage < \csname Pg@question@1\endcsname\relax
      % We're before the page with question 1:
      #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.)
      \expandafter\ifx\csname Contin@\thepage\endcsname\ref@relax
        #2%
      \else
        % See if we're after a \nomorequestions command:
        \@ifundefined{Pg@@endquestions}%
        {#1}%
        {\ifnum \thepage > \PgInfo@get{@endquestions}\relax
          % We're after a \nomorequestions:
          #2
         \else
           % We actually are incomplete:
           #1
         \fi
        }%
      \fi
    \fi 
  \fi
}

\def\nomorequestions{
  \PgInfo@write{@endquestions}%
}



%--------------------------------------------------------------------
% \ContinuedQuestion is for use in headers and footers, where we can
% assume that \thepage is the number of the page on which we'll
% actually appear.

% \ContinuedQuestion expands to the number of the question that
% continues onto this page, or to -1 if this page begins with a new
% question.

% ACTUALLY: \ContinuedQuestion expands to a positive number if either
% (1) this page doesn't contain the beginning of any question, part,
% subpart, or subsubpart, or (2) this page has a part, subpart, or
% subsubpart that appears before any question.  That means that if the
% current page actually begins with space for a continuation of the
% previous question (but doesn't begin any part, subpart, or subsubpart
% of that question) and then has a question, then we'll be asserting
% that this page begins with a new question, but the actual top of the
% page will begin with some blank space that's intended for the previous
% question.

% \ContinuedQuestion works by examining the value of the macro
% Contin@\thepage.  If this page starts with a question (i.e., if no
% question continues onto this page), then the macro Contin@\thepage
% will be defined, and will expand to `\relax' (and so an \ifx between
% \csname Contin@\thepage\endcsname and \ref@relax will be true).

% If Contin@\thepage is undefined, then when it is used in an \ifx
% command it will be temporarily set equal to \relax (which is
% *different* from being a macro that expands to \relax); in this case,
% there is no question, part, subpart, or subsubpart that begins on this
% page, and so \ContinuedQuestion will be set equal to the last question
% that was begun on a page before this one.

% The last possibility is that this page begins with either a part,
% subpart, or subsubpart.  In this case, Contin@\thepage is defined, and
% it expands to the number of the question that is continues onto this
% page.


\def\ref@relax{\relax}

\def\ContinuedQuestion{%
  \expandafter\ifx\csname Contin@\thepage\endcsname\relax
    % We get here if there's no question, part, subpart, or
    % subsubpart on this page, and so Contin@\thepage has
    % never been defined at all.  In that case, this page
    % continues whichever question was last begun on or 
    % before this page.
    \find@latestques
    \thelatest@ques
  \else
    \expandafter\ifx\csname Contin@\thepage\endcsname\ref@relax
      % We get here if this page begins with a new question,
      % which is why Contin@\thepage has been defined to be
      % a macro that expands to \relax.
      % ACTUALLY: We get here if this page has a question that
      % appears before any part, subpart, or subsubpart.  That
      % means that if the current page actually begins with space
      % for a continuation of the previous question but doesn't begin
      % any part, subpart, or subsubpart of that question, then
      % we'll be asserting that this page begins with a new question,
      % but the actual top of the page will begin with some space
      % that's intended for the previous question.
      -1\relax
    \else
      % We get here if we didn't get anywhere above.  This happens
      % if Contin@\thepage has been defined to be a macro that expands
      % to something other than \relax, in which case it has been
      % defined to be a macro that expands to the number of the
      % question that continues onto this page.
      \csname Contin@\thepage\endcsname
    \fi
  \fi
}

%--------------------------------------------------------------------
% \find@latestques is for use in headers and footers, where we can
% assume that \thepage actually equals the page on which we'll appear.
% We find the last question that was started on or before the current
% page.

\newcounter{latest@ques}

\newcommand\find@latestques{%
  % \find@latestques is for use in headers and footers.
  % \find@latestques will set the counter latest@ques
  % to the number of the last question
  % that was begun on the exam from page 1 through the current
  % page.  This may well be the value of the question counter,
  % but it may be less than that if the page following this one
  % begins a new question and that question beginning was
  % typeset before the present page was shipped out.
  % Note: This macro is called both by \ContinuedQuestion and by
  % \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
    % Oops; probably because we're before the first question
    % Just set latest@ques to -1:
    \setcounter{latest@ques}{-1}%
  \else
    % If question latest@ques actually begins on this page (rather
    % than on the next page, but early enough on the next page
    % that the counter was advanced before we ran off into the
    % output routine to output the page and set the header and 
    % footer), then that's the correct question number.
    \expandafter\ifx\csname Pg@question@\arabic{question}\endcsname\relax
      % We don't know what page that question is on;
      % this must be an early run, before the aux file
      % is helpful.  Just set it equal to -1 and wait until the next
      % run to get it right.
      \setcounter{latest@ques}{-1}%
    \else
      % We now know that \PgInfo@get can tell us the page number
      % of \arabic{question} and of all earlier questions.
      % Set latest@ques equal to the current question number, and
      % 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}}%
      \decr@latest@ques
    \fi
  \fi
}

\def\decr@latest@ques{%
  % If we get here, then we've already checked that the reference
  % Pg@question@\thelatest@ques is defined at least for a value of
  % \thelatest@ques greater than or equal to it's present value,
  % so we assume it's defined for all lesser values as well:
  \ifnum \thepage < \PgInfo@get{question@\thelatest@ques}\relax
    % Nope; latest@ques starts on a later page
    % Decrement latest@ques and see if that one's right:
    \addtocounter{latest@ques}{-1}%
    \ifnum \thelatest@ques < 1\relax
      \setcounter{latest@ques}{-1}%
      \let\next@dlq=\relax
    \else
      \let\next@dlq=\decr@latest@ques
    \fi
  \else
    % latest@ques starts on this page or earlier, so
    % that's the correct question number!  Exit:
    \let\next@dlq=\relax
  \fi
  \next@dlq
}
         


%--------------------------------------------------------------------
%--------------------------------------------------------------------
%--------------------------------------------------------------------
\newcounter{ques@end}
\def\find@quesend{%
  % We find the last question started on or before the current page
  % and then find the page containing the last part (or subpart, or
  % subsubpart) of that question, and set the counter ques@end to that
  % page number.
  % Set latest@ques equal to the correct question number:
  \find@latestques
  \ifnum \value{latest@ques} < 0\relax
    % This must be an early run of LaTeX, before we have
    % \PgInfo commands in the .aux file:
    \setcounter{ques@end}{-1}%
  \else
    % See if this question has any parts.  (It has one or more parts
    % if and only if it has a part number 1.)
    \@ifundefined{Pg@part@\thelatest@ques @1}%
      {%
        % Nope; no parts.
        \setcounter{ques@end}{\PgInfo@get{question@\thelatest@ques}}%
      }%
      {\find@part}%
  \fi
}

\newcounter{last@part}
\def\find@part{%
  % We now know that this question has at least one part.
  % We'll find its highest numbered part by setting last@part
  % equal to 2 and then calling \find@lastpart to recursively
  % test whether that part number exists and, if so, incrementing
  % last@part to test for a higher numbered one:
  \setcounter{last@part}{2}%
  \find@lastpart
  % Now: See if this part has any subparts.  (It has one or more
  % subparts if and only if it has a subpart numbered 1.)
  \@ifundefined{Pg@subpart@\thelatest@ques @\thelast@part @1}%
    {%
      % Nope; no subparts.
      \setcounter{ques@end}{\PgInfo@get{part@\thelatest@ques
                                          @\thelast@part}}%
    }%
    {\find@subpart}%
}

\def\find@lastpart{%
  % We check whether this question has a part numbered last@part
  % and recursively increment last@part to find the highest
  % numbered value for which the part exists:
  \@ifundefined{Pg@part@\thelatest@ques @\thelast@part}%
    {\addtocounter{last@part}{-1}%
      \let\nextfind@lastpart=\relax
    }%
    {\addtocounter{last@part}{1}%
      \let\nextfind@lastpart=\find@lastpart
    }%
  \nextfind@lastpart
}

\newcounter{last@subpart}
\def\find@subpart{%
  % We now know that this part has at least one subpart.
  % We'll find its highest numbered subpart by setting last@subpart
  % equal to 2 and then calling \find@lastsubpart to recursively
  % test whether that subpart number exists and, if so, incrementing
  % last@subpart to test for a higher numbered one:
  \setcounter{last@subpart}{2}%
  \find@lastsubpart
  % Now: See if this subpart has any subsubparts.  (It has one or more
  % subsubparts if and only if it has a subsubpart numbered 1.)
  \@ifundefined{Pg@subsubpart@\thelatest@ques 
                         @\thelast@part @\thelast@subpart @1}%
    {%
      % Nope; no subsubparts
      \setcounter{ques@end}{\PgInfo@get{subpart@\thelatest@ques
                                  @\thelast@part @\thelast@subpart}}%
    }%
    {\find@subsubpart}%
}

\def\find@lastsubpart{%
  % We check whether this part has a subpart numbered last@subpart
  % and recursively increment last@subpart to find the highest
  % numbered value for which the subpart exists:
  \@ifundefined{Pg@subpart@\thelatest@ques 
                         @\thelast@part @\thelast@subpart}%
    {\addtocounter{last@subpart}{-1}%
      \let\nextfind@lastsubpart=\relax
    }%
    {\addtocounter{last@subpart}{1}%
      \let\nextfind@lastsubpart=\find@lastsubpart
    }%
  \nextfind@lastsubpart
}

\newcounter{last@subsubpart}
\def\find@subsubpart{%
  % We now know that this subpart has at least one subsubpart.
  % We'll find its highest numbered subsubpart by setting last@subsubpart
  % equal to 2 and then calling \find@lastsubsubpart to recursively
  % test whether that subsubpart number exists and, if so, incrementing
  % last@subsubpart to test for a higher numbered one:
  \setcounter{last@subsubpart}{2}%
  \find@lastsubsubpart
  \setcounter{ques@end}{\PgInfo@get{subsubpart@\thelatest@ques
               @\thelast@part @\thelast@subpart @\thelast@subsubpart}}%
}

\def\find@lastsubsubpart{%
  % We check whether this subpart has a subsubpart numbered last@subsubpart
  % and recursively increment last@subsubpart to find the highest
  % numbered value for which the subsubpart exists:
  \@ifundefined{Pg@subsubpart@\thelatest@ques 
              @\thelast@part @\thelast@subpart @\thelast@subsubpart}%
    {\addtocounter{last@subsubpart}{-1}%
      \let\nextfind@lastsubsubpart=\relax
    }%
    {\addtocounter{last@subsubpart}{1}%
      \let\nextfind@lastsubsubpart=\find@lastsubsubpart
    }%
  \nextfind@lastsubsubpart
}


%--------------------------------------------------------------------
\newcounter{incmp@ques}

\def\IncompleteQuestion{%
  \Find@Incmp@ques
  \theincmp@ques
}

\def\Find@Incmp@ques{%
  \iflastpage{\setcounter{incmp@ques}{-1}}{\chk@incomp}%
}
\newcounter{next@ques}
\newcounter{nextq@page}
\def\chk@incomp{%
  \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
  \fi
}


\def\ifincomplete#1#2{%
  \def\incomp@first{#1}%
  \def\incomp@second{#2}%
  \Find@Incmp@ques
  \ifnum \theincmp@ques < 0\relax
    \incomp@second
  \else
        \@ifundefined{Pg@@endquestions}%
        {\incomp@first}%
        {\ifnum \thepage < \PgInfo@get{@endquestions}%
           \incomp@first
         \else
           \incomp@second
         \fi
        }%
  \fi
}




%---------------------------------------------------------------------
%
%                    ***************************
%                    ** QUESTION ENVIRONMENTS **
%                    ***************************
%
%
%

% We define the command \part only inside of a parts environment, so
% that we don't interfere with the meaning of the standard article
% documentclass command \part if that is used inside of a questions
% environment.  The commands \question, \subpart, and \subsubpart are
% defined everywhere inside of a questions environment.  If the user
% accidentally gives a \subpart command outside of a subparts
% environment, then an error will be created.


%--------------------------------------------------------------------
% These are the commands for dealing with hlfcntr's, i.e., the things
% used to count points.
%
% A point value is a nonnegative integer with an optional half integer.
% A hlfcntr consists of a regular counter together with an \if: If the
% regular counter is called ``counter'', then the \if is called
% ``\ifcounter@half''; it's set true by ``\counter@halftrue'' and set
% false by ``\counter@halffalse''.
%
% The commands:
%
% \set@hlfcntr{countername}{value}
% \copy@hlfcntr{tocounter}{fromcounter}
% \addto@hlfcntr{countername}{value}
% \add@hlfcntrtohlfcntr
% \ifhlfcntr@pos{countername}
% \prtaux@hlfcntr{countername}
%
% ``value'' can be either a (nonnegative) integer, an integer followed by
% ``\half'', or just plain ``\half''.  (Actually, ``value'' can be empty
% (although the braces must be present), in which case it's interpreted
% as ``0''.)
%
% Examples of valid values:
%   0
%   0\half
%   1
%   1\half
%   2
%   2\half
% etc.

% Note on using ``\global'': LaTeX's \setcounter and \addtocounter
% commands are already \global (i.e., you don't have to say
% ``\global''), but \somethingtrue and \somethingfalse (used to set
% \ifsomething) aren't.  Thus, we need to say ``\global'' when setting
% these things.

% A scratch hlfcntr:
\newcounter{tmp@hlfcntr}
\newif\iftmp@hlfcntr@half

\newcommand*\horiz@half{$\frac{1}{2}$}
\newcommand*\slanted@half{%
  $\raise0.6ex\hbox{$\scriptstyle 1$}\kern -.2em/\kern -.2em
     \raise-0.5ex\hbox{$\scriptstyle 2$}$%
}
\newcommand*\useslantedhalf{\let\half\slanted@half}
\newcommand*\usehorizontalhalf{\let\half\horiz@half}
\newcommand*\half{\slanted@half}


\newcommand*\set@hlfcntr[2]{%
  \begingroup
    \expandafter\global\csname #1@halffalse\endcsname
    % If there as a `\half' present, it will be executed
    % right after the assignment of the digit part of #2
    % to the counter #1.
    \def\half{%
      \expandafter\global\csname #1@halftrue\endcsname
    }%
    % We insert a `0' in case there are no digits present:
    \setcounter{#1}{0#2}\relax
  \endgroup
}

\newcommand*\copy@hlfcntr[2]{%
  % We set #1 to the value of #2
  \setcounter{#1}{\value{#2}}%
  \csname if#2@half\endcsname
    \expandafter\global\csname #1@halftrue\endcsname
  \else
    \expandafter\global\csname #1@halffalse\endcsname
  \fi
}

\newcommand*\addto@hlfcntr[2]{%
  % We add the valueandhalf #2 to hlfcntr #1
  \begingroup
    \def\half{\add@half{#1}}%
    % We insert a `0' in case there are no digits present:
    \addtocounter{#1}{0#2}\relax
  \endgroup
}

\newcommand*\add@hlfcntrtohlfcntr[2]{%
  % We add the hlfcntr #2 to the hlfcntr #1
  \addtocounter{#1}{\value{#2}}%
  \csname if#2@half\endcsname
    \add@half{#1}%
  \fi
}

\newcommand*\add@half[1]{%
  % We add one half to hlfcntr #1:
  \csname if#1@half\endcsname
    \addtocounter{#1}{1}%
    \expandafter\global\csname #1@halffalse\endcsname
  \else
    \expandafter\global\csname #1@halftrue\endcsname
  \fi
}

\newcounter{ifpos@cntr}
\def\ifhlfcntr@pos#1{%
  % The argument must be a hlfcntr (which, of course,
  % can never be negative); we'll be true if and only if
  % that halfcntr is positive:
  \setcounter{ifpos@cntr}{\value{#1}}%
  \csname if#1@half\endcsname
    \addtocounter{ifpos@cntr}{1}%
  \fi
  \ifnum \value{ifpos@cntr} > 0
}

% \prtaux@hlfcntr is used inside the argument of a \write command for
% writing to the .aux file:
\newcommand*\prtaux@hlfcntr[1]{%
  % We don't want a \relax after the 0 in the following
  % line, because it would sometimes appear in the aux file:
  \ifnum \value{#1} = 0 
    % We have to make the following a macro, because if we
    % don't do this part, the \fi will cause confusion, since
    % there's no \if visible until the \csname is expanded:
    \prtaux@halforzero{#1}%
  \else
    \arabic{#1}%
    % We have to make the following a macro, because if we
    % don't do this part, the \fi will cause confusion, since
    % there's no \if visible until the \csname is expanded:
    \prtaux@halforblank{#1}%
  \fi
}
\newcommand*\prtaux@halforzero[1]{%
  \csname if#1@half\endcsname
    \string\half
  \else
    0%
  \fi
}
\newcommand*\prtaux@halforblank[1]{%
  \csname if#1@half\endcsname
    \string\half
  \fi
}
%--------------------------------------------------------------------




% We use the counter name `partno' for the parts environment so that
% we will not interfere with the counter `part' used by the article
% document class.

\newcounter{question}
\newcounter{partno}
\newcounter{subpart}
\newcounter{subsubpart}
\newcounter{choice}
\newcounter{numpoints}
\newif\ifnumpoints@half
\set@hlfcntr{numpoints}{0}
\newcounter{pointsof@thisquestion}
\newif\ifpointsof@thisquestion@half
\set@hlfcntr{pointsof@thisquestion}{0}
\newcounter{numquestions}
\newcounter{numparts}
\newcounter{numsubparts}
\newcounter{numsubsubparts}
\newcounter{Curr@Page}

% @pagepoints accumulates the points on a single page:
\newcounter{@pagepoints}
\newif\if@pagepoints@half
%\setcounter{@pagepoints}{0}
\set@hlfcntr{@pagepoints}{0}
\newcounter{pageof@pagepoints}
\setcounter{pageof@pagepoints}{0}

% latest@points is a holding area for points until we know
% whether they'll land on the same page as the points
% currently counted in @pagepoints:
\newcounter{latest@points}
\newif\iflatest@points@half
\set@hlfcntr{latest@points}{0}

% Whenever we meet a new page on which points are defined, we'll
% redefine \page@withpoints to expand to that page.  At the end of the
% document, it will hold the last page that has points, and we'll write
% a \gdef\lastpage@withpoints command to the .aux file.
% We initialize \page@withpoints here:
\def\page@withpoints{0}%

% \pageinfo@commands is used by each question, part, subpart, and
% subsubpart to insert into everypar the \PgInfo@write command to put
% its page number inot the .aux file, the \PgInfo@get command to read
% the page number into the counter Curr@Page, and to test and set
% \Contin@\theCurr@Page.  \temp@toks is used by part, subpart, and
% subsubpart to append all that to \pageinfo@commands, rather than
% deleting whatever may have been put into \pageinfo@commands by the
% current question and/or part and/or subpart.
\newtoks\pageinfo@commands
\newtoks\temp@toks

% \pagepoint@commands holds the commands to manage the counting of the
% number of points defined on each page.
\newtoks\pagepoint@commands

% \point@toks holds the commands to print the points at the proper
% location on the page (except that it's not used by the \qformat
% option).
\newtoks\point@toks

% We'll use \greeknum to number subsubparts
\def\greeknum#1{\expandafter\lc@greek\csname c@#1\endcsname}
\def\lc@greek#1{%
  \ifcase #1\or $\alpha$\or $\beta$\or $\gamma$\or $\delta$\or
  $\epsilon$\or $\zeta$\or $\eta$\or $\theta$\or $\iota$\or
  $\kappa$\or $\lambda$\or $\mu$\or $\nu$\or $\xi$\or o\or $\pi$\or
  $\rho$\or $\sigma$\or $\tau$\or $\upsilon$\or $\phi$\or $\chi$\or
  $\psi$\or $\omega$\else \@ctrerr
  \fi
}%


% The following macros are a variation on a trick from Victor
% Eijkhout's ``TeX by Topic'', page 142:
% Both \prepend@toklist and \append@toklist take two arguments,
% both of which should be token lists.
% \prepend@toklist prepends #2 to #1
% \append@toklist appends #2 to #1

\def\prepend@toklist#1#2{%
  \edef\do@it{\noexpand#1={\the#2\the#1}}%
  \do@it
}%

\def\append@toklist#1#2{%
  \edef\do@it{\noexpand#1={\the#1\the#2}}%
  \do@it
}%


% The command \qformat is provided for the user who wants to
% design a nonstandard question line.  If this command is used,
% then the usual line containing the question numbers will be
% replaced by the line specified by the \qformat command.
% Within the argument of the \qformat command:
% \thequestion will be replaced by the question number, and
% \thepoints will be replaced by ``\@points \@pointname'' if the
% number of points has been specified for this question, and otherwise
% it inserts nothing at all.  (The conditional @placepoints is used to
% determine if the number of points is nonzero.)
% The argument to the \qformat command *must* contain some
% stretch, i.e., at least one \hfil or \dotfill or ...
\newif\if@qformat
\@qformatfalse

\def\qformat#1{%
  \global\@qformattrue
  \gdef\@questionformat{#1}%
}

\newcommand\noqformat{%
  \global\@qformatfalse
}

\newcommand\thepoints{%
  \if@placepoints
    \@points \@pointname
  \fi
}

% We define the \subpart and \subsubpart commands when we enter a
% questions environment (rather than waiting until we enter a subparts
% of subsubparts environment) so that we can signal an error if a
% \subpart or \subsubpart command appears outside of the corresponding
% environment.  (We don't do this for the \part command so that the user
% can use the standard sectioning \part command outside of a parts
% environment.)

\newenvironment{questions}{%
  % \@queslevel is used for two purposes:
  % (1) We check that every \question, \part, \subpart, and 
  % \subsubpart command appears inside the appropriate environment,
  % and generate an error if one appears in the wrong place.
  % (2) If a \qformat is being used and if \@queslevel tells us
  % that we're currently processing a question, then we set
  % \global \point@toks={} to avoid setting the points for a 
  % question other than via the qformat command.
  \def\@queslevel{question}%
  \def\question{%
    \if@coverpages
      \cover@question@error
    \fi
    \@checkqueslevel{question}%
    \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
    % number of the question that was just completed.)
    \if@filesw
      \ifnum \arabic{question} > 0\relax
        \immediate\write\@mainaux
          {\string\gdef\string\pointsofq@
            \romannumeral \csname c@question\endcsname
              {\prtaux@hlfcntr{pointsof@thisquestion}}}%
        % See if this has changed from the last run of LaTeX:
        \@ifundefined{pointsofq@\romannumeral
                            \csname c@question\endcsname}%
          {\global\@pointschangedtrue}%
          {%
          % OK; it's defined.  See if it's changed:
          \begingroup
            \set@hlfcntr{tmp@hlfcntr}{\csname pointsofq@\romannumeral 
                         \csname c@question\endcsname\endcsname}%
            \edef\othpt@check{\prtaux@hlfcntr{tmp@hlfcntr}}%
            \edef\pt@check{\prtaux@hlfcntr{pointsof@thisquestion}}%
            \ifx \pt@check \othpt@check
              % Do nothing
            \else
              \global\@pointschangedtrue
            \fi
          \endgroup
          }%
      \fi
    \fi
    \set@hlfcntr{pointsof@thisquestion}{0}%
    % If there was a question with points immediately preceding
    % this question (i.e., there were no parts in the previous
    % question), then @placepoints will still be true, and we need to
    % cancel it.  (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 \part command.
    \global \@placepointsfalse
    % point@toks will normally be empty at this point, but it might be
    % nonempty if there were points somewhere in the previous question
    % that never made it onto the page because we never entered
    % horizontal mode (perhaps because the user was weird and let the
    % text of a question (or part, etc.) consist entirely of an
    % enumerate environment, or description environment, or etc.).
    \global \point@toks={}%
    % 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. 
    \pageinfo@commands={%
      \edef\@queslabel{question@\arabic{question}}%
      \PgInfo@write{\@queslabel}%
      \set@counter@to@pageof{Curr@Page}{\@queslabel}%
      \expandafter\ifx\csname Contin@\theCurr@Page\endcsname\relax
        % We're the first \question, \part, \subpart, or \subsubpart
        % on this page:
        \global\expandafter\edef
               \csname Contin@\theCurr@Page\endcsname{\relax}%
      \fi
      \the\pagepoint@commands
      \global \pageinfo@commands={}%
    }% pageinfo@commands
    \ifhmode
      % Remove any skips at the end of the previous paragraph
      % that might cause a blank line, and then end that paragraph:
      \unskip\unskip \par
    \fi
    \@doitem
  }% question
  \def\subpart{%
    \if@coverpages
      \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}%
      \set@counter@to@pageof{Curr@Page}{\@subpartlabel}%
      \expandafter\ifx\csname Contin@\theCurr@Page\endcsname\relax
        % We're the first \question, \part, \subpart, or \subsubpart
        % on this page:
        \global\expandafter\edef\csname
                       Contin@\theCurr@Page\endcsname{\arabic{question}}%
      \fi
      \the\pagepoint@commands
      \global \pageinfo@commands={}%
    }% temp@toks
    \append@toklist \pageinfo@commands \temp@toks
    \ifhmode
      % Remove any skips at the end of the previous paragraph
      % that might cause a blank line, and then end that paragraph:
      \unskip\unskip \par
    \fi
    \@doitem
  }% subpart
  \def\subsubpart{%
    \if@coverpages
      \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}%
      \set@counter@to@pageof{Curr@Page}{\@subsubpartlabel}%
      \expandafter\ifx\csname Contin@\theCurr@Page\endcsname\relax
        % We're the first \question, \part, \subpart, or \subsubpart
        % on this page:
        \global\expandafter\edef\csname
                       Contin@\theCurr@Page\endcsname{\arabic{question}}%
      \fi
      \the\pagepoint@commands
      \global \pageinfo@commands={}%
    }% temp@toks
    \append@toklist \pageinfo@commands \temp@toks
    \ifhmode
      % Remove any skips at the end of the previous paragraph
      % that might cause a blank line, and then end that paragraph:
      \unskip\unskip \par
    \fi
    \@doitem
  }% subsubpart
  \list{\question@number}%
    {\usecounter{question}%
    % We use the default definition of \makelabel
    % so as not to interfere with \qformat commands.
    % \def\makelabel##1{\hss\llap{##1}}%
    \settowidth{\leftmargin}{10.\hskip\labelsep}%
    \labelwidth\leftmargin\advance\labelwidth-\labelsep
    \partopsep=0pt
    }%
  }%
  {%
    \endlist
    % Write the number of points of the final question
    % to the .aux file:
    \if@filesw
      \ifnum \arabic{question} > 0\relax
        \immediate\write\@mainaux
          {\string\gdef\string\pointsofq@\romannumeral
                                \csname c@question\endcsname
            {\prtaux@hlfcntr{pointsof@thisquestion}}}%
        % See if this has changed from the last run of LaTeX:
        \@ifundefined{pointsofq@\romannumeral
                            \csname c@question\endcsname}%
          {\global\@pointschangedtrue}%
          {%
          % OK; it's defined.  See if it's changed:
          \begingroup
            \set@hlfcntr{tmp@hlfcntr}{\csname pointsofq@\romannumeral 
                         \csname c@question\endcsname\endcsname}%
            \edef\othpt@check{\prtaux@hlfcntr{tmp@hlfcntr}}%
            \edef\pt@check{\prtaux@hlfcntr{pointsof@thisquestion}}%
            \ifx \pt@check \othpt@check
              % Do nothing
            \else
              \global\@pointschangedtrue
            \fi
          \endgroup
          }%
      \fi
    \fi
  }
  
% \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
  \else
    \questionlabel
  \fi
}
\newcommand\questionlabel{\thequestion.}
     
% We want the \part command to be defined *only* inside of a parts
% environment, so that the user can use the standard sectioning \part
% command inside of a questions environment (as long as it's outside of
% a parts environment).

\newenvironment{parts}{%
  \def\@queslevel{part}%
  % If the question numbers are being inserted via a \qformat,
  % and if a question is beginning with a parts environmnt, then
  % we need to enter horizonal mode to the the qformat printed
  % on the page, rather than saving up the question label (and
  % 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
    \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{%
    \if@coverpages
      \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}%
      \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={}%
    }%
    \append@toklist \pageinfo@commands \temp@toks
    \ifhmode
      % Remove any skips at the end of the previous paragraph
      % that might cause a blank line, and then end that paragraph:
      \unskip\unskip \par
    \fi
    \@doitem
  }% part
  \list{\partlabel}%
    {%
    \usecounter{partno}\def\makelabel##1{\hss\llap{##1}}%
    \settowidth{\leftmargin}{(m)\hskip\labelsep}%
    \labelwidth\leftmargin\advance\labelwidth-\labelsep
    \topsep=0pt
    \partopsep=0pt
    }%
  }% newenvironment{parts}
  {\endlist}
\newcommand\partlabel{(\thepartno)}
\def\thepartno{\alph{partno}}

\newenvironment{subparts}{%
  \def\@queslevel{subpart}%
  \list{\subpartlabel}%
    {%
    \usecounter{subpart}\def\makelabel##1{\hss\llap{##1}}%
    \settowidth{\leftmargin}{vii.\hskip\labelsep}%
    \labelwidth\leftmargin\advance\labelwidth-\labelsep
    \topsep=0pt
    \partopsep=0pt
    }%
  }%
  {\endlist}
\newcommand\subpartlabel{\thesubpart.}
\def\thesubpart{\roman{subpart}}

\newenvironment{subsubparts}{%
  \def\@queslevel{subsubpart}%
  \list{\subsubpartlabel}%
    {%
    \usecounter{subsubpart}\def\makelabel##1{\hss\llap{##1}}%
    \settowidth{\leftmargin}{($\psi$)\hskip\labelsep}%
    \labelwidth\leftmargin\advance\labelwidth-\labelsep
    \topsep=0pt
    \partopsep=0pt
    }%
  }%
  {\endlist}
\newcommand\subsubpartlabel{\thesubsubpart)}
\def\thesubsubpart{\greeknum{subsubpart}}


\pagepoint@commands={%
  \ifhlfcntr@pos{latest@points}%
    % We're putting a question (or part, etc.)
    % with points onto this page: 
    \ifnum \theCurr@Page > \thepageof@pagepoints\relax
      % These points go on a later page than
      % the points currently counted in @pagepoints:
      \ifnum \thepageof@pagepoints = 0\relax
        % Do nothing...
      \else
        \immediate\write\@mainaux
          {\string\gdef\string\pointsonpage@
           \romannumeral \csname c@pageof@pagepoints\endcsname
             {\prtaux@hlfcntr{@pagepoints}}}%
        % See if this has changed from the last run of LaTeX:
        \@ifundefined{pointsonpage@\romannumeral
                            \csname c@pageof@pagepoints\endcsname}%
          {\global\@pointschangedtrue}%
          {%
          % OK; it's defined.  See if it's changed:
          \begingroup
            \set@hlfcntr{tmp@hlfcntr}{\csname pointsonpage@\romannumeral 
                      \csname c@pageof@pagepoints\endcsname\endcsname}%
            \edef\othpt@check{\prtaux@hlfcntr{tmp@hlfcntr}}%
            \edef\pt@check{\prtaux@hlfcntr{@pagepoints}}%
            \ifx \pt@check \othpt@check
              % Do nothing
            \else
              \global\@pointschangedtrue
            \fi
          \endgroup
          }%
      \fi
      % The following is a macro because \theCurr@Page and
      % \thepageof@pagepoints might differ by more than 1:
      \increment@pageof@pagepoints
    \else
      % These points go on the same page as the points
      % currently counted in @pagepoints:
      \add@hlfcntrtohlfcntr{@pagepoints}{latest@points}%
      \set@hlfcntr{latest@points}{0}%
    \fi
  \fi
}
\def\increment@pageof@pagepoints{%
  \addtocounter{pageof@pagepoints}{1}%
  \ifnum \theCurr@Page > \thepageof@pagepoints\relax
    \immediate\write\@mainaux
        {\string\gdef\string\pointsonpage@
         \romannumeral \csname c@pageof@pagepoints\endcsname{0}}%
    % See if this has changed from the last run of LaTeX:
    \@ifundefined{pointsonpage@\romannumeral
                        \csname c@pageof@pagepoints\endcsname}
      {\global\@pointschangedtrue}%
      {%
      % OK; it's defined.  See if it's changed:
      \begingroup
        \set@hlfcntr{tmp@hlfcntr}{\csname pointsonpage@\romannumeral 
                  \csname c@pageof@pagepoints\endcsname\endcsname}%
        \edef\othpt@check{\prtaux@hlfcntr{tmp@hlfcntr}}%
        \def\pt@check{0}%
        \ifx \pt@check \othpt@check
          % Do nothing
        \else
          \global\@pointschangedtrue
        \fi
      \endgroup
      }%
    \let\next@incr@pageof = \increment@pageof@pagepoints
  \else
    \copy@hlfcntr{@pagepoints}{latest@points}%
    \set@hlfcntr{latest@points}{0}%
    % \page@withpoints will be used to find the last
    % page that has points, which will be written to
    % the .aux file vis \AtEndDocument:
    \global\edef\page@withpoints{\thepageof@pagepoints}%
    \let\next@incr@pageof = \relax
  \fi
  \next@incr@pageof
}







\def\@checkqueslevel#1{%
  \begingroup
    \def\@temp{#1}%
    \ifx\@temp\@queslevel
      % Everything's fine; do nothing.
    \else
      \ClassError{exam}{%
        I found a #1 where I expected to find a
        \@queslevel\MessageBreak
      }{%
        Both #1 and \@queslevel \space can be used only inside the
        correct \MessageBreak \space \space
        environment and outside of any smaller environment
        \MessageBreak
      }%
    \fi
  \endgroup
}

\def\@doitem{\@ifnextchar[{\@readpoints}%
                          {\item@points@pageinfo}%
}

\def\@readpoints[#1]{%
% We use \def for \@points instead of \edef because we don't want
% \half (if present) to be expanded yet, so that the command \points
% can figure out how to deal with it:
  \def\@points{#1}%
  \global \@placepointstrue
  \if@addpoints
    \addto@hlfcntr{numpoints}{\@points}%
    \addto@hlfcntr{pointsof@thisquestion}{\@points}%
    % latest@points is a holding area for points to be
    % added to @pagepoints after we check whether they're
    % on the same page as the points currently counted
    % by @pagepoints:
    \addto@hlfcntr{latest@points}{\@points}%
  \fi
  \item@points@pageinfo
}



% do@int@lbl is the command used to create a label for every question,
% part, subpart, and subsubpart.  We make no use of these labels, but we
% put them there so 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.

\newcounter{lbl@cntr}
\def\do@int@lbl{%
  \addtocounter{lbl@cntr}{1}%
  % Looking at latex.ltx reveals that the argument to \label is
  % expanded, so we don't really need the \expandafter's in the
  % following, but I haven't seen any statement anywhere in
  % documentation about it being expanded, so we'll be paranoid and
  % protect against future changes in latex.ltx by using
  % \expandafter's: 
  \expandafter\label\expandafter{\thelbl@cntr @@exam@lbl}%
}


% Bug fix, 5 April 2004: \item@points@pageinfo
% Appending \point@toks and \pageinfo@commands to \everypar:
% Instead of appending the contents of \point@toks and
% \pageinfo@commands to \everypar using \append@toklist,
% we instead want to append only the two tokens
%   \the\point@toks
% and the two tokens
%   \the\pageinfo@commands
% to \everypar.  We need to do this because if a questions environment
% immediately follows a \section command, then @nobreak will be true,
% and so the \if@nobreak inside of \everypar will *not* execute the
% \everypar={} that we had been counting on to keep the points from
% being inserted a second time in the second paragraph of a question.
% Since we've put the command \global \point@toks={} inside of 
% \point@toks and the command \pageinfo@commands={} inside of
% \pageinfo@commands, when the contents of \point@toks and of
% \pageinfo@commands are executed when we enter horizontal mode and
% \everypar is dumped in, the contents of \point@toks and
% \pageinfo@commands will be made empty, and so if
% the second paragraph also get \the\point@toks and
% \the\pageinfo@commands, it won't matter.

\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
  % command ``\sbox\@tempboxa{\makelabel{#1}}%''), expanding the
  % argument of \qformat as it does so.  Thus, @placepoints will be
  % true when the argument of \qformat is expanded, and so if the
  % 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
  \if@placepoints
    % \setup@point@toks defines \point@block to be a macro that prints
    % the points with the correct choice of parentheses, brackets, or
    % box, and \@pointname or \@marginpointname and puts commands into
    % \point@toks to place \point@block at the correct spot.  It
    % doesn't append anything to \everypar (we do that in this macro,
    % below). 
    \if@pointsdropped
      % Do nothing!
    \else
      \setup@point@toks
    \fi
    \global \@placepointsfalse
  \fi
  % We *don't* use \append@toklist; see Bug fix note above
  % 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.
  \edef\append@everypar{\noexpand\everypar={\the\everypar
                        \noexpand\the \noexpand\pageinfo@commands
                        \noexpand\the \noexpand\point@toks}}%
  \append@everypar
  \do@int@lbl
}







% Initialize \@points:
% (Now that I think of it, this seems totally unnecessary,
% but we're not deleting it because we're chicken.)
\def\@points{0}


\def\setup@point@toks{%
% We begin by defining \point@block so that it expands to the properly
% formatted points (including either \pointname or \marginpointname,
% enclosed in either parentheses, brackets, or a box).  We then set
% the token list \point@toks equal to the sequence of commands needed
% to put \point@block at the correct location, followed by the tokens
% ``\global \point@toks={}''.  The \question, \part, \subpart, or 
% \subsubpart command then adds the two tokens ``\the\point@toks'' to
% \everypar.
%
% Note: It is not the *contents* of \point@toks that is added to
% \everypar; just the two tokens ``\the\point@toks''.  This difference
% is the bug fix of 2 April 2004, described above (the bug was that in
% earlier versions, we used to append the contents).
%
% The result of this is that whenever we finally enter horizontal mode
% (because we finally encountered the text of a question, part,
% subpart, or subsubpart) the contents of \point@toks will be dumped
% into horizontal mode and executed, and so the points will be placed
% and the token list \point@toks will be set to empty.  Thus, in the
% occasional circumstances in which \everypar is *not* set to empty
% after being added to the first paragraph (which occurs when a
% questions environment immediately follows a \section command), and
% so \everypar will still contain ``\the\point@toks'' when it
% encounters a possible second paragraph of the first question, the
% tokens ``\the\point@toks'' will insert an *empty* token list, which
% will do no harm.
%
%
% \point@block consists of \point@string surrounded by either
% parentheses, brackets, or an fbox.
%
% \point@string is either \@points\@pointname or
% \@points\@marginpointname.
  \setup@point@block
  \if@pointsinleftmargin
    \def\point@string{\@points\@marginpointname}%
    \point@toks={%
          \llap{\point@block 
                \hskip\@totalleftmargin
                \hskip\marginpointssep
          }%
          \global \point@toks={}%
    }%
  \else
    \if@pointsinrightmargin
      \def\point@string{\@points\@marginpointname}%
      \point@toks={%
            \rlap{\hskip-\@totalleftmargin
                  \hskip\textwidth
                  \hskip\@rightmargin
                  \hskip-\rightpointsmargin
                  \llap{\point@block}%
            }%
            \global \point@toks={}%
      }%
    \else
      % The points just go after the question number:
      \def\point@string{\@points\@pointname}%
      \point@toks={%
            \point@block
            \enspace
            \global \point@toks={}%
      }%
    \fi
  \fi
}% setup@point@toks


\def\setup@point@block{%
  \if@boxedpoints
    \def\point@block{\fbox{\point@string}}%
  \else
    \if@bracketedpoints
      \def\point@block{[\point@string]}%
    \else
      % plain old parentheses:
      \def\point@block{(\point@string)}%
    \fi
  \fi
}

\def\droppoints{%
  \def\point@string{\@points\@marginpointname}%
  \setup@point@block
  \leavevmode\unskip\nobreak\hfill
  \rlap{\hskip\rightmargin  % Defined by the list environment
        \hskip\@rightmargin % Defined by exam.cls
        \hskip-\rightpointsmargin
        \llap{\point@block}%
  }% rlap
  \par
}

% The following is the default definition.
% It will be redefined if the user givea a \totalformat command.
\def\setup@total@block{%
  \def\total@block{%
    Total for Question \thequestion: \totalpoints\@marginpointname
  }%
}

\def\totalformat#1{%
  \def\setup@total@block{\def\total@block{#1}}%
}
% The following is for use in the argument to a \totalformat command:
\def\totalpoints{\pointsofquestion{\arabic{question}}}

\def\droptotalpoints{%
  \setup@total@block
  \leavevmode\unskip\nobreak\hfill
  \rlap{\hskip\rightmargin  % Defined by the list environment
        \hskip\@rightmargin % Defined by exam.cls
        \hskip-\rightpointsmargin
        \llap{\total@block}%
  }% rlap
  \par
}


% @placepoints is set true when we encounter a question (or part, etc.)
% that has points.  It is set to false (1) when we set \point@toks equal
% to the sequence of commands required to put the properly formatted
% points onto the page (this happens only if @qformat is false or if
% @qformat is true but we're not doing a question), or (2) by a
% \question or \part command (since if we're doing a question and
% @qformat is true, we need to leave @placepoints true so that the
% \thepoints command can tell if it should expand to points or to
% nothing, and encountering a \question or \part command tells us that
% we no longer have to deal with a possible \thepoints, since we won't
% be expanding a qformat).
\newif\if@placepoints
\@placepointsfalse


% \marginpointssep will be used if the user says
% \pointsinleftmargin.  It will be the distance from whatever encloses
% the points (parentheses, brackets, or a box) to the left margin:
\newlength\marginpointssep
\setlength{\marginpointssep}{5pt}

% \rightpointsmargin will be used if the user says \pointsinrightmargin.
% It will be the distance from whatever encloses the point (parentheses,
% brackets, or a box) to the right edge of the paper:
\newlength\rightpointsmargin
\setlength{\rightpointsmargin}{1cm}


\newif\if@pointsdropped
\newif\if@pointsinleftmargin
\newif\if@pointsinrightmargin
\def\pointsinleftmargin{\global\@pointsinleftmargintrue 
                    \global\@pointsinrightmarginfalse
                    \global\@pointsdroppedfalse}
\def\pointsinrightmargin{\global\@pointsinrightmargintrue
                         \global\@pointsinleftmarginfalse
                         \global\@pointsdroppedfalse}
\def\nopointsinmargin{\global\@pointsinleftmarginfalse
                      \global\@pointsinrightmarginfalse
                      \global\@pointsdroppedfalse}
\def\pointsdroppedatright{\global\@pointsdroppedtrue
                          \global\@pointsinleftmarginfalse
                          \global\@pointsinrightmarginfalse}
\let\pointsinmargin\pointsinleftmargin
\let\nopointsinrightmargin\nopointsinmargin
\let\nopointsinleftmargin\nopointsinmargin


\nopointsinmargin


% Will the points be displayed inside parentheses (the default), or
% will they be boxed or bracketed:
\newif\if@boxedpoints
\def\boxedpoints{\global\@boxedpointstrue \global\@bracketedpointsfalse}
\def\noboxedpoints{\global\@boxedpointsfalse \global\@bracketedpointsfalse}
\@boxedpointsfalse

\newif\if@bracketedpoints
\def\bracketedpoints{\global\@bracketedpointstrue \global\@boxedpointsfalse}
\def\nobracketedpoints{\global\@bracketedpointsfalse \global\@boxedpointsfalse}
\@bracketedpointsfalse



\def\pointname#1{\gdef\@pointname{#1}}
% Initialize to leave a space, and then the word `points':
%%\pointname{ points}
% The following improvement was contributed by 
% Mate Wierdl <mw@wierdlmpc.msci.memphis.edu> 
% If the number of points is ``1'', then the default value of
% \pointname will print `` point'' instead of `` points'' (and this
% version of the command doesn't generate an error message if the
% points entry is something other than a number):
% Note the space before the \points in the following; it's
% intentional!)
\pointname{ \points}

\newcommand\point@sing{point}
\newcommand\point@plur{points}
\newcommand\pointpoints[2]{%
  \renewcommand\point@sing{#1}%
  \renewcommand\point@plur{#2}%
}



% The command \points:
% We use \ifthenelse and \equal so that if the user types something
% other than a legit point value, there still won't be any error
% messages.  We rig it so that if the point value looks like it's
% intended to be One or one or ONE, or some strange way of attempting
% one half, then it will expand to the singular value.  Alas, this is
% only useful for English, but I'm hoping few or no users will try doing
% this anyway.

% 0 points, one half point, 1 point, 1 and a half points, etc.:
\newcommand\points{%
  \begingroup
    \let\half=\relax
    \edef\pt@string{\@points}%
    \ifthenelse{\equal{\pt@string}{1} \or \equal{\pt@string}{\half}}
          {\point@sing}{\point@plur}%
  \endgroup
}
%\newcommand\points{%
%  \begingroup
%    \let\half=\relax
%    \edef\pt@string{\@points}%
%    \ifthenelse{\equal{\pt@string}{1} \or \equal{\pt@string}{\half} \or
%      \equal{\pt@string}{0\half} \or \equal{\pt@string}{0 \half}
%      \equal{\pt@string}{one} \or \equal{\pt@string}{One} \or
%      \equal{\pt@string}{ONE}}
%        {\point@sing}{\point@plur}%
%  \endgroup
%}

%\newcommand\points{\ifthenelse{\equal{\@points}{1}}{\point@sing}{\point@plur}}
% If we used the following line instead, then you'd get an error
% message if the point value contained something other than a valid
% integer:
%\pointname{ \ifthenelse{\@points = 1}{point}{points}}

% We used to define a command named \marks that works like \points,
% except that it expands to either ``mark'' or ``marks'', but that
% conflicts with some package or other.  Thus, we'll implement
% \marksnotpoints using the \pointpoints command instead:
\newcommand\marksnotpoints{\pointpoints{mark}{marks}}


% \@marginpointname is used in place of \@pointname if any of
% \@pointsinmargin, \@pointsinrightmargin, and \@pointsdropped are
% true:
\def\marginpointname#1{\gdef\@marginpointname{#1}}
\marginpointname{}


% 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
% question (or part, or subpart) won't get error messages.
% We use \if@printtotalpoints as a flag to signal that we are counting
% points, so that we will know to print the total on the screen (and
% in the log file).  We use this separate flag so that the user can
% use both \addpoints and \noaddpoints to count some points and not
% others, but still have the total printed when we finish the file no
% matter what the state of \if@addpoints.
\newif\if@addpoints
\newif\if@printtotalpoints
\def\addpoints{\global\@addpointstrue\global\@printtotalpointstrue}
\def\noaddpoints{\global\@addpointsfalse}
\@addpointsfalse
\@printtotalpointsfalse

%--------------------------------------------------------------------
%                   choices (for multiple choice)


\renewcommand\thechoice{\Alph{choice}}
\newcommand\choicelabel{\thechoice.}

% Added 22 April 2004: Increased the \leftmargin by 2.5em,
% so the choices will be visibly indented.
\newenvironment{choices}%
  {\list{\choicelabel}%
     {\usecounter{choice}\def\makelabel##1{\hss\llap{##1}}%
       \settowidth{\leftmargin}{W.\hskip\labelsep\hskip 2.5em}%
       \let\choice=\item
       \labelwidth\leftmargin\advance\labelwidth-\labelsep
       \topsep=0pt
       \partopsep=0pt
     }%
  }%
  {\endlist}

\newenvironment{oneparchoices}%
  {%
    \setcounter{choice}{0}%
    \def\choice{%
                 \refstepcounter{choice}%
                 \ifnum\value{choice}>1
                   \penalty -50\hskip 1em plus 1em\relax
                 \fi
                 \choicelabel\nobreak\enskip
               }%
    \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
  }%
  {}


%--------------------------------------------------------------------
%             Answer Lines (for short answer questions)

% Note: \ques@ref is also used in \item@points@pageinfo

\def\ques@ref{question}
\def\part@ref{part}
\def\subpart@ref{subpart}
\def\subsubpart@ref{subsubpart}

\newlength\answerlinelength
\newlength\answerskip
\setlength\answerlinelength{1in}
\setlength\answerskip{2ex}

\def\answerline{%
  \ifx\@queslevel\ques@ref
    \let\ans@l=\questionlabel
  \else
    \ifx\@queslevel\part@ref
      \let\ans@l=\partlabel
    \else
      \ifx\@queslevel\subpart@ref
        \let\ans@l=\subpartlabel
      \else
        \ifx\@queslevel\subsubpart@ref
          \let\ans@l=\subsubpartlabel
        \else
          % Oops; no question level defined.
          % We must be outide of the questions environment.
          % Just leave out the label, I guess:
          \def\ans@l{}%
        \fi
      \fi
    \fi
  \fi
  \par \nobreak \vskip \answerskip
  \hfill \ans@l~\hbox to \answerlinelength{\hrulefill}%
  \par
}

%--------------------------------------------------------------------
%                            \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, the extend from the current
% left margin (which depends on whether we're in a quesiton, parts,
% subpart, or subsubpart) to the right margin.
%
% The distance between the lines is \linefillheight, whose default value
% is set with the command
%
% \setlength\linefillheight{.25in}
%
% This value can be changed by giving a new \setlength command.
%
% The thickness of the lines is \linefillthickness, whose default value
% is set with the command
%
% \setlength\linefillthickness{.2pt}
%
% This value can be changed by giving a new \setlength command.


\newlength\linefillheight
\newlength\linefillthickness
\setlength\linefillheight{.25in}
\setlength\linefillthickness{0.1pt}

\newcommand\linefill{\leavevmode
    \leaders\hrule height \linefillthickness \hfill\kern\z@}


\def\fillwithlines#1{%
  \begingroup
  \ifhmode
    \par
  \fi
  \hrule height \z@
  \nobreak
  \setbox0=\hbox to \hsize{\hskip \@totalleftmargin
          \vrule height \linefillheight depth \z@ width \z@
          \linefill}%
  % 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:
  \cleaders \copy0 \vskip #1 \hbox{}%
  \endgroup
}


%--------------------------------------------------------------------
%                      \uplevel and \fullwidth:

% \uplevel is used to print text at the indentation level of the 
% enclosing environment.  For example, to precede a question with
% directions about how that question should be answered, you would
% say \uplevel{Answer this question correctly.}
% 
% \fullwidth is similar, but uses the full page of text on the page.

\long\def\uplevel#1{%
  \par\bigskip
  \vbox{%
    % We set \leftskip to provide the correct left margin for whatever
    % text is in the argument of the \uplevel command:
    \leftskip=\@totalleftmargin
    \advance\leftskip-\leftmargin
    % 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
    #1%
  }% vbox
  \nobreak
}

\long\def\fullwidth#1{%
  \par\bigskip
  \vbox{%
    \leftskip=0pt \rightskip=0pt
    \advance\linewidth\@totalleftmargin
    \@totalleftmargin=0pt
    #1%
  }% vbox
  \nobreak
}


%--------------------------------------------------------------------
%--------------------------------------------------------------------
%
%                        ********************
%                        ** GRADING TABLES **
%                        ********************



\newcounter{@iterator}
\newlength\@cellwidth

\def\cellwidth#1{\@cellwidth=#1}
\def\gradetablestretch#1{\def\@gtblstretch{#1}}

% 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\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}}

% Initialize:
\cellwidth{2em}
\gradetablestretch{1.5}
\hpword{Points:}
\hsword{Score:}
\htword{Total}
\vpword{Points}
\vsword{Score}
\vtword{Total:}

% For tables indexed by question number:
\vqword{Question}
\hqword{Question:}

% For tables indexed by page number:
\vpgword{Page}
\hpgword{Page:}



% The only command here accessible to the user is \gradetable.
% The possibilities are

%   \gradetable[v][questions]
%   \gradetable[v][pages]
%   \gradetable[h][questions]
%   \gradetable[h][pages]

% If one or both optional arguments are omitted, the defaults are `[v]'
% and `[questions]'.

\def\gradetable{%
  % If the user doesn't include the optional argument
  % choosing between vertical and horizontal,
  % we give them vertical:
  \@ifnextchar[{\i@gtable}{\i@gtable[v]}%
}
\def\i@gtable[#1]{%
  % If the user doesn't include the optional argument
  % choosing between questions and pages,
  % we give them questions:
  \@ifnextchar[{\ii@gtable{#1}}{\ii@gtable{#1}[questions]}%
}
\def\ii@gtable#1[#2]{%
  \if@addpoints
    \@ifundefined{exam@numpoints}%
      {\ClassWarning{exam}%
        {%
          You must run LaTeX again to produce the grade table.
            \MessageBreak
        }%
        \fbox{Run \LaTeX{} again to produce the table}%
      }%
      {\do@gtable{#1}{#2}}%
  \else
    \ClassError{exam}{%
      You must give the command \protect\addpoints\MessageBreak
      \space\space in order to use the command \protect\gradetable
      \MessageBreak
      }{%
      If you don't give the command \protect\addpoints\MessageBreak
      \space\space then we're not keeping track of point values.
      \MessageBreak
      }%
  \fi
}
\def\@questionsref{questions}
\def\@pagesref{pages}
\def\do@gtable#1#2{%
  \begingroup % avoid trouble from using \@temp
    \def\@temp{#2}%
    \ifx\@temp\@questionsref
      \@grdtblquestions{#1}%
    \else
      \ifx\@temp\@pagesref
        \@grdtblpages{#1}%
      \else
        \ClassError{exam}{%
          The second optional argument to \protect\gradetable \MessageBreak
          \space \space must be either `questions' or `pages'\MessageBreak
        }{%
          Grade tables can be indexed by questions or pages;\MessageBreak
          \space\space for others, you're on your own.\MessageBreak
        }%
        \fbox{Error: Grade table: Invalid second optional argument `#1'.}%
      \fi
    \fi
  \endgroup
}

%--------------------------------------------------------------------
%--------------------------------------------------------------------
% Grading tables indexed by question numbers:

\def\@grdtblquestions#1{%
  \if v#1%
    \@vgrdtblquestions
  \else
    \if h#1%
      \@hgrdtblquestions
    \else
      \ClassError{exam}{%
        The first optional argument to \protect\gradetable \MessageBreak
        \space \space must be either `h' or `v'\MessageBreak
      }{%
        Grade tables can be either horizontal or vertical;\MessageBreak
        \space\space no diagonals allowed.\MessageBreak
      }%
      \fbox{Error: Grade table: Invalid first optional argument `#1'.}%
    \fi
  \fi
}

%--------------------------------------------------------------------
% Vertical, indexed by question numbers:

\def\@vgrdtblquestions{%
  \begingroup
    % Save the current value of question in @iterator, so that
    % we cna restore it after doing the table:
    \setcounter{@iterator}{\arabic{question}}%
    \renewcommand\arraystretch{\@gtblstretch}%
    \begin{tabular}{|c|c|c|}
      \hline
      {\@vqword}& {\@vpword}& {\@vsword}\\
      \hline
      \setcounter{question}{0}\do@vloop
      {\@vtword}& \numpoints&\hbox to \@cellwidth{\hfill}\\
      \hline
    \end{tabular}%
    % Restore the saved value of question:
    \setcounter{question}{\arabic{@iterator}}%
  \endgroup
}
\def\do@vloop{%
  \addtocounter{question}{1}%
  \thequestion & \pointsofquestion{\arabic{question}}&\\
  \hline
  \ifnum \arabic{question} < \numquestions\relax
    \let\next@vloop=\do@vloop
  \else
    \let\next@vloop=\relax
  \fi
  \next@vloop
}

%--------------------------------------------------------------------
% Horizontal, indexed by question numbers:

\def\@hgrdtblquestions{%
  \begingroup
  